Beispiel #1
0
// Issue 1191: ConEmu was launched instead of explorer from taskbar pinned library icon
void CSetPgIntegr::UnregisterShellInvalids()
{
	HKEY hkDir;

	if (0 == RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Classes\\LibraryFolder\\shell", 0, KEY_READ, &hkDir))
	{
		int iOthers = 0;
		MArray<wchar_t*> lsNames;

		for (DWORD i = 0; i < 512; i++)
		{
			wchar_t szName[MAX_PATH+32] = {};
			wchar_t szCmd[MAX_PATH*4];
			DWORD cchMax = countof(szName) - 32;
			if (0 != RegEnumKeyEx(hkDir, i, szName, &cchMax, NULL, NULL, NULL, NULL))
				break;
			wchar_t* pszSlash = szName + _tcslen(szName);
			wcscat_c(szName, L"\\command");
			HKEY hkCmd = NULL;
			if (0 == RegOpenKeyEx(hkDir, szName, 0, KEY_READ, &hkCmd))
			{
				DWORD cbMax = sizeof(szCmd)-2;
				if (0 == RegQueryValueEx(hkCmd, NULL, NULL, NULL, (LPBYTE)szCmd, &cbMax))
				{
					szCmd[cbMax>>1] = 0;
					*pszSlash = 0;
					//LPCWSTR pszInside = StrStrI(szCmd, L"-inside");
					LPCWSTR pszConEmu = StrStrI(szCmd, L"conemu");
					if (pszConEmu)
						lsNames.push_back(lstrdup(szName));
					else
						iOthers++;
				}
				RegCloseKey(hkCmd);
			}
Beispiel #2
0
static INT_PTR WLoadWindows(MArray<WindowInfo>& wCurrent, int windowCount)
{
	WindowInfo WInfo;
	wCurrent.clear();

	// 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);
		}
	}

	return wCurrent.size();
}
Beispiel #3
0
MArray<CDpiForDialog::DlgItem>* CDpiForDialog::LoadDialogItems(HWND hDlg)
{
	MArray<DlgItem>* p = new MArray<DlgItem>();
	DlgItem i = {hDlg};
	if (!GetWindowRect(hDlg, &i.r))
	{
		delete p;
		return NULL;
	}
	OffsetRect(&i.r, -i.r.left, -i.r.top);
	p->push_back(i);

	i.h = NULL;
	while ((i.h = FindWindowEx(hDlg, i.h, NULL, NULL)) != NULL)
	{
		if (GetWindowRect(i.h, &i.r) && MapWindowPoints(NULL, hDlg, (LPPOINT)&i.r, 2))
		{
			#ifdef _DEBUG
			DWORD_PTR ID = GetWindowLong(i.h, GWL_ID);
			if (ID == cbExtendFonts)
			{
				RECT rcMargin = {};
				if (Button_GetTextMargin(i.h, &rcMargin))
				{
					wchar_t szLog[100];
					_wsprintf(szLog, SKIPCOUNT(szLog) L"CheckBox Rect={%i,%i}-{%i,%i} Margin={%i,%i}-{%i,%i}",
						LOGRECTCOORDS(i.r), LOGRECTCOORDS(rcMargin));
					LogString(szLog);
				}
			}
			#endif

			p->push_back(i);
		}
	}

	return p;
}
Beispiel #4
0
MArray<CDpiForDialog::DlgItem>* CDpiForDialog::LoadDialogItems(HWND hDlg)
{
	MArray<DlgItem>* p = new MArray<DlgItem>();
	DlgItem i = {hDlg};
	if (!GetWindowRect(hDlg, &i.r))
	{
		delete p;
		return NULL;
	}
	OffsetRect(&i.r, -i.r.left, -i.r.top);
	p->push_back(i);

	i.h = NULL;
	while ((i.h = FindWindowEx(hDlg, i.h, NULL, NULL)) != NULL)
	{
		if (GetWindowRect(i.h, &i.r) && MapWindowPoints(NULL, hDlg, (LPPOINT)&i.r, 2))
		{
			p->push_back(i);
		}
	}

	return p;
}
Beispiel #5
0
size_t CConEmuCtrl::GetOpenedPanels(wchar_t*& pszDirs, int& iCount, int& iCurrent)
{
	CmdArg szActiveDir, szPassive;
	CVConGuard VCon;
	MArray<wchar_t*> Dirs;
	size_t cchAllLen = 1;
	iCount = iCurrent = 0;

	for (int V = 0; CVConGroup::GetVCon(V, &VCon, true); V++)
	{
		VCon->RCon()->GetPanelDirs(szActiveDir, szPassive);
		if (VCon->isActive(false))
			iCurrent = iCount;
		LPCWSTR psz[] = {szActiveDir.ms_Arg, szPassive.ms_Arg};
		for (int i = 0; i <= 1; i++)
		{
			if (psz[i] && psz[i][0])
			{
				int iLen = lstrlen(psz[i]);
				cchAllLen += (iLen+1);
				Dirs.push_back(lstrdup(psz[i]));
				iCount++;
			}
		}
	}

	_ASSERTE(pszDirs == NULL);
	pszDirs = (wchar_t*)malloc(cchAllLen*sizeof(*pszDirs));
	if (!pszDirs)
		return 0;

	wchar_t* psz = pszDirs;
	for (int i = 0; i < Dirs.size(); i++)
	{
		wchar_t* p = Dirs[i];
		_wcscpy_c(psz, cchAllLen, p);
		psz += lstrlen(psz)+1;
		free(p);
	}

	return cchAllLen;
}
Beispiel #6
0
	// Parse switches stored in gpConEmu during initialization (AppendExtraArgs)
	// These are, for example, `-lngfile`, `-fontdir`, and so on.
	void ParseStdSwitches()
	{
		_ASSERTE(stdSwitches.empty());

		CEStr szArg, szNext, lsExta;
		LPCWSTR psz, pszExtraArgs;

		pszExtraArgs = gpConEmu->MakeConEmuStartArgs(lsExta);
		psz = pszExtraArgs;
		while (psz && *psz)
		{
			Switch* ps = GetNextPair(psz);
			if (!ps)
			{
				continue;
			}
			if (IsIgnored(ps, GetSkipSwitches()))
			{
				SafeDelete(ps);
				continue;
			}
			stdSwitches.push_back(ps);
		}
	};
Beispiel #7
0
CAttachDlg::AttachMacroRet CAttachDlg::AttachFromMacro(DWORD anPID, bool abAlternative)
{
	MArray<AttachParm> Parms;

	HWND hFind = NULL;
	CProcessData ProcessData;

	while ((hFind = FindWindowEx(NULL, hFind, NULL, NULL)) != NULL)
	{
		if (!IsWindowVisible(hFind))
			continue;

		AttachWndInfo Info = {};
		if (!GetWindowThreadProcessId(hFind, &Info.nPID) || (Info.nPID != anPID))
			continue;

		if (!CanAttachWindow(hFind, 0, &ProcessData, Info))
			continue;

		AttachParm p = {};
		p.hAttachWnd = hFind;
		p.nPID = Info.nPID;
		p.nBits = Info.nImageBits;
		if (lstrcmp(Info.szType, szTypeCon) == 0)
			p.nType = apt_Console;
		else if (lstrcmp(Info.szType, szTypeGui) == 0)
			p.nType = apt_Gui;
		else
			continue;
		p.bAlternativeMode = abAlternative;
		Parms.push_back(p);
	}

	if (Parms.empty())
		return amr_WindowNotFound;
	if (Parms.size() > 1)
		return amr_Ambiguous;

	AttachParm Null = {};
	Parms.push_back(Null);

	// Работу делаем в фоновом потоке, чтобы не блокировать главный
	// (к окну ConEmu должна подцепиться новая вкладка)
	AttachParm* pParm = Parms.detach();
	if (!pParm)
		return amr_Unexpected;

	DWORD nTID = 0;
	HANDLE hThread = apiCreateThread((LPTHREAD_START_ROUTINE)StartAttachThread, pParm, &nTID, "CAttachDlg::StartAttachThread#2");
	if (!hThread)
	{
		//DWORD dwErr = GetLastError();
		//_wsprintf(szItem, SKIPLEN(countof(szItem)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId());
		//DisplayLastError(L"Can't start attach thread", dwErr, 0, szItem);
		return amr_Unexpected;
	}
	// We don't need this handle
	CloseHandle(hThread);

	return amr_Success;
}
Beispiel #8
0
bool CAttachDlg::OnStartAttach()
{
	bool lbRc = false;
	// Тут нужно получить инфу из списка и дернуть собственно аттач
	wchar_t szItem[128] = {};
	//DWORD nPID = 0, nBits = WIN3264TEST(32,64);
	//AttachProcessType nType = apt_Unknown;
	wchar_t *psz;
	int iSel, iCur;
	DWORD nTID;
	HANDLE hThread = NULL;
	AttachParm *pParm = NULL;
	MArray<AttachParm> Parms;
	//HWND hAttachWnd = NULL;

	ShowWindow(mh_Dlg, SW_HIDE);

	BOOL bAlternativeMode = (IsDlgButtonChecked(mh_Dlg, IDC_ATTACH_ALT) != 0);

	iSel = ListView_GetNextItem(mh_List, -1, LVNI_SELECTED);
	while (iSel >= 0)
	{
		iCur = iSel;
		iSel = ListView_GetNextItem(mh_List, iCur, LVNI_SELECTED);

		AttachParm L = {NULL, 0, WIN3264TEST(32,64), apt_Unknown, bAlternativeMode};

		ListView_GetItemText(mh_List, iCur, alc_PID, szItem, countof(szItem)-1);
		L.nPID = wcstoul(szItem, &psz, 10);
		if (L.nPID)
		{
			psz = wcschr(szItem, L'[');
			if (!psz)
			{
				_ASSERTE(FALSE && "Process bitness was not detected?");
			}
			else
			{
				L.nBits = wcstoul(psz+1, &psz, 10);
			}
		}
		ListView_GetItemText(mh_List, iCur, alc_Type, szItem, countof(szItem));
		if (lstrcmp(szItem, szTypeCon) == 0)
			L.nType = apt_Console;
		else if (lstrcmp(szItem, szTypeGui) == 0)
			L.nType = apt_Gui;

		ListView_GetItemText(mh_List, iCur, alc_HWND, szItem, countof(szItem));
		L.hAttachWnd = (szItem[0]==L'0' && szItem[1]==L'x') ? (HWND)(DWORD_PTR)wcstoul(szItem+2, &psz, 16) : NULL;

		if (!L.nPID || !L.nBits || !L.nType || !L.hAttachWnd)
		{
			MBoxAssert(L.nPID && L.nBits && L.nType && L.hAttachWnd);
			goto wrap;
		}

		Parms.push_back(L);
	}

	if (Parms.empty())
	{
		goto wrap;
	}
	else
	{
		AttachParm N = {NULL};
		Parms.push_back(N);
	}

	//// Чтобы клик от мышки в консоль не провалился
	//WARNING("Клик от мышки в консоль проваливается");
	//gpConEmu->mouse.nSkipEvents[0] = WM_LBUTTONUP;
	//gpConEmu->mouse.nSkipEvents[1] = 0;
	//gpConEmu->mouse.nReplaceDblClk = 0;

	// Все, диалог закрываем, чтобы не мешался
	Close();

	// Работу делаем в фоновом потоке, чтобы не блокировать главный
	// (к окну ConEmu должна подцепиться новая вкладка)
	pParm = Parms.detach();
	if (!pParm)
	{
		_wsprintf(szItem, SKIPLEN(countof(szItem)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId());
		DisplayLastError(L"Parms.detach() failed", -1, 0, szItem);
		goto wrap;
	}
	else
	{
		hThread = apiCreateThread((LPTHREAD_START_ROUTINE)StartAttachThread, pParm, &nTID, "CAttachDlg::StartAttachThread#1");
		if (!hThread)
		{
			DWORD dwErr = GetLastError();
			_wsprintf(szItem, SKIPLEN(countof(szItem)) L"ConEmu Attach, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId());
			DisplayLastError(L"Can't start attach thread", dwErr, 0, szItem);
		}
		else
			lbRc = true;
	}
wrap:
	// We don't need this handle
	if (hThread)
		CloseHandle(hThread);

	return lbRc;
}
Beispiel #9
0
// Supports MultiLine and SingleLine strings
// If there were no key_value or key_value_type is unexpected, DOESN'T touch *value
bool SettingsXML::Load(const wchar_t *regName, wchar_t **value) noexcept
{
	bool lbRc = false;
	SettingsXML::node *pChild = NULL;
	SettingsXML::node *pNode = NULL;
	const char *sType;
	size_t cchMax = 0;
	CEStrA data;
	LPCSTR pszData = nullptr;

	try
	{
		if (mp_Key)
			pChild = FindItem(mp_Key, L"value", regName, false);

		if (!pChild)
			return false;

		sType = GetAttr(pChild, "type");

		if (0 == _strcmpi(sType, "multi"))
		{
			//<value name="CmdLineHistory" type="multi">
			//	<line data="C:\Far\Far.exe"/>
			//	<line data="cmd"/>
			//</value>
			struct line_info { const char* str; size_t cchSize; };
			MArray<line_info> lines;

			for (pNode = pChild->first_node("line"); pNode; pNode = pNode->next_sibling("line"))
			{
				const char* lstr = GetAttr(pNode, "data");
				if (!lstr || !*lstr)
					lstr = " "; // Because of ASCIIZZ we must be sure there were no zero-length string
				size_t cchSize = strlen(lstr) + 1;
				cchMax += cchSize;
				lines.push_back({lstr, cchSize});
			}

			if (!lines.empty())
			{
				// ASCIIZ,ASCIIZ,...,ASCIIZ buffer
				if (char* buffer = data.getbuffer(cchMax))
				{
					for (INT_PTR i = 0; i < lines.size(); ++i)
					{
						const auto& line = lines[i];
						strcpy_s(buffer, line.cchSize, line.str);
						buffer += line.cchSize;
					}
					_ASSERTE(cchMax>=1 && data.ms_Val[cchMax-1]==0);
					pszData = data.c_str();
				}
			}
		}
		else if (0 == _strcmpi(sType, "string"))
		{
			pszData = GetAttr(pChild, "data");
			cchMax = pszData ? (strlen(pszData) + 1) : 0; // ASCIIZ
		}
		else
		{
			// We don't care about other data types, only strings here
		}

		// Data exist?
		if (pszData)
		{
			int cvt_size = MultiByteToWideChar(CP_UTF8, 0, pszData, cchMax, nullptr, 0);
			if (cvt_size > 0)
			{
				// Allocate data for ASCIIZZ (additional zero at the end)
				if ((*value = (wchar_t*)realloc(*value, (cvt_size + 1) * sizeof(**value))))
				{
					int cvt = MultiByteToWideChar(CP_UTF8, 0, pszData, cchMax, *value, cvt_size+1);
					_ASSERTE(cvt == cvt_size);
					if (cvt > 0)
					{
						_ASSERTE((*value)[cvt-1] == 0);
						(*value)[cvt] = 0; // ASCIIZZ
						lbRc = true;
					}
				}
			}
		}
	}
	catch (rapidxml::parse_error&)
	{
		// #XML Log error
		lbRc = false;
	}
	return lbRc;
}
Beispiel #10
0
bool CDpiForDialog::SetDialogDPI(const DpiValue& newDpi, LPRECT lprcSuggested /*= NULL*/)
{
	if (mn_InSet > 0)
		return false;

	if (newDpi.Ydpi <= 0 || newDpi.Xdpi <= 0)
		return false;
	if (m_CurDpi.Ydpi <= 0 || m_CurDpi.Xdpi <= 0)
		return false;
	if (m_CurDpi.Equals(newDpi))
		return false;

	bool bRc = false;
	MArray<DlgItem>* p = NULL;
	DpiValue curDpi(m_CurDpi);
	HFONT hf = NULL;

	wchar_t szClass[100];

	#ifdef _DEBUG
	LOGFONT lftest1 = {}, lftest2 = {};
	HFONT hftest;
	int itest1, itest2;
	#endif

	// To avoid several nested passes
	InterlockedIncrement(&mn_InSet);
	m_CurDpi.SetDpi(newDpi);

	_wsprintf(szClass, SKIPLEN(countof(szClass)) L"CDpiForDialog::SetDialogDPI(x%08X, {%i,%i})", (DWORD)(DWORD_PTR)mh_Dlg, newDpi.Xdpi, newDpi.Ydpi);
	LogString(szClass);

	// Eval
	mn_CurFontHeight = (mn_InitFontHeight * newDpi.Ydpi / 96);
	mlf_CurFont = mlf_InitFont;
	mlf_CurFont.lfHeight = mn_CurFontHeight;
	mlf_CurFont.lfWidth = 0; // Font mapper fault

	if (mn_CurFontHeight == 0 || mn_InitFontHeight == 0)
		goto wrap;


	if (!m_Items.Get(newDpi.Ydpi, &p))
	{
		MArray<DlgItem>* pOrig = NULL;
		int iOrigDpi = 0;
		if (!m_Items.GetNext(NULL, &iOrigDpi, &pOrig) || !pOrig || (iOrigDpi <= 0))
			goto wrap;
		int iNewDpi = newDpi.Ydpi;

		p = new MArray<DlgItem>();

		DWORD dwStyle = GetWindowLong(mh_Dlg, GWL_STYLE);
		DWORD dwStyleEx = GetWindowLong(mh_Dlg, GWL_EXSTYLE);

		RECT rcClient = {}, rcCurWnd = {};
		if (!GetClientRect(mh_Dlg, &rcClient) || !GetWindowRect(mh_Dlg, &rcCurWnd))
		{
			delete p;
			goto wrap;
		}

		_ASSERTE(rcClient.left==0 && rcClient.top==0);
		int calcDlgWidth = rcClient.right * newDpi.Xdpi / curDpi.Xdpi;
		int calcDlgHeight = rcClient.bottom * newDpi.Ydpi / curDpi.Ydpi;

		DlgItem i = {mh_Dlg};

		// Windows DWM manager do not resize NonClient areas of per-monitor dpi aware applications
		// So, we can not use AdjustWindowRectEx to determine full window rectangle
		// Just use current NonClient dimensions
		i.r.right = calcDlgWidth + ((rcCurWnd.right - rcCurWnd.left) - rcClient.right);
		i.r.bottom = calcDlgHeight + ((rcCurWnd.bottom - rcCurWnd.top) - rcClient.bottom);

		// .right and .bottom are width and height of the dialog
		_ASSERTE(i.r.left==0 && i.r.top==0);
		p->push_back(i);

		for (INT_PTR k = 1; k < pOrig->size(); k++)
		{
			const DlgItem& iOrig = (*pOrig)[k];
			i.h = iOrig.h;
			i.r.left = iOrig.r.left * iNewDpi / iOrigDpi;
			i.r.top = iOrig.r.top * iNewDpi / iOrigDpi;
			i.r.right = iOrig.r.right * iNewDpi / iOrigDpi;
			i.r.bottom = iOrig.r.bottom * iNewDpi / iOrigDpi;
			p->push_back(i);
		}

		m_Items.Set(iNewDpi, p);
	}

	hf = CreateFontIndirect(&mlf_CurFont);
	if (hf == NULL)
	{
		goto wrap;
	}

	for (INT_PTR k = p->size() - 1; k >= 0; k--)
	{
		const DlgItem& di = (*p)[k];
		GetClassName(di.h, szClass, countof(szClass));
		DWORD nCtrlID = GetWindowLong(di.h, GWL_ID);
		DWORD nStyles = GetWindowLong(di.h, GWL_STYLE);
		bool bResizeCombo = (lstrcmpi(szClass, L"ComboBox") == 0);
		int iComboFieldHeight = 0, iComboWasHeight = 0;
		if (bResizeCombo && (nStyles & CBS_OWNERDRAWFIXED))
		{
			RECT rcCur = {}; GetWindowRect(di.h, &rcCur);
			iComboWasHeight = (rcCur.bottom - rcCur.top);
			LONG_PTR lFieldHeight = SendMessage(di.h, CB_GETITEMHEIGHT, -1, 0);
			if (lFieldHeight < iComboWasHeight)
			{
				iComboFieldHeight = lFieldHeight;
			}
		}

		int newW = di.r.right - di.r.left;
		int newH = di.r.bottom - di.r.top;

		MoveWindow(di.h, di.r.left, di.r.top, newW, newH, FALSE);
		SendMessage(di.h, WM_SETFONT, (WPARAM)hf, FALSE/*immediately*/);
		if (bResizeCombo)
		{
			if ((nStyles & CBS_OWNERDRAWFIXED) && (iComboWasHeight > 0) && (iComboFieldHeight > 0))
				SendMessage(di.h, CB_SETITEMHEIGHT, -1, newH*iComboFieldHeight/iComboWasHeight);
			SendMessage(di.h, CB_SETEDITSEL, 0, MAKELPARAM(-1,0));
		}
		EditIconHint_ResChanged(di.h);
		InvalidateRect(di.h, NULL, TRUE);
		#ifdef _DEBUG
		itest1 = GetObject(hf, sizeof(lftest1), &lftest1);
		hftest = (HFONT)SendMessage(di.h, WM_GETFONT, 0, 0);
		itest2 = GetObject(hftest, sizeof(lftest2), &lftest2);
		#endif
	}

	if (p->size() > 0)
	{
		const DlgItem& di = (*p)[0];
		SendMessage(mh_Dlg, WM_SETFONT, (WPARAM)hf, FALSE);
		DWORD nWndFlags = SWP_NOZORDER | (lprcSuggested ? 0 : SWP_NOMOVE);
		SetWindowPos(mh_Dlg, NULL,
			lprcSuggested ? lprcSuggested->left : 0, lprcSuggested ? lprcSuggested->top : 0,
			di.r.right, di.r.bottom,
			nWndFlags);
		RECT rc = {}; GetClientRect(mh_Dlg, &rc);
		InvalidateRect(mh_Dlg, NULL, TRUE);
		RedrawWindow(mh_Dlg, &rc, NULL, /*RDW_ERASE|*/RDW_ALLCHILDREN/*|RDW_INVALIDATE|RDW_UPDATENOW|RDW_INTERNALPAINT*/);
	}

	if (mh_CurFont != hf)
		DeleteObject(mh_CurFont);
	mh_CurFont = hf;

	bRc = true;
wrap:
	InterlockedDecrement(&mn_InSet);
	return bRc;
}
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;
}
Beispiel #12
0
bool CDpiForDialog::SetDialogDPI(const DpiValue& newDpi, LPRECT lprcSuggested /*= NULL*/)
{
	wchar_t szLog[160];
	RECT rcClient = {}, rcCurWnd = {};

	#ifdef _DEBUG
	if (gbSkipSetDialogDPI)
	{
		GetClientRect(mh_Dlg, &rcClient); GetWindowRect(mh_Dlg, &rcCurWnd);
		_wsprintf(szLog, SKIPCOUNT(szLog) L"SKIPPED CDpiForDialog::SetDialogDPI x%08X, OldDpi={%i,%i}, NewDpi={%i,%i}, CurSize={%i,%i}, CurClient={%i,%i}",
			(DWORD)(DWORD_PTR)mh_Dlg, m_CurDpi.Xdpi, m_CurDpi.Ydpi, newDpi.Xdpi, newDpi.Ydpi,
			(rcCurWnd.right - rcCurWnd.left), (rcCurWnd.bottom - rcCurWnd.top),
			(rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top));
		LogString(szLog);
		return false;
	}
	#endif

	if (mn_InSet > 0)
		return false;

	if (newDpi.Ydpi <= 0 || newDpi.Xdpi <= 0)
		return false;
	if (m_CurDpi.Ydpi <= 0 || m_CurDpi.Xdpi <= 0)
		return false;

	// When overall DPI is very large but new dpi is small
	// (example: primary mon is 192 high-dpi, new mon is 96 dpi)
	// Windows goes crazy... HUGE caption, scrollbars, checkbox marks and so on...
	// So huge difference makes dialog unattractive, let's try to smooth that
	DpiValue setDpi(newDpi);
	if (m_InitDpi.Ydpi > MulDiv(setDpi.Ydpi, 144, 96))
	{
		// Increase DPI one step up
		setDpi.Ydpi = MulDiv(setDpi.Ydpi, 120, 96);
		setDpi.Xdpi = MulDiv(setDpi.Xdpi, 120, 96);
		// Log it
		_wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::SetDialogDPI x%08X forces larger dpi value from {%i,%i} to {%i,%i}",
			(DWORD)(DWORD_PTR)mh_Dlg, newDpi.Xdpi, newDpi.Ydpi, setDpi.Xdpi, setDpi.Ydpi);
		LogString(szLog);
	}

	if (m_CurDpi.Equals(setDpi))
		return false;

	bool bRc = false;
	MArray<DlgItem>* p = NULL;
	DpiValue curDpi(m_CurDpi);
	HFONT hf = NULL;

	wchar_t szClass[100];

	#ifdef _DEBUG
	LOGFONT lftest1 = {}, lftest2 = {};
	HFONT hftest;
	int itest1, itest2;
	#endif

	// To avoid several nested passes
	InterlockedIncrement(&mn_InSet);
	m_CurDpi.SetDpi(setDpi);

	// Eval
	mn_CurFontHeight = GetFontSizeForDpi(NULL, m_CurDpi.Ydpi);
	//(m_CurDpi.Ydpi && m_InitDpi.Ydpi) ? (mn_InitFontHeight * m_CurDpi.Ydpi / m_InitDpi.Ydpi) : -11;
	mlf_CurFont = mlf_InitFont;
	mlf_CurFont.lfHeight = mn_CurFontHeight;
	mlf_CurFont.lfWidth = 0; // Font mapper fault

	if (mn_CurFontHeight == 0)
		goto wrap;


	if (!m_Items.Get(m_CurDpi.Ydpi, &p))
	{
		MArray<DlgItem>* pOrig = NULL;
		int iOrigDpi = 0;
		if (!m_Items.GetNext(NULL, &iOrigDpi, &pOrig) || !pOrig || (iOrigDpi <= 0))
			goto wrap;
		int iNewDpi = m_CurDpi.Ydpi;

		p = new MArray<DlgItem>();

		DWORD dwStyle = GetWindowLong(mh_Dlg, GWL_STYLE);
		DWORD dwStyleEx = GetWindowLong(mh_Dlg, GWL_EXSTYLE);

		if (!GetClientRect(mh_Dlg, &rcClient) || !GetWindowRect(mh_Dlg, &rcCurWnd))
		{
			delete p;
			goto wrap;
		}

		_ASSERTE(rcClient.left==0 && rcClient.top==0);
		int calcDlgWidth = rcClient.right * m_CurDpi.Xdpi / curDpi.Xdpi;
		int calcDlgHeight = rcClient.bottom * m_CurDpi.Ydpi / curDpi.Ydpi;

		DlgItem i = {mh_Dlg};

		// Windows DWM manager do not resize NonClient areas of per-monitor dpi aware applications
		// So, we can not use AdjustWindowRectEx to determine full window rectangle
		// Just use current NonClient dimensions
		i.r.right = calcDlgWidth + ((rcCurWnd.right - rcCurWnd.left) - rcClient.right);
		i.r.bottom = calcDlgHeight + ((rcCurWnd.bottom - rcCurWnd.top) - rcClient.bottom);

		// .right and .bottom are width and height of the dialog
		_ASSERTE(i.r.left==0 && i.r.top==0);
		p->push_back(i);

		for (INT_PTR k = 1; k < pOrig->size(); k++)
		{
			const DlgItem& iOrig = (*pOrig)[k];
			i.h = iOrig.h;
			i.r.left = iOrig.r.left * iNewDpi / iOrigDpi;
			i.r.top = iOrig.r.top * iNewDpi / iOrigDpi;
			i.r.right = iOrig.r.right * iNewDpi / iOrigDpi;
			i.r.bottom = iOrig.r.bottom * iNewDpi / iOrigDpi;
			p->push_back(i);
		}

		m_Items.Set(iNewDpi, p);
	}

	if (p->size() <= 0)
	{
		_ASSERTE(FALSE && "No elements");
		goto wrap;
	}
	else
	{
		const DlgItem& di = (*p)[0];
		_wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::SetDialogDPI x%08X, OldDpi={%i,%i}, NewDpi={%i,%i}, OldSize={%i,%i}, NewSize={%i,%i}, NewFont=%i",
			(DWORD)(DWORD_PTR)mh_Dlg, curDpi.Xdpi, curDpi.Ydpi, newDpi.Xdpi, newDpi.Ydpi,
			(rcCurWnd.right - rcCurWnd.left), (rcCurWnd.bottom - rcCurWnd.top), di.r.right, di.r.bottom,
			mlf_CurFont.lfHeight);
		LogString(szLog);
	}

	hf = CreateFontIndirect(&mlf_CurFont);
	if (hf == NULL)
	{
		goto wrap;
	}

	for (INT_PTR k = p->size() - 1; k >= 1; k--)
	{
		const DlgItem& di = (*p)[k];
		GetClassName(di.h, szClass, countof(szClass));
		DWORD nCtrlID = GetWindowLong(di.h, GWL_ID);
		DWORD nStyles = GetWindowLong(di.h, GWL_STYLE);
		bool bResizeCombo = (lstrcmpi(szClass, L"ComboBox") == 0);
		int iComboFieldHeight = 0, iComboWasHeight = 0;
		LONG_PTR lFieldHeight = 0, lNewHeight = 0;
		RECT rcCur = {};
		HWND hComboEdit = NULL;
		RECT rcEdit = {}, rcClient = {};

		if (bResizeCombo && (nStyles & CBS_OWNERDRAWFIXED))
		{
			GetWindowRect(di.h, &rcCur);
			hComboEdit = FindWindowEx(di.h, NULL, L"Edit", NULL);
			GetClientRect(di.h, &rcClient);
			GetClientRect(hComboEdit, &rcEdit);
			iComboWasHeight = (rcCur.bottom - rcCur.top);
			lFieldHeight = SendMessage(di.h, CB_GETITEMHEIGHT, -1, 0);
			if (lFieldHeight < iComboWasHeight)
			{
				iComboFieldHeight = lFieldHeight;
			}
		}

		int newW = di.r.right - di.r.left;
		int newH = di.r.bottom - di.r.top;

		MoveWindow(di.h, di.r.left, di.r.top, newW, newH, FALSE);
		SendMessage(di.h, WM_SETFONT, (WPARAM)hf, FALSE/*immediately*/);
		if (bResizeCombo)
		{
			if ((nStyles & CBS_OWNERDRAWFIXED) && (iComboWasHeight > 0) && (iComboFieldHeight > 0))
			{
				RECT rcEdit2 = {}, rcClient2 = {};
				GetClientRect(di.h, &rcClient2);
				GetClientRect(hComboEdit, &rcEdit2);
				lNewHeight = newH*iComboFieldHeight/iComboWasHeight;
				_wsprintf(szLog, SKIPCOUNT(szLog) L"CDpiForDialog::Combo height changed - OldHeight=%i, ItemHeight=%i, NewHeight=%i, NewItemHeight=%i",
					(rcCur.bottom - rcCur.top), lFieldHeight, newH, lNewHeight);
				LogString(szLog);
				SendMessage(di.h, CB_SETITEMHEIGHT, -1, lNewHeight);
			}
			SendMessage(di.h, CB_SETEDITSEL, 0, MAKELPARAM(-1,0));
		}
		EditIconHint_ResChanged(di.h);
		InvalidateRect(di.h, NULL, TRUE);
		#ifdef _DEBUG
		itest1 = GetObject(hf, sizeof(lftest1), &lftest1);
		hftest = (HFONT)SendMessage(di.h, WM_GETFONT, 0, 0);
		itest2 = GetObject(hftest, sizeof(lftest2), &lftest2);
		#endif
	}

	if (p->size() > 0)
	{
		const DlgItem& di = (*p)[0];
		SendMessage(mh_Dlg, WM_SETFONT, (WPARAM)hf, FALSE);
		DWORD nWndFlags = SWP_NOZORDER | (lprcSuggested ? 0 : SWP_NOMOVE);
		SetWindowPos(mh_Dlg, NULL,
			lprcSuggested ? lprcSuggested->left : 0, lprcSuggested ? lprcSuggested->top : 0,
			di.r.right, di.r.bottom,
			nWndFlags);
		RECT rc = {}; GetClientRect(mh_Dlg, &rc);
		InvalidateRect(mh_Dlg, NULL, TRUE);
		RedrawWindow(mh_Dlg, &rc, NULL, /*RDW_ERASE|*/RDW_ALLCHILDREN/*|RDW_INVALIDATE|RDW_UPDATENOW|RDW_INTERNALPAINT*/);
	}

	if (mh_CurFont != hf)
		DeleteObject(mh_CurFont);
	mh_CurFont = hf;

	bRc = true;
wrap:
	InterlockedDecrement(&mn_InSet);
	return bRc;
}
Beispiel #13
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();
	}
}
Beispiel #14
0
	// pszFull comes from registry's [HKCR\Directory\shell\...\command]
	// Example:
	//	"C:\Tools\ConEmu.exe" -inside -LoadCfgFile "C:\Tools\ConEmu.xml" -FontDir C:\Tools\ConEmu
	//			-lngfile C:\Tools\ConEmu\ConEmu.l10n -lng ru  -dir "%1" -run {cmd} -cur_console:n
	// Strip switches which match current instance startup arguments
	// No sense to show them (e.g. "-lng ru") in the Integration dialog page
	void StripDupSwitches(LPCWSTR pszFull)
	{
		bCmdList = false;
		szCmd = L"";
		szDirSync = L"";
		szConfig = L"";
		ReleaseVectors();

		CEStr szArg, szNext;
		LPCWSTR psz;
		Switch* ps = NULL;

		// First, parse our extra args (passed to current ConEmu.exe)
		ParseStdSwitches();

		// Now parse new switches (command from registry or from field on Integration page)
		// Drop `-dir "..."` (especially from registry) always!

		psz = pszFull;
		while (0 == NextArg(&psz, szArg))
		{
			if (!szArg.IsPossibleSwitch())
				continue;

			if (szArg.OneOfSwitches(L"-inside", L"-here"))
			{
				// Nop
			}
			else if (szArg.IsSwitch(L"-inside:")) // Both "-inside:" and "-inside=" notations are supported
			{
				szDirSync.Set(szArg.Mid(8)); // may be empty!
			}
			else if (szArg.IsSwitch(L"-config"))
			{
				if (0 != NextArg(&psz, szArg))
					break;
				szConfig.Set(szArg);
			}
			else if (szArg.IsSwitch(L"-dir"))
			{
				if (0 != NextArg(&psz, szArg))
					break;
				_ASSERTE(lstrcmpi(szArg, L"%1")==0);
			}
			else if (szArg.OneOfSwitches(L"-Single", L"-NoSingle", L"-ReUse"))
			{
				ps = new Switch(szArg.Detach(), NULL);
				ourSwitches.push_back(ps);
			}
			else if (szArg.OneOfSwitches(L"-run", L"-cmd", L"-runlist", L"-cmdlist"))
			{
				// FIN! LAST SWITCH!
				szCmd.Set(psz);
				bCmdList = szArg.OneOfSwitches(L"-runlist",L"-cmdlist");
				break;
			}
			else if (NULL != (ps = GetNextSwitch(psz, szArg)))
			{
				if (IsIgnored(ps, GetSkipSwitches())
					|| IsIgnored(ps, stdSwitches))
				{
					SafeDelete(ps);
				}
				else
				{
					ourSwitches.push_back(ps);
				}
			}
		}
	};