Example #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);
			}
Example #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();
}
Example #3
0
	void ReleaseVectors()
	{
		Switch* p;
		while (stdSwitches.pop_back(p))
			SafeDelete(p);
		while (ourSwitches.pop_back(p))
			SafeDelete(p);
	};
Example #4
0
VALUE OR_Matrix::to_ruby()
{
  Matrix matrix;
  MArray<double> values;
  double cell;
  int i, number_of_values;
  VALUE argv[2];
  
  matrix = octave_val.matrix_value();
  int number_of_rows = matrix.rows();
  int number_of_columns = matrix.columns();
  
  if ((number_of_rows == 0) && (number_of_columns == 0)) {
    return rb_ary_new2(0);
  } else if (number_of_columns == 1) {
    values = matrix.column(0);
  } else {
    argv[0] = INT2FIX(number_of_rows);
    argv[1] = INT2FIX(number_of_columns);
    ruby_val = rb_class_new_instance(2, argv, rb_path2class("Octave::Matrix"));
    
    int row_index, column_index = 0;
    VALUE cells, row;
    cells = rb_ary_new2(number_of_rows);
    for (row_index = 0; row_index < number_of_rows; row_index++) {
      row = rb_ary_new2(number_of_columns);
      values = matrix.row(row_index);
      
      for (column_index = 0; column_index < number_of_columns; column_index++) {
        cell = values(column_index);
        if (xisnan(cell) || octave_is_NA(cell)) {
          rb_ary_push(row, Qnil);
        } else {
          rb_ary_push(row, rb_float_new(cell));
        }
      }
      
      rb_ary_push(cells, row);
    }
    
    rb_iv_set(ruby_val, "@cells", cells);
    return ruby_val;
  }
  
  number_of_values = values.length();
  ruby_val = rb_ary_new2(number_of_values);
  for (i = 0; i < number_of_values; i++) {
    cell = values(i);
    if (xisnan(cell) || octave_is_NA(cell)) {
      rb_ary_push(ruby_val, Qnil);
    } else {
      rb_ary_push(ruby_val, rb_float_new(cell));
    }
  }
  
  return ruby_val;
}
Example #5
0
// Set resource item
bool CLngRc::SetResource(MArray<LngRcItem>& arr, int idx, LPCWSTR asValue, bool bLocalized)
{
	if (idx < 0)
	{
		_ASSERTE(idx >= 0);
		return false;
	}

	_ASSERTE(!bLocalized || (asValue && *asValue));

	if (idx >= arr.size())
	{
		LngRcItem dummy = {};
		arr.set_at(idx, dummy);
	}

	bool bOk = false;
	LngRcItem& item = arr[idx];

	// Caching: no resource was found for that id
	if (!asValue || !*asValue)
	{
		if (item.Str)
			item.Str[0] = 0;
		item.Processed = true;
		item.Localized = false;
		return true;
	}

	size_t iLen = wcslen(asValue);
	if (iLen >= (u16)-1)
	{
		// Too long string?
		_ASSERTE(iLen < (u16)-1);
	}
	else
	{
		if (item.Str && (item.MaxLen >= iLen))
		{
			_wcscpy_c(item.Str, item.MaxLen, asValue);
		}
		else
		{
			//TODO: thread-safe
			SafeFree(item.Str);
			item.MaxLen = iLen;
			item.Str = lstrdup(asValue);
		}
		bOk = (item.Str != NULL);
	}

	item.Processed = bOk;
	item.Localized = (bOk && bLocalized);

	return bOk;
}
Example #6
0
	// Create the command to show on the Integration settings page
	LPCWSTR CreateCommand(CEStr& rsReady)
	{
		rsReady = L"";

		for (INT_PTR i = 0; i < ourSwitches.size(); i++)
		{
			Switch* ps = ourSwitches[i];
			_ASSERTE(ps && !ps->szSwitch.IsEmpty());
			bool bOpt = !ps->szOpt.IsEmpty();
			bool bQuot = (bOpt && IsQuotationNeeded(ps->szOpt));
			lstrmerge(&rsReady.ms_Val,
				ps->szSwitch,
				bOpt ? L" " : NULL,
				bQuot ? L"\"" : NULL,
				bOpt ? ps->szOpt.c_str() : NULL,
				bQuot ? L"\" " : L" ");
		}

		if (!rsReady.IsEmpty() || bCmdList)
		{
			lstrmerge(&rsReady.ms_Val,
				bCmdList ? L"-runlist " : L"-run ", szCmd);
		}
		else
		{
			rsReady.Set(szCmd);
		}

		return rsReady.c_str(L"");
	};
Example #7
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;
}
Example #8
0
void CLngRc::Clean(MArray<CLngRc::LngRcItem>& arr)
{
	for (INT_PTR i = arr.size()-1; i >= 0; --i)
	{
		LngRcItem& l = arr[i];
		l.Processed = false;
		l.Localized = false;
		l.MaxLen = 0;
		SafeFree(l.Str);
	}
}
Example #9
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;
}
Example #10
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;
}
static INT_PTR WExists(const WindowInfo& C, const MArray<WindowInfo>& wList)
{
	for (INT_PTR j = 0; j < wList.size(); j++)
	{
		const WindowInfo& L = wList[j];
		if (L.Type != C.Type)
			continue;
		if ((L.Type != WTYPE_PANELS) && (L.Id != C.Id))
			continue;
		return j;
	}

	return -1;
}
Example #12
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);
		}
	};
Example #13
0
bool CLngRc::GetResource(MArray<LngRcItem>& arr, int idx, CEStr& lsText)
{
	bool bFound = false;

	if ((idx >= 0) && (idx < arr.size()))
	{
		const LngRcItem& item = arr[idx];

		if (item.Processed && (item.Str && *item.Str))
		{
			lsText.Set(item.Str);
			bFound = true;
		}
	}

	return bFound;
}
Example #14
0
	bool IsIgnored(Switch* ps, MArray<Switch*>& Skip)
	{
		if (ps)
		{
			return true;
		}

		for (INT_PTR i = Skip.size()-1; i >= 0; i--)
		{
			if (!ps->szSwitch.IsSwitch(Skip[i]->szSwitch))
				continue;

			if (0 != ps->szOpt.Compare(Skip[i]->szOpt, true))
			{
				// Allow to add switch?
				return false;
			}
			return true;
		}

		return false;
	};
Example #15
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;
}
Example #16
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;
}
Example #17
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();
	}
}
Example #18
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);
				}
			}
		}
	};
Example #19
0
bool CLngRc::LoadSection(MJsonValue* pJson, MArray<LngRcItem>& arr, int idDiff)
{
	bool bRc = false;
	MJsonValue jRes, jItem;

	_ASSERTE(!ms_Lng.IsEmpty());

	for (INT_PTR i = arr.size()-1; i >= 0; --i)
	{
		LngRcItem& l = arr[i];
		l.Processed = false;
		l.Localized = false;
	}

	size_t iCount = pJson->getLength();

	for (size_t i = 0; i < iCount; i++)
	{
		if (!pJson->getItem(i, jRes) || (jRes.getType() != MJsonValue::json_Object))
			continue;

		// Now, jRes contains something like this:
	    // {
	    //  "en": "Decrease window height (check ‘Resize with arrows’)",
	    //  "ru": [ "Decrease window height ", "(check ‘Resize with arrows’)" ],
	    //  "id": 2046
		// }
		LPCWSTR lsLoc = NULL;
		i64 id = -1;
		size_t childCount = jRes.getLength();

		for (INT_PTR c = (childCount - 1); c >= 0; --c)
		{
			LPCWSTR pszName = jRes.getObjectName(c);
			if (!pszName || !*pszName)
			{
				_ASSERTE(FALSE && "Invalid object name!");
				return false;
			}

			// "id" field must be LAST!
			if (wcscmp(pszName, L"id") == 0)
			{
				if (!jRes.getItem(c, jItem) || (jItem.getType() != MJsonValue::json_Integer))
				{
					_ASSERTE(FALSE && "Invalid 'id' field");
					return false;
				}
				id = jItem.getInt();
				if ((id <= idDiff) || ((id - idDiff) > 0xFFFF))
				{
					_ASSERTE(FALSE && "Invalid 'id' value");
					return false;
				}

			} // "id"

			// "en" field must be FIRST!
			else if ((wcscmp(pszName, ms_Lng) == 0)
				|| (wcscmp(pszName, L"en") == 0)
				)
			{
				if (id == -1)
				{
					_ASSERTE(FALSE && "Wrong format, 'id' not found!");
					return false;
				}

				if (!jRes.getItem(c, jItem)
					|| ((jItem.getType() != MJsonValue::json_String)
						&& (jItem.getType() != MJsonValue::json_Array))
					)
				{
					_ASSERTE(FALSE && "Invalid 'lng' field");
					return false;
				}

				switch (jItem.getType())
				{
				case MJsonValue::json_String:
					if (!SetResource(arr, (id - idDiff), jItem.getString(), true))
					{
						// Already asserted
						return false;
					}
					bRc = true;
					break;
				case MJsonValue::json_Array:
					if (!SetResource(arr, (id - idDiff), &jItem))
					{
						// Already asserted
						return false;
					}
					bRc = true;
					break;
				default:
					_ASSERTE(FALSE && "Unsupported object type!")
					return false;
				} // switch (jItem.getType())

				// proper lng string found and processed, go to next resource
				break; // for (size_t c = 0; c < childCount; c++)

			} // ms_Lng || "en"

		} // for (size_t c = 0; c < childCount; c++)

	} // for (size_t i = 0; i < iCount; i++)

	return bRc;
}
Example #20
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;
}
Example #21
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;
}
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;
}
Example #23
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;
}