Ejemplo n.º 1
0
void CConEmuCtrl::ChooseTabFromMenu(BOOL abFirstTabOnly, POINT pt, DWORD Align /*= TPM_CENTERALIGN|TPM_VCENTERALIGN*/)
{
	HMENU hPopup = gpConEmu->mp_Menu->CreateVConListPopupMenu(NULL, abFirstTabOnly);

	if (!Align)
		Align = TPM_LEFTALIGN|TPM_TOPALIGN;

	int nTab = gpConEmu->mp_Menu->trackPopupMenu(tmp_TabsList, hPopup, Align|TPM_RETURNCMD,
		pt.x, pt.y, ghWnd);

	if (nTab >= IDM_VCON_FIRST && nTab <= IDM_VCON_LAST)
	{
		int nNewV = ((int)HIWORD(nTab))-1;
		int nNewR = ((int)LOWORD(nTab))-1;

		CVConGuard VCon;
		if (CVConGroup::GetVCon(nNewV, &VCon))
		{
			CRealConsole* pRCon = VCon->RCon();
			if (pRCon)
			{
				CTab tab(__FILE__,__LINE__);
				if (pRCon->GetTab(nNewR, tab))
					pRCon->ActivateFarWindow(tab->Info.nFarWindowID);
			}
			if (!VCon->isActive(false))
				gpConEmu->Activate(VCon.VCon());
		}
	}

	DestroyMenu(hPopup);
}
Ejemplo n.º 2
0
int  CTabBarClass::UpdateAddTab(HANDLE hUpdate, int& tabIdx, int& nCurTab, bool& bStackChanged, CVirtualConsole* pVCon, DWORD nFlags/*UpdateAddTabFlags*/)
{
	CRealConsole *pRCon = pVCon->RCon();
	if (!pRCon)
	{
		_ASSERTE(pRCon!=NULL);
		return 0;
	}

	bool bVConActive = pVCon->isActive(false);
	bool bAllWindows = (gpSet->bShowFarWindows && !(pRCon->GetActiveTabType() & fwt_ModalFarWnd));
	int rFrom = bAllWindows ? 0 : pRCon->GetActiveTab();
	int rFound = 0;

	for (int I = rFrom; bAllWindows || !rFound; I++)
	{
		#ifdef _DEBUG
			if (this != gpConEmu->mp_TabBar)
			{
				_ASSERTE(this == gpConEmu->mp_TabBar);
			}
			MCHKHEAP;
		#endif

		// Check first, if the tab exists
		CTab tab(__FILE__,__LINE__);
		if (!pRCon->GetTab(I, tab))
			break;

		// bShowFarWindows проверяем, чтобы не проколоться с недоступностью единственного таба
		if (gpSet->bHideDisabledTabs && gpSet->bShowFarWindows)
		{
			if (!pRCon->CanActivateFarWindow(I))
				continue;
		}


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

		// Additional flags (to add or not to add)
		if (nFlags & (uat_PanelsOrModalsOnly|uat_PanelsOnly))
		{
			if ((tab->Type() != fwt_Panels))
			{
				if (nFlags & uat_PanelsOnly)
					continue;
				if (!(tab->Flags() & fwt_ModalFarWnd))
					continue;
				// Редакторы/вьюверы из "far /e ..." здесь НЕ добавлять!
				// Они либо показываются как "Консоль" (без сплитов)
				// Либо как отдельный таб редактора
				if (!pRCon->isFarPanelAllowed())
					continue;
			}
		}
		if (nFlags & uat_NonModals)
		{
			// Смысл в том, что если VCon активна,
			// то модальный редактор показан *первой* вкладкой группы (вместо панелей).
			// Для НЕ активных VCon - модальный редактор нужно все-равно допихнуть в табы,
			// а то таб этого редактор вообще не будет виден пользователю.
			if (bVConActive && (tab->Flags() & fwt_ModalFarWnd) && pRCon->isFarPanelAllowed())
				continue;
		}
		if (nFlags & uat_NonPanels)
		{
			if ((tab->Type() == fwt_Panels) && pRCon->isFarPanelAllowed())
				continue;
		}

		// Prepare tab to display
		WARNING("TabIcon, trim words?");
		int iTabIcon = PrepareTab(tab, pVCon);

		#if 0
		vct.pVCon = pVCon;
		vct.nFarWindowId = I;
		#endif


		m_Tabs.UpdateAppend(hUpdate, tab, FALSE);

		// Физически (WinAPI) добавляет закладку, или меняет (при необходимости) заголовок существующей
		mp_Rebar->AddTabInt(tab->GetLabel(), tabIdx, (tab->Flags() & fwt_Elevated)==fwt_Elevated, iTabIcon);

		// Add current (selected) tab to the top of recent stack
		if ((tab->Flags() & fwt_CurrentFarWnd) && bVConActive)
		{
			// !!! RCon must return ONLY ONE active tab !!!
			// with only temorarily exception during edit/view activation from panels

			#ifdef _DEBUG
			static int iFails = 0;
			if (nCurTab == -1)
			{
				iFails = 0;
			}
			else
			{
				_ASSERTE((nCurTab == -1) || (nCurTab == 0 && iFails == 0 && tab->Type() == fwt_Panels));
				iFails++;
			}
			#endif

			nCurTab = tabIdx;
			if (AddStack(tab))
				bStackChanged = true;
		}

		rFound++;
		tabIdx++;


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

	return rFound;
}
Ejemplo n.º 3
0
int CTabBarClass::ActiveTabByName(int anType, LPCWSTR asName, CVConGuard* rpVCon)
{
	int nTab = -1;

	if (rpVCon)
		rpVCon->Release();

	TODO("TabBarClass::ActiveTabByName - найти таб по имени");

	INT_PTR V, I;
	int tabIdx = 0;

	CVConGuard VCon;
	for (V = 0; (nTab == -1) && CVConGroup::GetVCon(V, &VCon, true); V++)
	{
		#ifdef _DEBUG
		bool lbActive = VCon->isActive(false);
		#endif

		//111120 - Эту опцию игнорируем. Если редактор открыт в другой консоли - активируем ее потом
		//if (gpSet->bHideInactiveConsoleTabs)
		//{
		//	if (!lbActive) continue;
		//}

		CRealConsole *pRCon = VCon->RCon();

		for (I = 0; TRUE; I++)
		{
			CTab tab(__FILE__,__LINE__);
			if (!pRCon->GetTab(I, tab))
				break;

			if (tab->Type() == (anType & fwt_TypeMask))
			{
				// Тут GetName() использовать нельзя, т.к. оно может возвращать "переименованное пользователем"
				// А здесь ищется конкретный редактор-вьювер фара (то есть нужно правильное полное имя-путь к файлу)
				LPCWSTR pszNamePtr = tab->Name.Ptr();
				// If asName (searched file) has been specified with path, we need to compare with tab full path
				LPCWSTR pszCompareTab = wcspbrk(asName, L"\\/") ? pszNamePtr : PointToName(pszNamePtr);
				if (pszNamePtr && ((lstrcmpi(pszCompareTab, asName) == 0)))
				{
					nTab = tabIdx;
					break;
				}
			}

			tabIdx++;
		}
	}


	if (nTab >= 0)
	{
		if (!CanActivateTab(nTab))
		{
			nTab = -2;
		}
		else
		{
			if (!mp_Rebar->FarSendChangeTab(nTab, &VCon))
				nTab = -2;
		}
	}

	if (rpVCon)
		rpVCon->Attach(VCon.VCon());

	return nTab;
}
Ejemplo n.º 4
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;
	CVConGuard VCon;

	pTabs = (CESERVER_REQ_GETALLTABS::TabInfo*)calloc(cchMax, sizeof(*pTabs));

	for (int V = 0; CVConGroup::GetVCon(V, &VCon, true); V++)
	{
		if (!pTabs)
		{
			_ASSERTE(pTabs!=NULL);
			break;
		}

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

		CTab tab(__FILE__,__LINE__);
		wchar_t szMark[6];
		for (int t = 0; pRCon->GetTab(t, tab); t++)
		{
			int T = t; //tab->Info.nFarWindowID; -- В Far3 номер из nFarWindowID стал бесполезным для пользователя

			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].TabNo = T;
			pTabs[cchCount].FarWindow = tab->Info.nFarWindowID;

			// 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) && (T <= 9))
				_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);

			#ifdef _DEBUG
			if (pRCon->IsFarLua())
				_wsprintf(pTabs[cchCount].Title+lstrlen(pTabs[cchCount].Title), SKIPLEN(30) L"{%i} ", tab->Info.nFarWindowID);
			#endif

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

			cchCount++;
		}
	}
	return cchCount;
}
Ejemplo n.º 5
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;

		ConEmuTab 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.Current != 0);
			pTabs[cchCount].Disabled = ((tab.Type & fwt_Disabled) == fwt_Disabled);
			pTabs[cchCount].ConsoleIdx = V;
			pTabs[cchCount].TabIdx = T;

			// Text
			//wcscpy_c(szMark, tab.Modified ? L" * " : L"   ");
			switch ((tab.Type & fwt_TypeMask))
			{
				case fwt_Editor:
					wcscpy_c(szMark, tab.Modified ? 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, countof(pTabs[cchCount].Title)-nCurLen);

			cchCount++;
		}
	}
	return cchCount;
}
Ejemplo n.º 6
0
//// Эта функция пайп не закрывает!
//void CGuiServer::GuiServerThreadCommand(HANDLE hPipe)
BOOL CGuiServer::GuiServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam)
{
	BOOL lbRc = FALSE;
	CGuiServer* pGSrv = (CGuiServer*)lParam;

	if (!pGSrv)
	{
		_ASSERTE(((CGuiServer*)lParam)!=NULL);
		pGSrv = &gpConEmu->m_GuiServer;
	}
	
	if (pIn->hdr.bAsync)
		pGSrv->mp_GuiServer->BreakConnection(pInst);

	gpSetCls->debugLogCommand(pIn, TRUE, timeGetTime(), 0, pGSrv ? pGSrv->ms_ServerPipe : NULL);

	#ifdef _DEBUG
	UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR);
	#endif
	// Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат

	#ifdef ALLOW_WINE_MSG
	if (gbIsWine)
	{
		wchar_t szMsg[128];
		msprintf(szMsg, countof(szMsg), L"CGuiServer::GuiServerCommand.\nGUI TID=%u\nSrcPID=%u, SrcTID=%u, Cmd=%u",
			GetCurrentThreadId(), pIn->hdr.nSrcPID, pIn->hdr.nSrcThreadId, pIn->hdr.nCmd);
		MessageBox(szMsg, MB_ICONINFORMATION);
	}
	#endif

	switch (pIn->hdr.nCmd)
	{
		case CECMD_NEWCMD:
		{
			// Приходит из другой копии ConEmu.exe, когда она запущена с ключом /single, /showhide, /showhideTSA
			DEBUGSTR(L"GUI recieved CECMD_NEWCMD\n");

			if (gpSetCls->isAdvLogging)
			{
				size_t cchAll = 120 + _tcslen(pIn->NewCmd.szConEmu) + _tcslen(pIn->NewCmd.szCurDir) + _tcslen(pIn->NewCmd.szCommand);
				wchar_t* pszInfo = (wchar_t*)malloc(cchAll*sizeof(*pszInfo));
				if (pszInfo)
				{
					_wsprintf(pszInfo, SKIPLEN(cchAll) L"CECMD_NEWCMD: Wnd=x%08X, Act=%u, ConEmu=%s, Dir=%s, Cmd=%s",
						(DWORD)(DWORD_PTR)pIn->NewCmd.hFromConWnd, pIn->NewCmd.ShowHide,
						pIn->NewCmd.szConEmu, pIn->NewCmd.szCurDir, pIn->NewCmd.szCommand);
					gpConEmu->LogString(pszInfo);
					free(pszInfo);
				}
			}

			BOOL bAccepted = FALSE;

			if (pIn->NewCmd.szConEmu[0])
			{
				bAccepted = (lstrcmpi(gpConEmu->ms_ConEmuExeDir, pIn->NewCmd.szConEmu) == 0);
			}
			else
			{
				bAccepted = TRUE;
			}

			if (bAccepted)
			{
				bool bCreateTab = (pIn->NewCmd.ShowHide == sih_None || pIn->NewCmd.ShowHide == sih_StartDetached);
				gpConEmu->OnMinimizeRestore(bCreateTab ? sih_SetForeground : pIn->NewCmd.ShowHide);

				// Может быть пусто
				if (bCreateTab && pIn->NewCmd.szCommand[0])
				{
					RConStartArgs *pArgs = new RConStartArgs;
					pArgs->bDetached = (pIn->NewCmd.ShowHide == sih_StartDetached);
					pArgs->pszSpecialCmd = lstrdup(pIn->NewCmd.szCommand);
					if (pIn->NewCmd.szCurDir[0] == 0)
					{
						_ASSERTE(pIn->NewCmd.szCurDir[0] != 0);
					}
					else
					{
						pArgs->pszStartupDir = lstrdup(pIn->NewCmd.szCurDir);
					}

					if (gpSet->isMulti || CVConGroup::isDetached())
					{
						gpConEmu->PostCreateCon(pArgs);
					}
					else
					{
						// Если хотят в одном окне - только одну консоль
						gpConEmu->CreateWnd(pArgs);
						SafeDelete(pArgs);
					}
				}
				else
				{
					_ASSERTE(pIn->NewCmd.ShowHide==sih_ShowMinimize || pIn->NewCmd.ShowHide==sih_ShowHideTSA || pIn->NewCmd.ShowHide==sih_Show);
				}
			}

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(BYTE);
			lbRc = ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize);
			if (lbRc)
			{
				ppReply->Data[0] = bAccepted;
			}

			break;
		} //CECMD_NEWCMD

		case CECMD_TABSCMD:
		{
			// 0: спрятать/показать табы, 1: перейти на следующую, 2: перейти на предыдущую, 3: commit switch
			DEBUGSTR(L"GUI recieved CECMD_TABSCMD\n");
			_ASSERTE(nDataSize>=1);
			DWORD nTabCmd = pIn->Data[0];
			gpConEmu->TabCommand((ConEmuTabCommand)nTabCmd);

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(BYTE);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				ppReply->Data[0] = TRUE;
			}
			break;
		} // CECMD_TABSCMD

		#if 0
		case CECMD_GETALLTABS:
		{
			int nConCount = gpConEmu->GetConCount();
			int nActiveCon = gpConEmu->ActiveConNum();
			size_t cchMax = nConCount*16;
			size_t cchCount = 0;
			CVirtualConsole* pVCon;
			CESERVER_REQ_GETALLTABS::TabInfo* 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;

				ConEmuTab tab;
				wchar_t szModified[4];
				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.Current != 0);
					pTabs[cchCount].Disabled = ((tab.Type & fwt_Disabled) == fwt_Disabled);
					pTabs[cchCount].ConsoleIdx = V;
					pTabs[cchCount].TabIdx = T;

					// Text
					wcscpy_c(szModified, tab.Modified ? L" * " : L"   ");
					if (V == nActiveCon)
					{
						if (T < 9)
							_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/&%i]%s", V+1, T+1, szModified);
						else if (T == 9)
							_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/1&0]%s", V+1, szModified);
						else
							_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/%i]%s", V+1, T+1, szModified);
					}
					else
					{
						_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/%i]%s", V+1, T+1, szModified);
					}

					cchCount++;
				}
			}
			if (cchCount && pTabs)
			{
				pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_GETALLTABS)+((cchCount-1)*sizeof(CESERVER_REQ_GETALLTABS::TabInfo));
				if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				{
					lbRc = TRUE;
					ppReply->GetAllTabs.Count = cchCount;
					memmove(ppReply->GetAllTabs.Tabs, pTabs, cchCount*sizeof(*pTabs));
				}
			}
			SafeFree(pTabs);
			break;
		} // CECMD_GETALLTABS

		case CECMD_ACTIVATETAB:
		{
			BOOL lbTabOk = FALSE;
			CVirtualConsole *pVCon = gpConEmu->GetVCon(pIn->dwData[0]);
			if (pVCon && pVCon->RCon())
			{
				lbTabOk = pVCon->RCon()->ActivateFarWindow(pIn->dwData[1]);
			}

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				ppReply->dwData[0] = lbTabOk;
			}
			break;
		} // CECMD_ACTIVATETAB
		#endif

		case CECMD_ATTACH2GUI:
		{
			// Получен запрос на Attach из сервера
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOPRET);
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				goto wrap;
			//CESERVER_REQ* pOut = ExecuteNewCmd(CECMD_ATTACH2GUI, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOPRET));

			gpConEmu->AttachRequested(pIn->StartStop.hWnd, &(pIn->StartStop), &(ppReply->StartStopRet));
			_ASSERTE((ppReply->StartStopRet.nBufferHeight == 0) || ((int)ppReply->StartStopRet.nBufferHeight > pIn->StartStop.sbi.dwSize.X));

			lbRc = TRUE;
			//ExecuteFreeResult(pOut);
			break;
		} // CECMD_ATTACH2GUI

		case CECMD_SRVSTARTSTOP:
		{
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_STARTSTOPRET);
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				goto wrap;

			if (pIn->SrvStartStop.Started == srv_Started)
			{
				// Запущен процесс сервера
				HWND hConWnd = (HWND)pIn->dwData[1];
				_ASSERTE(hConWnd && IsWindow(hConWnd));

				DWORD nStartTick = timeGetTime();

				//LRESULT l = 0;
				//DWORD_PTR dwRc = 0;
				//2010-05-21 Поскольку это критично - лучше ждать до упора, хотя может быть DeadLock?
				//l = SendMessageTimeout(ghWnd, gpConEmu->mn_MsgSrvStarted, (WPARAM)hConWnd, pIn->hdr.nSrcPID,
				//	SMTO_BLOCK, 5000, &dwRc);

				//111002 - вернуть должен HWND окна отрисовки (дочернее окно ConEmu)
				MsgSrvStartedArg arg = {hConWnd, pIn->hdr.nSrcPID, pIn->SrvStartStop.dwKeybLayout, nStartTick};
				SendMessage(ghWnd, gpConEmu->mn_MsgSrvStarted, 0, (LPARAM)&arg);
				HWND hWndDC = arg.hWndDc;
				HWND hWndBack = arg.hWndBack;
				_ASSERTE(hWndDC!=NULL);

				#ifdef _DEBUG
				DWORD dwErr = GetLastError(), nEndTick = timeGetTime(), nDelta = nEndTick - nStartTick;
				if (hWndDC && nDelta >= EXECUTE_CMD_WARN_TIMEOUT)
				{
					if (!IsDebuggerPresent())
					{
						//_ASSERTE(nDelta <= EXECUTE_CMD_WARN_TIMEOUT || (pIn->hdr.nCmd == CECMD_CMDSTARTSTOP && nDelta <= EXECUTE_CMD_WARN_TIMEOUT2));
						_ASSERTEX(nDelta <= EXECUTE_CMD_WARN_TIMEOUT);
					}
				}
				#endif

				//pIn->dwData[0] = (DWORD)ghWnd; //-V205
				//pIn->dwData[1] = (DWORD)dwRc; //-V205
				//pIn->dwData[0] = (l == 0) ? 0 : 1;
				ppReply->StartStopRet.hWnd = ghWnd;
				ppReply->StartStopRet.hWndDc = hWndDC;
				ppReply->StartStopRet.hWndBack = hWndBack;
				ppReply->StartStopRet.dwPID = GetCurrentProcessId();
			}
			else if (pIn->SrvStartStop.Started == srv_Stopped)
			{
				// Процесс сервера завершается
				CRealConsole* pRCon = NULL;
				CVConGuard VCon;

				for (size_t i = 0;; i++)
				{
					if (!CVConGroup::GetVCon(i, &VCon))
						break;

					pRCon = VCon->RCon();
					if (pRCon && (pRCon->GetServerPID(true) == pIn->hdr.nSrcPID || pRCon->GetServerPID(false) == pIn->hdr.nSrcPID))
					{
						break;
					}
					pRCon = NULL;
				}

				if (pRCon)
					pRCon->OnServerClosing(pIn->hdr.nSrcPID);

				//pIn->dwData[0] = 1;
			}
			else
			{
				_ASSERTE((pIn->dwData[0] == 1) || (pIn->dwData[0] == 101));
			}

			lbRc = TRUE;
			//// Отправляем
			//fSuccess = WriteFile(
			//               hPipe,        // handle to pipe
			//               pOut,         // buffer to write from
			//               pOut->hdr.cbSize,  // number of bytes to write
			//               &cbWritten,   // number of bytes written
			//               NULL);        // not overlapped I/O

			//ExecuteFreeResult(pOut);
			break;
		} // CECMD_SRVSTARTSTOP

		case CECMD_ASSERT:
		{
			DWORD nBtn = MessageBox(NULL, pIn->AssertInfo.szDebugInfo, pIn->AssertInfo.szTitle, pIn->AssertInfo.nBtns);

			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD);
			if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
			{
				lbRc = TRUE;
				ppReply->dwData[0] = nBtn;
			}

			//ExecutePrepareCmd(&pIn->hdr, CECMD_ASSERT, sizeof(CESERVER_REQ_HDR) + sizeof(DWORD));
			//pIn->dwData[0] = nBtn;
			//// Отправляем
			//fSuccess = WriteFile(
			//               hPipe,        // handle to pipe
			//               pIn,         // buffer to write from
			//               pIn->hdr.cbSize,  // number of bytes to write
			//               &cbWritten,   // number of bytes written
			//               NULL);        // not overlapped I/O
			break;
		} // CECMD_ASSERT

		case CECMD_ATTACHGUIAPP:
		{
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_ATTACHGUIAPP);
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				goto wrap;
			ppReply->AttachGuiApp = pIn->AttachGuiApp;

			//CESERVER_REQ Out;
			//ExecutePrepareCmd(&Out.hdr, CECMD_ATTACHGUIAPP, sizeof(CESERVER_REQ_HDR)+sizeof(Out.AttachGuiApp));
			//Out.AttachGuiApp = pIn->AttachGuiApp;
			
			#ifdef SHOW_GUIATTACH_START
			if (pIn->AttachGuiApp.hWindow == NULL)
			{
				wchar_t szDbg[1024];
				_wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"AttachGuiApp requested from:\n%s\nPID=%u", pIn->AttachGuiApp.sAppFileName, pIn->AttachGuiApp.nPID);
				//MBoxA(szDbg);
				MessageBox(NULL, szDbg, L"ConEmu", MB_SYSTEMMODAL);
			}
			#endif

			// Уведомить ожидающую вкладку
			CRealConsole* pRCon = gpConEmu->AttachRequestedGui(pIn->AttachGuiApp.sAppFileName, pIn->AttachGuiApp.nPID);
			if (pRCon)
			{
				CVConGuard VCon(pRCon->VCon());
				RECT rcPrev = ppReply->AttachGuiApp.rcWindow;
				HWND hBack = pRCon->VCon()->GetBack();

				//// Размер должен быть независим от возможности наличия прокрутки в VCon
				//GetWindowRect(hBack, &ppReply->AttachGuiApp.rcWindow);
				//ppReply->AttachGuiApp.rcWindow.right -= ppReply->AttachGuiApp.rcWindow.left;
				//ppReply->AttachGuiApp.rcWindow.bottom -= ppReply->AttachGuiApp.rcWindow.top;
				//ppReply->AttachGuiApp.rcWindow.left = ppReply->AttachGuiApp.rcWindow.top = 0;
				////MapWindowPoints(NULL, hBack, (LPPOINT)&ppReply->AttachGuiApp.rcWindow, 2);
				//pRCon->CorrectGuiChildRect(ppReply->AttachGuiApp.nStyle, ppReply->AttachGuiApp.nStyleEx, ppReply->AttachGuiApp.rcWindow);
				
				// Уведомить RCon и ConEmuC, что гуй подцепился
				// Вызывается два раза. Первый (при запуске exe) ahGuiWnd==NULL, второй - после фактического создания окна
				pRCon->SetGuiMode(pIn->AttachGuiApp.nFlags, pIn->AttachGuiApp.hAppWindow, pIn->AttachGuiApp.Styles.nStyle, pIn->AttachGuiApp.Styles.nStyleEx, pIn->AttachGuiApp.sAppFileName, pIn->AttachGuiApp.nPID, rcPrev);

				ppReply->AttachGuiApp.nFlags = agaf_Success | (pRCon->isActive(false) ? 0 : agaf_Inactive);
				ppReply->AttachGuiApp.nPID = pRCon->GetServerPID();
				ppReply->AttachGuiApp.hConEmuDc = pRCon->GetView();
				ppReply->AttachGuiApp.hConEmuBack = hBack;
				ppReply->AttachGuiApp.hConEmuWnd = ghWnd;
				ppReply->AttachGuiApp.hAppWindow = pIn->AttachGuiApp.hAppWindow;
				ppReply->AttachGuiApp.hSrvConWnd = pRCon->ConWnd();
				ppReply->AttachGuiApp.hkl = (DWORD)(LONG)(LONG_PTR)GetKeyboardLayout(gpConEmu->mn_MainThreadId);
				ZeroStruct(ppReply->AttachGuiApp.Styles.Shifts);
				CRealConsole::CorrectGuiChildRect(pIn->AttachGuiApp.Styles.nStyle, pIn->AttachGuiApp.Styles.nStyleEx, ppReply->AttachGuiApp.Styles.Shifts);
			}
			else
			{
				ppReply->AttachGuiApp.nFlags = agaf_Fail;
			}

			lbRc = TRUE;

			//// Отправляем
			//fSuccess = WriteFile(
			//               hPipe,        // handle to pipe
			//               &Out,         // buffer to write from
			//               Out.hdr.cbSize,  // number of bytes to write
			//               &cbWritten,   // number of bytes written
			//               NULL);        // not overlapped I/O
			break;
		} // CECMD_ATTACHGUIAPP

		case CECMD_GUICLIENTSHIFT:
		{
			pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(GuiStylesAndShifts);
			if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize))
				goto wrap;
			ppReply->GuiAppShifts = pIn->GuiAppShifts;

			ZeroStruct(ppReply->GuiAppShifts.Shifts);
			CRealConsole::CorrectGuiChildRect(pIn->GuiAppShifts.nStyle, pIn->GuiAppShifts.nStyleEx, ppReply->GuiAppShifts.Shifts);

			lbRc = TRUE;
			break;
		} // CECMD_GUICLIENTSHIFT
	}

	//// Освободить память
	//if (pIn && (LPVOID)pIn != (LPVOID)&in)
	//{
	//	free(pIn); pIn = NULL;
	//}
wrap:
	return lbRc;
}