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); }
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; CVirtualConsole* pVCon = gpConEmu->GetVCon(nNewV); if (pVCon) { CRealConsole* pRCon = pVCon->RCon(); if (pRCon) { pRCon->ActivateFarWindow(nNewR); } if (!gpConEmu->isActive(pVCon)) gpConEmu->Activate(pVCon); } } DestroyMenu(hPopup); }
void CEFindDlg::FindTextDialog() { if (mh_FindDlg && IsWindow(mh_FindDlg)) { SetForegroundWindow(mh_FindDlg); return; } CVConGuard VCon; CRealConsole* pRCon = (CVConGroup::GetActiveVCon(&VCon) >= 0) ? VCon->RCon() : NULL; // Создаем диалог поиска только для консольных приложений if (!pRCon || (pRCon->GuiWnd() && !pRCon->isBufferHeight()) || !pRCon->GetView()) { //DisplayLastError(L"No RealConsole, nothing to find"); return; } gpConEmu->SkipOneAppsRelease(true); mh_FindDlg = CreateDialogParam((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_FIND), ghWnd, findTextProc, 0/*Param*/); if (!mh_FindDlg) { DisplayLastError(L"Can't create Find text dialog", GetLastError()); } }
// This function is called throughout the duration of the panning/inertia gesture bool CGestures::ProcessMove(HWND hWnd, const LONG ldx, const LONG ldy) { bool lbSent = false; if (ldy) { CVConGuard VCon; CRealConsole* pRCon = (CVConGroup::GetActiveVCon(&VCon) >= 0) ? VCon->RCon() : NULL; if (pRCon) { TODO("Если можно будет задавать разный шрифт для разных консолей - заменить gpSet->FontSizeY"); // Соотнести Pan с высотой шрифта int dy = ((ldy < 0) ? -ldy : ldy) / gpSet->FontSizeY; if (dy > 0) { short Delta = ((ldy < 0) ? -120 : 120) * dy; #ifdef _DEBUG wchar_t szDbg[128]; _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L" ProcessMove(%i,%i), WheelDelta=%i\n", ldx, ldy, (int)Delta); DEBUGSTRPAN(szDbg); #endif POINT pt = _ptBegin; if (hWnd != VCon->GetView()) MapWindowPoints(hWnd, VCon->GetView(), &pt, 1); pRCon->OnMouse(WM_MOUSEWHEEL, MAKELPARAM(0,Delta), pt.x, pt.y, true, true); lbSent = true; // Запомнить обработанную координату } } } return lbSent; }
void CGestures::SendRClick(HWND hWnd, const LONG ldx, const LONG ldy) { CVConGuard VCon; CRealConsole* pRCon = (CVConGroup::GetActiveVCon(&VCon) >= 0) ? VCon->RCon() : NULL; if (pRCon) { POINT pt = {ldx, ldy}; if (hWnd != VCon->GetView()) MapWindowPoints(hWnd, VCon->GetView(), &pt, 1); pRCon->OnMouse(WM_RBUTTONDOWN, MK_RBUTTON, pt.x, pt.y); pRCon->OnMouse(WM_RBUTTONUP, 0, pt.x, pt.y); } }
LRESULT CConEmuChild::OnPaintGaps() { CVConGuard VCon((CVirtualConsole*)this); if (!VCon.VCon()) { _ASSERTE(VCon.VCon()!=NULL); return 0; } int nColorIdx = RELEASEDEBUGTEST(0/*Black*/,1/*Blue*/); COLORREF* clrPalette = VCon->GetColors(); if (!clrPalette) { _ASSERTE(clrPalette!=NULL); return 0; } CRealConsole* pRCon = VCon->RCon(); if (pRCon) { nColorIdx = pRCon->GetDefaultBackColorIdx(); } PAINTSTRUCT ps = {}; BeginPaint(mh_WndBack, &ps); HBRUSH hBrush = CreateSolidBrush(clrPalette[nColorIdx]); if (hBrush) { FillRect(ps.hdc, &ps.rcPaint, hBrush); DeleteObject(hBrush); } EndPaint(mh_WndBack, &ps); return 0; }
void CEFindDlg::FindTextDialog() { if (mh_FindDlg && IsWindow(mh_FindDlg)) { SetForegroundWindow(mh_FindDlg); return; } CVConGuard VCon; CRealConsole* pRCon = (CVConGroup::GetActiveVCon(&VCon) >= 0) ? VCon->RCon() : NULL; // Создаем диалог поиска только для консольных приложений if (!pRCon || (pRCon->GuiWnd() && !pRCon->isBufferHeight()) || !pRCon->GetView()) { //DisplayLastError(L"No RealConsole, nothing to find"); return; } if (gpConEmu->mp_TabBar && gpConEmu->mp_TabBar->ActivateSearchPane(true)) { // Контрол поиска встроен и показан в панели инструментов return; } gpConEmu->SkipOneAppsRelease(true); if (!mp_DpiAware) mp_DpiAware = new CDpiForDialog(); // (CreateDialog) mp_Dlg = CDynDialog::ShowDialog(IDD_FIND, ghWnd, findTextProc, 0/*Param*/); mh_FindDlg = mp_Dlg ? mp_Dlg->mh_Dlg : NULL; if (!mh_FindDlg) { DisplayLastError(L"Can't create Find text dialog", GetLastError()); } }
int CTabBarClass::PrepareTab(CTab& pTab, CVirtualConsole *apVCon) { int iTabIcon = -1; #ifdef _DEBUG if (this != gpConEmu->mp_TabBar) { _ASSERTE(this == gpConEmu->mp_TabBar); } #endif MCHKHEAP // get file name TCHAR dummy[MAX_PATH*2]; TCHAR fileName[MAX_PATH+4]; fileName[0] = 0; TCHAR szFormat[32]; TCHAR szEllip[MAX_PATH+1]; //wchar_t /**tFileName=NULL,*/ *pszNo=NULL, *pszTitle=NULL; int nSplit = 0; int nMaxLen = 0; //gpSet->nTabLenMax - _tcslen(szFormat) + 2/* %s */; int origLength = 0; //_tcslen(tFileName); CRealConsole* pRCon = apVCon ? apVCon->RCon() : NULL; bool bIsFar = pRCon ? pRCon->isFar() : false; // Far 4040 - new "Desktop" window type has "0" index if (apVCon && (pTab->Info.nFarWindowID == 0 || pTab->Type() == fwt_Panels)) { iTabIcon = apVCon->RCon()->GetRootProcessIcon(); } LPCWSTR pszTabName = pRCon->GetTabTitle(pTab); if (pTab->Name.Empty() || (pTab->Type() == fwt_Panels)) { //_tcscpy(szFormat, _T("%s")); lstrcpyn(szFormat, bIsFar ? gpSet->szTabPanels : gpSet->szTabConsole, countof(szFormat)); nMaxLen = gpSet->nTabLenMax - _tcslen(szFormat) + 2/* %s */; lstrcpyn(fileName, pszTabName, countof(fileName)); if (gpSet->pszTabSkipWords && *gpSet->pszTabSkipWords) { StripWords(fileName, gpSet->pszTabSkipWords); } origLength = _tcslen(fileName); //if (origLength>6) { // // Чтобы в заголовке было что-то вроде "{C:\Program Fil...- Far" // // вместо "{C:\Program F...} - Far" // После добавления суффиков к заголовку фара - оно уже влезать не будет в любом случае... Так что если панели - '...' строго ставить в конце // if (lstrcmp(tFileName + origLength - 6, L" - Far") == 0) // nSplit = nMaxLen - 6; //} } else { LPTSTR tFileName = NULL; if (GetFullPathName(pszTabName, countof(dummy), dummy, &tFileName) && tFileName && *tFileName) lstrcpyn(fileName, tFileName, countof(fileName)); else lstrcpyn(fileName, pszTabName, countof(fileName)); if (pTab->Type() == fwt_Editor) { if (pTab->Flags() & fwt_ModifiedFarWnd) lstrcpyn(szFormat, gpSet->szTabEditorModified, countof(szFormat)); else lstrcpyn(szFormat, gpSet->szTabEditor, countof(szFormat)); } else if (pTab->Type() == fwt_Viewer) { lstrcpyn(szFormat, gpSet->szTabViewer, countof(szFormat)); } else { _ASSERTE(FALSE && "Must be processed in previous branch"); lstrcpyn(szFormat, bIsFar ? gpSet->szTabPanels : gpSet->szTabConsole, countof(szFormat)); } } // restrict length if (!nMaxLen) nMaxLen = gpSet->nTabLenMax - _tcslen(szFormat) + 2/* %s */; if (!origLength) origLength = _tcslen(fileName); if (nMaxLen<15) nMaxLen=15; else if (nMaxLen>=MAX_PATH) nMaxLen=MAX_PATH-1; if (origLength > nMaxLen) { /*_tcsnset(fileName, _T('\0'), MAX_PATH); _tcsncat(fileName, tFileName, 10); _tcsncat(fileName, _T("..."), 3); _tcsncat(fileName, tFileName + origLength - 10, 10);*/ //if (!nSplit) // nSplit = nMaxLen*2/3; //// 2009-09-20 Если в заголовке нет расширения (отсутствует точка) //const wchar_t* pszAdmin = gpSet->szAdminTitleSuffix; //const wchar_t* pszFrom = tFileName + origLength - (nMaxLen - nSplit); //if (!wcschr(pszFrom, L'.') && (*pszAdmin && !wcsstr(tFileName, pszAdmin))) //{ // // то троеточие ставить в конец, а не середину // nSplit = nMaxLen; //} // "{C:\Program Files} - Far 2.1283 Administrator x64" // После добавления суффиков к заголовку фара - оно уже влезать не будет в любом случае... Так что если панели - '...' строго ставить в конце nSplit = nMaxLen; _tcsncpy(szEllip, fileName, nSplit); szEllip[nSplit]=0; szEllip[nSplit] = L'\x2026' /*"…"*/; szEllip[nSplit+1] = 0; //_tcscat(szEllip, L"\x2026" /*"…"*/); //_tcscat(szEllip, tFileName + origLength - (nMaxLen - nSplit)); //tFileName = szEllip; lstrcpyn(fileName, szEllip, countof(fileName)); } // szFormat различается для Panel/Viewer(*)/Editor(*) // Пример: "%i-[%s] *" ////pszNo = wcsstr(szFormat, L"%i"); ////pszTitle = wcsstr(szFormat, L"%s"); ////if (pszNo == NULL) //// _wsprintf(fileName, SKIPLEN(countof(fileName)) szFormat, tFileName); ////else if (pszNo < pszTitle || pszTitle == NULL) //// _wsprintf(fileName, SKIPLEN(countof(fileName)) szFormat, pTab->Pos, tFileName); ////else //// _wsprintf(fileName, SKIPLEN(countof(fileName)) szFormat, tFileName, pTab->Pos); //wcscpy(pTab->Name, fileName); const TCHAR* pszFmt = szFormat; TCHAR* pszDst = dummy; TCHAR* pszStart = pszDst; TCHAR* pszEnd = dummy + countof(dummy) - 1; // в конце еще нужно зарезервировать место для '\0' if (!pszFmt || !*pszFmt) { pszFmt = _T("%s"); } *pszDst = 0; bool bRenamedTab = false; if (pTab->Flags() & fwt_Renamed) { if (wcsstr(pszFmt, L"%s") == NULL) { if (wcsstr(pszFmt, L"%n") != NULL) bRenamedTab = true; else pszFmt = _T("%s"); } } TCHAR szTmp[64]; CmdArg szArg; bool bAppendAdmin = gpSet->isAdminSuffix() && (pTab->Flags() & fwt_Elevated); while (*pszFmt && pszDst < pszEnd) { if (*pszFmt == _T('%')) { pszFmt++; LPCTSTR pszText = NULL; switch (*pszFmt) { case _T('s'): case _T('S'): pszText = fileName; break; case _T('i'): case _T('I'): _wsprintf(szTmp, SKIPLEN(countof(szTmp)) _T("%i"), pTab->Info.nIndex); pszText = szTmp; break; case _T('p'): case _T('P'): if (!apVCon || !apVCon->RCon()) { wcscpy_c(szTmp, _T("?")); } else { _wsprintf(szTmp, SKIPLEN(countof(szTmp)) _T("%u"), apVCon->RCon()->GetActivePID()); } pszText = szTmp; break; case _T('c'): case _T('C'): { int iCon = gpConEmu->isVConValid(apVCon); if (iCon > 0) _wsprintf(szTmp, SKIPLEN(countof(szTmp)) _T("%u"), iCon); else wcscpy_c(szTmp, _T("?")); pszText = szTmp; } break; case _T('n'): case _T('N'): { pszText = bRenamedTab ? fileName : pRCon ? pRCon->GetActiveProcessName() : NULL; wcscpy_c(szTmp, (pszText && *pszText) ? pszText : L"?"); pszText = szTmp; } break; case _T('d'): case _T('D'): { pszText = pRCon ? pRCon->GetConsoleCurDir(szArg) : NULL; if (!pszText || !*pszText) pszText = L"?"; } break; case _T('a'): case _T('A'): pszText = bAppendAdmin ? gpSet->szAdminTitleSuffix : NULL; bAppendAdmin = false; break; case _T('%'): pszText = L"%"; break; case 0: pszFmt--; break; } pszFmt++; if (pszText) { if ((*(pszDst-1) == L' ') && (*pszText == L' ')) pszText = SkipNonPrintable(pszText); while (*pszText && pszDst < pszEnd) { *(pszDst++) = *(pszText++); } } } else if ((pszDst > pszStart) && (*(pszDst-1) == L' ') && (*pszFmt == L' ')) { pszFmt++; // Avoid adding sequential spaces (e.g. if some macros was empty) } else { *(pszDst++) = *(pszFmt++); } } // Fin. Append smth else? if (bAppendAdmin) { LPCTSTR pszText = gpSet->szAdminTitleSuffix; if (pszText) { while (*pszText && pszDst < pszEnd) { *(pszDst++) = *(pszText++); } } } *pszDst = 0; #ifdef _DEBUG if (dummy[0] && *(pszDst-1) == L' ') *pszDst = 0; #endif pTab->SetLabel(dummy); MCHKHEAP; return iTabIcon; }
void CRecreateDlg::InitVars() { if (mpsz_DefCmd || mpsz_CurCmd || mpsz_SysCmd || mpsz_DefDir || !ms_RConStartDir.IsEmpty() || !ms_RConCurDir.IsEmpty()) { _ASSERTE(!(mpsz_DefCmd || mpsz_CurCmd || mpsz_SysCmd || mpsz_DefDir || !ms_RConStartDir.IsEmpty() || !ms_RConCurDir.IsEmpty())); FreeVars(); } CVConGuard VCon; CVirtualConsole* pVCon = (gpConEmu->GetActiveVCon(&VCon) >= 0) ? VCon.VCon() : NULL; CRealConsole* pRCon = pVCon ? pVCon->RCon() : NULL; if (pRCon) { ms_RConStartDir.Set(pRCon->GetStartupDir()); pRCon->GetConsoleCurDir(ms_RConCurDir); } // Если уже передана команда через параметры - из текущей консоли не извлекать if (!mp_Args || mp_Args->pszSpecialCmd) { _ASSERTE(mp_Args!=NULL); return; } // AutoStartTaskName - не возвращаем никогда. // Если он выбран при старте - то либо текущая консоль, либо первая команда из AutoStartTaskName, либо команда по умолчанию // Диалог может быть вызван в следующих случаях // * Recreate // * Свободный выбор = cra_EditTab (добавление новой команды в task или выбор шелла при обломе на старте) // * Ни одной консоли нет (предложить то что запускается при старте - Task, команда) // * Консоли есть (пусть наверное будет то что запускается при старте - Task, команда) wchar_t* pszBuf = NULL; _ASSERTE(pRCon || (mp_Args->aRecreate == cra_CreateTab || mp_Args->aRecreate == cra_EditTab)); LPCWSTR pszCmd = pRCon ? pRCon->GetCmd() : NULL; if (pszCmd && *pszCmd) mpsz_CurCmd = lstrdup(pszCmd); LPCWSTR pszSystem = gpSetCls->GetCmd(); if (pszSystem && *pszSystem && (lstrcmpi(pszSystem, AutoStartTaskName) != 0)) mpsz_SysCmd = lstrdup(pszSystem); bool bDirFromRCon = false; if (mp_Args->aRecreate == cra_RecreateTab) { // When recreate - always show active console command line _ASSERTE(pRCon); mpsz_DefCmd = lstrdup(pszCmd); bDirFromRCon = true; } else { // В диалоге запуска новой консоли - нечего делать автостартующему таску? if (lstrcmpi(pszSystem, AutoStartTaskName) == 0) { // Раз активной консоли нет - попробовать взять первую команду из AutoStartTaskName if (!pszCmd) { pszBuf = gpConEmu->LoadConsoleBatch(AutoStartTaskName); wchar_t* pszLine = wcschr(pszBuf, L'\n'); if (pszLine > pszBuf && *(pszLine-1) == L'\r') pszLine--; if (pszLine) *pszLine = 0; bool lbRunAdmin = (mp_Args->RunAsAdministrator == crb_On); pszCmd = gpConEmu->ParseScriptLineOptions(pszBuf, &lbRunAdmin, NULL); if (lbRunAdmin) mp_Args->RunAsAdministrator = crb_On; } else { bDirFromRCon = true; } } else if (pszSystem && *pszSystem) { pszCmd = pszSystem; } else { bDirFromRCon = true; } mpsz_DefCmd = lstrdup(pszCmd); //mpsz_DefDir = lstrdup(mp_Args->pszStartupDir ? mp_Args->pszStartupDir : L""); } if (bDirFromRCon) { TODO("May be try to retrieve current directory of the shell?"); mpsz_DefDir = lstrdup(ms_RConCurDir); } SafeFree(pszBuf); }
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; }
INT_PTR CEFindDlg::findTextProc(HWND hWnd2, UINT messg, WPARAM wParam, LPARAM lParam) { switch (messg) { case WM_INITDIALOG: { gpConEmu->OnOurDialogOpened(); gpConEmu->mp_Find->mh_FindDlg = hWnd2; SendMessage(hWnd2, WM_SETICON, ICON_BIG, (LPARAM)hClassIcon); SendMessage(hWnd2, WM_SETICON, ICON_SMALL, (LPARAM)hClassIconSm); CDynDialog::LocalizeDialog(hWnd2); if (gpConEmu->mp_Find->mp_DpiAware) { gpConEmu->mp_Find->mp_DpiAware->Attach(hWnd2, ghWnd, gpConEmu->mp_Find->mp_Dlg); } #if 0 //if (IsDebuggerPresent()) if (!gpSet->isAlwaysOnTop) SetWindowPos(hWnd2, HWND_NOTOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE); #endif CVConGuard VCon; CRealConsole* pRCon = (CVConGroup::GetActiveVCon(&VCon) >= 0) ? VCon->RCon() : NULL; RECT rcWnd = {}; GetWindowRect(pRCon->GetView(), &rcWnd); RECT rcDlg = {}; GetWindowRect(hWnd2, &rcDlg); int nShift = max(gpFontMgr->FontWidth(),gpFontMgr->FontHeight()); int nWidth = rcDlg.right - rcDlg.left; SetWindowPos(hWnd2, gpSet->isAlwaysOnTop ? HWND_TOPMOST : HWND_TOP, max(rcWnd.left,(rcWnd.right-nShift-nWidth)), (rcWnd.top+nShift), 0,0, SWP_NOSIZE); gpConEmu->mp_Find->UpdateFindDlgAlpha(true); SetTimer(hWnd2, 101, 1000, NULL); SetClassLongPtr(hWnd2, GCLP_HICON, (LONG_PTR)hClassIcon); SetDlgItemText(hWnd2, tFindText, gpSet->FindOptions.pszText ? gpSet->FindOptions.pszText : L""); CDlgItemHelper::checkDlgButton(hWnd2, cbFindMatchCase, gpSet->FindOptions.bMatchCase); CDlgItemHelper::checkDlgButton(hWnd2, cbFindWholeWords, gpSet->FindOptions.bMatchWholeWords); CDlgItemHelper::checkDlgButton(hWnd2, cbFindFreezeConsole, gpSet->FindOptions.bFreezeConsole); #if 0 CDlgItemHelper::checkDlgButton(hWnd2, cbFindHighlightAll, gpSet->FindOptions.bHighlightAll); #endif CDlgItemHelper::checkDlgButton(hWnd2, cbFindTransparent, gpSet->FindOptions.bTransparent); if (gpSet->FindOptions.pszText && *gpSet->FindOptions.pszText) SendDlgItemMessage(hWnd2, tFindText, EM_SETSEL, 0, lstrlen(gpSet->FindOptions.pszText)); // Зовем всегда, чтобы инициализировать буфер для поиска как минимум gpConEmu->DoFindText(0); break; } //case WM_SYSCOMMAND: // if (LOWORD(wParam) == ID_ALWAYSONTOP) // { // BOOL lbOnTopNow = GetWindowLong(ghOpWnd, GWL_EXSTYLE) & WS_EX_TOPMOST; // SetWindowPos(ghOpWnd, lbOnTopNow ? HWND_NOTOPMOST : HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); // CheckMenuItem(GetSystemMenu(ghOpWnd, FALSE), ID_ALWAYSONTOP, MF_BYCOMMAND | // (lbOnTopNow ? MF_UNCHECKED : MF_CHECKED)); // SetWindowLongPtr(hWnd2, DWLP_MSGRESULT, 0); // return 1; // } // break; case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: case WM_TIMER: gpConEmu->mp_Find->UpdateFindDlgAlpha(); break; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED) { int nDirection = 0; switch (LOWORD(wParam)) { case IDCLOSE: case IDCANCEL: DestroyWindow(hWnd2); return 0; case cbFindMatchCase: gpSet->FindOptions.bMatchCase = CDlgItemHelper::isChecked2(hWnd2, cbFindMatchCase); break; case cbFindWholeWords: gpSet->FindOptions.bMatchWholeWords = CDlgItemHelper::isChecked2(hWnd2, cbFindWholeWords); break; case cbFindFreezeConsole: gpSet->FindOptions.bFreezeConsole = CDlgItemHelper::isChecked2(hWnd2, cbFindFreezeConsole); break; case cbFindHighlightAll: gpSet->FindOptions.bHighlightAll = CDlgItemHelper::isChecked2(hWnd2, cbFindHighlightAll); break; case cbFindTransparent: gpSet->FindOptions.bTransparent = CDlgItemHelper::isChecked2(hWnd2, cbFindTransparent); gpConEmu->mp_Find->UpdateFindDlgAlpha(true); return 0; case cbFindNext: nDirection = 1; break; case cbFindPrev: nDirection = -1; break; default: return 0; } if (gpSet->FindOptions.pszText && *gpSet->FindOptions.pszText) gpConEmu->DoFindText(nDirection); } else if (HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE) { MyGetDlgItemText(hWnd2, tFindText, gpSet->FindOptions.cchTextMax, gpSet->FindOptions.pszText); if (gpSet->FindOptions.pszText && *gpSet->FindOptions.pszText) gpConEmu->DoFindText(0); } break; case WM_CLOSE: gpConEmu->OnOurDialogClosed(); DestroyWindow(hWnd2); break; case WM_DESTROY: KillTimer(hWnd2, 101); gpConEmu->mp_Find->mh_FindDlg = NULL; gpSet->SaveFindOptions(); gpConEmu->SkipOneAppsRelease(false); gpConEmu->DoEndFindText(); if (gpConEmu->mp_Find->mp_DpiAware) gpConEmu->mp_Find->mp_DpiAware->Detach(); SafeDelete(gpConEmu->mp_Find->mp_Dlg); break; default: if (gpConEmu->mp_Find->mp_DpiAware && gpConEmu->mp_Find->mp_DpiAware->ProcessDpiMessages(hWnd2, messg, wParam, lParam)) { return TRUE; } } return 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 DEBUGSTRCMD(L"GUI recieved CECMD_NEWCMD\n"); LPCWSTR pszCommand = pIn->NewCmd.GetCommand(); _ASSERTE(pszCommand!=NULL && "Must be at least empty string but NOT NULL"); if (pIn->NewCmd.isAdvLogging && !gpSetCls->isAdvLogging) { gpSetCls->isAdvLogging = pIn->NewCmd.isAdvLogging; gpConEmu->CreateLog(); } if (gpSetCls->isAdvLogging && (pIn->NewCmd.isAdvLogging > gpSetCls->isAdvLogging)) { wchar_t szLogLevel[80]; _wsprintf(szLogLevel, SKIPLEN(countof(szLogLevel)) L"Changing log level! Old=%u, New=%u", (UINT)gpSetCls->isAdvLogging, (UINT)pIn->NewCmd.isAdvLogging); gpConEmu->LogString(szLogLevel); gpSetCls->isAdvLogging = pIn->NewCmd.isAdvLogging; } if (gpSetCls->isAdvLogging) { size_t cchAll = 120 + _tcslen(pIn->NewCmd.szConEmu) + _tcslen(pIn->NewCmd.szCurDir) + _tcslen(pszCommand); 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, pszCommand); 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) // Issue 1275: When minimized into TSA (on all VCon are closed) we need to restore and run new tab || (pszCommand[0] && !CVConGroup::isVConExists(0)); RConStartArgs rTest; if (pszCommand[0]) { rTest.pszSpecialCmd = lstrdup(pszCommand); rTest.ProcessNewConArg(); } bool bSkipActivation = false; // Может быть пусто if (bCreateTab && pszCommand[0]) { RConStartArgs *pArgs = new RConStartArgs; // New tab must be started with same credentials that calling tab if others was not specified { if (!rTest.HasInheritedArgs()) { CVConGuard VCon; if ((pIn->NewCmd.hFromConWnd || pIn->NewCmd.hFromDcWnd) && CVConGroup::GetVConByHWND(pIn->NewCmd.hFromConWnd, pIn->NewCmd.hFromDcWnd, &VCon)) { const RConStartArgs& r = VCon->RCon()->GetArgs(); if (r.HasInheritedArgs()) { pArgs->AssignInheritedArgs(&r); } } } } pArgs->Detached = (pIn->NewCmd.ShowHide == sih_StartDetached) ? crb_On : crb_Off; pArgs->pszSpecialCmd = lstrdup(pszCommand); if (pIn->NewCmd.szCurDir[0] == 0) { _ASSERTE(pIn->NewCmd.szCurDir[0] != 0); } else { pArgs->pszStartupDir = lstrdup(pIn->NewCmd.szCurDir); } LPCWSTR pszStrings = pIn->NewCmd.GetEnvStrings(); if (pszStrings && pIn->NewCmd.cchEnvStrings) { size_t cbBytes = pIn->NewCmd.cchEnvStrings*sizeof(*pArgs->pszEnvStrings); pArgs->pszEnvStrings = (wchar_t*)malloc(cbBytes); if (pArgs->pszEnvStrings) { memmove(pArgs->pszEnvStrings, pszStrings, cbBytes); pArgs->cchEnvStrings = pIn->NewCmd.cchEnvStrings; } } if (gpSetCls->IsMulti() || CVConGroup::isDetached()) { gpConEmu->PostCreateCon(pArgs); } else { // Если хотят в одном окне - только одну консоль gpConEmu->CreateWnd(pArgs); SafeDelete(pArgs); // New window created? Don't activate this one. bSkipActivation = true; } } else { _ASSERTE(pIn->NewCmd.ShowHide==sih_ShowMinimize || pIn->NewCmd.ShowHide==sih_ShowHideTSA || pIn->NewCmd.ShowHide==sih_Show); } // gh#151: Do animation after starting tab creation if (!bSkipActivation && (rTest.BackgroundTab != crb_On)) { gpConEmu->DoMinimizeRestore(bCreateTab ? sih_SetForeground : pIn->NewCmd.ShowHide); } } 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 DEBUGSTRCMD(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 case CECMD_ATTACH2GUI: { // Получен запрос на Attach из сервера MCHKHEAP; CESERVER_REQ_SRVSTARTSTOPRET Ret = {}; lbRc = CVConGroup::AttachRequested(pIn->StartStop.hWnd, &(pIn->StartStop), Ret); pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SRVSTARTSTOPRET)+(Ret.cchEnvCommands*sizeof(wchar_t)); if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { SafeFree(Ret.pszCommands); goto wrap; } if (lbRc) { _ASSERTE(sizeof(ppReply->SrvStartStopRet) == sizeof(Ret)); memmove(&ppReply->SrvStartStopRet, &Ret, sizeof(Ret)); // Environment strings (inherited from parent console) if (Ret.cchEnvCommands && Ret.pszCommands) { memmove(ppReply->SrvStartStopRet.szCommands, Ret.pszCommands, Ret.cchEnvCommands*sizeof(wchar_t)); ppReply->SrvStartStopRet.cchEnvCommands = Ret.cchEnvCommands; } else { ppReply->SrvStartStopRet.cchEnvCommands = 0; } SafeFree(Ret.pszCommands); _ASSERTE((ppReply->StartStopRet.nBufferHeight == 0) || ((int)ppReply->StartStopRet.nBufferHeight > (pIn->StartStop.sbi.srWindow.Bottom-pIn->StartStop.sbi.srWindow.Top))); } MCHKHEAP; break; } // CECMD_ATTACH2GUI case CECMD_SRVSTARTSTOP: { MCHKHEAP; // SRVSTART не приходит если запускается cmd под админом или из Win+G bool lbAllocated = false; if (pIn->SrvStartStop.Started == srv_Started) { // Запущен процесс сервера HWND hConWnd = (HWND)pIn->dwData[1]; _ASSERTE(hConWnd && IsWindow(hConWnd)); DWORD nStartTick = timeGetTime(); struct MsgSrvStartedArg { HWND hConWnd; DWORD nSrcPID; DWORD dwKeybLayout; DWORD timeStart; DWORD timeRecv; DWORD timeFin; CESERVER_REQ_SRVSTARTSTOPRET Ret; //111002 - вернуть должен HWND окна отрисовки (дочернее окно ConEmu) static LRESULT OnSrvStarted(LPARAM lParam) { MsgSrvStartedArg *pArg = (MsgSrvStartedArg*)lParam; HWND hWndDC = NULL; DWORD nServerPID = pArg->nSrcPID; HWND hWndCon = pArg->hConWnd; DWORD dwKeybLayout = pArg->dwKeybLayout; pArg->timeRecv = timeGetTime(); DWORD t1, t2; int iFound = -1; hWndDC = CVConGroup::DoSrvCreated(nServerPID, hWndCon, dwKeybLayout, t1, t2, iFound, pArg->Ret); UNREFERENCED_PARAMETER(dwKeybLayout); UNREFERENCED_PARAMETER(hWndCon); pArg->timeFin = timeGetTime(); if (hWndDC == NULL) { _ASSERTE(hWndDC!=NULL); } else { #ifdef _DEBUG DWORD nRecvDur = pArg->timeRecv - pArg->timeStart; DWORD nProcDur = pArg->timeFin - pArg->timeRecv; #define MSGSTARTED_TIMEOUT 10000 if ((nRecvDur > MSGSTARTED_TIMEOUT) || (nProcDur > MSGSTARTED_TIMEOUT)) { _ASSERTE((nRecvDur <= MSGSTARTED_TIMEOUT) && (nProcDur <= MSGSTARTED_TIMEOUT)); } #endif } return (LRESULT)hWndDC; }; } arg = {hConWnd, pIn->hdr.nSrcPID, pIn->SrvStartStop.dwKeybLayout, nStartTick}; gpConEmu->CallMainThread(true, arg.OnSrvStarted, (LPARAM)&arg); HWND hWndDC = arg.Ret.Info.hWndDc; HWND hWndBack = arg.Ret.Info.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 pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SRVSTARTSTOPRET)+(arg.Ret.cchEnvCommands*sizeof(wchar_t)); if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { SafeFree(arg.Ret.pszCommands); goto wrap; } lbAllocated = true; _ASSERTE(sizeof(ppReply->SrvStartStopRet) == sizeof(arg.Ret)); memmove(&ppReply->SrvStartStopRet, &arg.Ret, sizeof(arg.Ret)); // Environment strings (inherited from parent console) if (arg.Ret.cchEnvCommands && arg.Ret.pszCommands) { memmove(ppReply->SrvStartStopRet.szCommands, arg.Ret.pszCommands, arg.Ret.cchEnvCommands*sizeof(wchar_t)); ppReply->SrvStartStopRet.cchEnvCommands = arg.Ret.cchEnvCommands; } else { ppReply->SrvStartStopRet.cchEnvCommands = 0; } SafeFree(arg.Ret.pszCommands); } 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; } gpConEmu->mn_ShellExitCode = pIn->SrvStartStop.nShellExitCode; if (pRCon) pRCon->OnServerClosing(pIn->hdr.nSrcPID, &pIn->SrvStartStop.nShellExitCode); //pIn->dwData[0] = 1; } else { _ASSERTE((pIn->dwData[0] == 1) || (pIn->dwData[0] == 101)); } MCHKHEAP; if (!lbAllocated) { pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_SRVSTARTSTOPRET); if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) goto wrap; } 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.sAppFilePathName, pIn->AttachGuiApp.nPID); //MBoxA(szDbg); MessageBox(NULL, szDbg, L"ConEmu", MB_SYSTEMMODAL); } #endif // Уведомить ожидающую вкладку CRealConsole* pRCon = CVConGroup::AttachRequestedGui(pIn->AttachGuiApp.nServerPID, pIn->AttachGuiApp.sAppFilePathName, 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.sAppFilePathName, pIn->AttachGuiApp.nPID, pIn->hdr.nBits, rcPrev); ppReply->AttachGuiApp.nFlags = agaf_Success | (pRCon->isActive(false) ? 0 : agaf_Inactive); ppReply->AttachGuiApp.nServerPID = pRCon->GetServerPID(); ppReply->AttachGuiApp.nPID = ppReply->AttachGuiApp.nServerPID; 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, pIn->AttachGuiApp.sAppFilePathName); } else { ppReply->AttachGuiApp.nFlags = agaf_Fail; _ASSERTE(FALSE && "No one tab is waiting for ChildGui process"); } 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, pIn->GuiAppShifts.szExeName); lbRc = TRUE; break; } // CECMD_GUICLIENTSHIFT case CECMD_GUIMACRO: { // Допустимо, если GuiMacro пытаются выполнить извне CVConGuard VCon; CVConGroup::GetActiveVCon(&VCon); DWORD nFarPluginPID = VCon->RCon()->GetFarPID(true); LPWSTR pszResult = ConEmuMacro::ExecuteMacro(pIn->GuiMacro.sMacro, VCon->RCon(), (nFarPluginPID==pIn->hdr.nSrcPID), &pIn->GuiMacro); int nLen = pszResult ? _tcslen(pszResult) : 0; pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_GUIMACRO)+nLen*sizeof(wchar_t); if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { SafeFree(pszResult); goto wrap; } if (pszResult) { lstrcpy(ppReply->GuiMacro.sMacro, pszResult); ppReply->GuiMacro.nSucceeded = 1; free(pszResult); } else { ppReply->GuiMacro.sMacro[0] = 0; ppReply->GuiMacro.nSucceeded = 0; } lbRc = TRUE; break; } // CECMD_GUIMACRO case CECMD_CMDSTARTSTOP: { CRealServer* pRSrv = NULL; CVConGuard VCon; DWORD nSrvPID = pIn->hdr.nSrcPID; DWORD nMonitorTID = (pIn->DataSize() >= sizeof(pIn->StartStop)) ? pIn->StartStop.dwAID : 0; if (CVConGroup::GetVConBySrvPID(nSrvPID, nMonitorTID, &VCon)) pRSrv = &VCon->RCon()->m_RConServer; if (pRSrv) { CESERVER_REQ* pOut = pRSrv->cmdStartStop(pInst, pIn, pIn->DataSize()); if (pOut) { DWORD nDataSize = pOut->DataSize(); pcbReplySize = pOut->hdr.cbSize; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pOut->hdr.nCmd, pcbReplySize)) { if (nDataSize > 0) { memmove(ppReply->Data, pOut->Data, nDataSize); } lbRc = TRUE; } ExecuteFreeResult(pOut); } } break; } // CECMD_CMDSTARTSTOP //case CECMD_DEFTERMSTARTED: //{ // if (gpConEmu->mp_DefTrm) // gpConEmu->mp_DefTrm->OnDefTermStarted(pIn); // pcbReplySize = sizeof(CESERVER_REQ_HDR); // if (!ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) // goto wrap; // lbRc = TRUE; // break; //} // CECMD_DEFTERMSTARTED default: _ASSERTE(FALSE && "Command was not handled in CGuiServer::GuiServerCommand"); } //// Освободить память //if (pIn && (LPVOID)pIn != (LPVOID)&in) //{ // free(pIn); pIn = NULL; //} wrap: return lbRc; }
LRESULT CConEmuChild::BackWndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam) { LRESULT result = 0; // Logger MSG msgStr = {hWnd, messg, wParam, lParam}; ConEmuMsgLogger::Log(msgStr, ConEmuMsgLogger::msgBack); if (gpSetCls->isAdvLogging >= 4) { gpConEmu->LogMessage(hWnd, messg, wParam, lParam); } CVConGuard guard; CVirtualConsole* pVCon = NULL; if (messg == WM_CREATE || messg == WM_NCCREATE) { LPCREATESTRUCT lp = (LPCREATESTRUCT)lParam; guard = (CVirtualConsole*)lp->lpCreateParams; pVCon = guard.VCon(); if (pVCon) gVConBkMap.Set(hWnd, pVCon); } else if (hWnd != ghBkInDestroing) { if (!gVConBkMap.Get(hWnd, &pVCon) || !guard.Attach(pVCon)) pVCon = NULL; } if (messg == WM_SYSCHAR) { _ASSERTE(FALSE); // по идее, фокуса тут быть не должно // Чтобы не пищало result = TRUE; goto wrap; } if (!pVCon) { _ASSERTE(pVCon!=NULL || hWnd==ghBkInDestroing); result = DefWindowProc(hWnd, messg, wParam, lParam); goto wrap; } switch (messg) { case WM_SHOWWINDOW: if (wParam) { HWND hView = pVCon->GetView(); SetWindowPos(hView, HWND_TOP, 0, 0, 0,0, SWP_NOSIZE|SWP_NOMOVE); SetWindowPos(hWnd, hView, 0, 0, 0,0, SWP_NOSIZE|SWP_NOMOVE); } break; // DefaultProc case WM_SETFOCUS: // Если в консоли работает "GUI" окно (GUI режим), то фокус нужно отдать туда. { // Фокус должен быть в главном окне! За исключением случая работы в GUI режиме. pVCon->setFocus(); } return 0; case WM_ERASEBKGND: result = 0; break; case WM_PAINT: _ASSERTE(hWnd == pVCon->mh_WndBack); pVCon->OnPaintGaps(); break; case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_MOUSEWHEEL: case WM_ACTIVATE: case WM_ACTIVATEAPP: //case WM_MOUSEACTIVATE: case WM_KILLFOCUS: //case WM_SETFOCUS: case WM_MOUSEMOVE: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_LBUTTONDBLCLK: case WM_MBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_XBUTTONDOWN: case WM_XBUTTONUP: case WM_XBUTTONDBLCLK: case WM_VSCROLL: // Вся обработка в родителе { switch (messg) { case WM_VSCROLL: switch (LOWORD(wParam)) { case SB_THUMBTRACK: case SB_THUMBPOSITION: pVCon->mb_VTracking = TRUE; break; case SB_ENDSCROLL: pVCon->mb_VTracking = FALSE; break; } pVCon->RCon()->OnSetScrollPos(wParam); break; case WM_LBUTTONUP: pVCon->mb_VTracking = FALSE; break; } TODO("Обработка ghWndWork"); HWND hParent = ghWnd; _ASSERTE(GetParent(hWnd)==ghWnd); if (messg >= WM_MOUSEFIRST && messg <= WM_MOUSELAST) { POINT pt = {LOWORD(lParam),HIWORD(lParam)}; MapWindowPoints(hWnd, hParent, &pt, 1); lParam = MAKELONG(pt.x,pt.y); } result = gpConEmu->WndProc(hParent, messg, wParam, lParam); } break; case WM_IME_NOTIFY: break; case WM_INPUTLANGCHANGE: case WM_INPUTLANGCHANGEREQUEST: { #ifdef _DEBUG if (IsDebuggerPresent()) { WCHAR szMsg[128]; _wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"InChild %s(CP:%i, HKL:0x%08X)\n", (messg == WM_INPUTLANGCHANGE) ? L"WM_INPUTLANGCHANGE" : L"WM_INPUTLANGCHANGEREQUEST", (DWORD)wParam, (DWORD)lParam); DEBUGSTRLANG(szMsg); } #endif result = DefWindowProc(hWnd, messg, wParam, lParam); } break; #ifdef _DEBUG case WM_WINDOWPOSCHANGING: { WINDOWPOS* pwp = (WINDOWPOS*)lParam; result = DefWindowProc(hWnd, messg, wParam, lParam); } return result; case WM_WINDOWPOSCHANGED: { WINDOWPOS* pwp = (WINDOWPOS*)lParam; result = DefWindowProc(hWnd, messg, wParam, lParam); } break; #endif case WM_SETCURSOR: { gpConEmu->WndProc(hWnd, messg, wParam, lParam); //if (!result) // result = DefWindowProc(hWnd, messg, wParam, lParam); } // If an application processes this message, it should return TRUE to halt further processing or FALSE to continue. break; case WM_SYSCOMMAND: // -- лишние ограничения, похоже result = DefWindowProc(hWnd, messg, wParam, lParam); //if (wParam >= SC_SIZE && wParam <= SC_CONTEXTHELP/*0xF180*/) //{ // // Изменение размеров/максимизация/и т.п. окна консоли - запрещена // _ASSERTE(!(wParam >= SC_SIZE && wParam <= SC_CONTEXTHELP)); //} //else //{ // // По идее, сюда ничего приходить больше не должно // _ASSERTE(FALSE); //} break; case WM_GESTURENOTIFY: case WM_GESTURE: { gpConEmu->ProcessGestureMessage(hWnd, messg, wParam, lParam, result); break; } // case WM_GESTURE, WM_GESTURENOTIFY default: if (pVCon && (messg == pVCon->mn_MsgRestoreChildFocus)) { if (!gpConEmu->CanSetChildFocus()) { // Клик по иконке открывает системное меню //_ASSERTE(FALSE && "Must not get here?"); } else { CRealConsole* pRCon = pVCon->RCon(); if (gpConEmu->isActive(pVCon, false)) { pRCon->GuiWndFocusRestore(); } if (pRCon->GuiWnd()) { pRCon->StoreGuiChildRect(NULL); } } } else { result = DefWindowProc(hWnd, messg, wParam, lParam); } } wrap: return result; }
//// Эта функция пайп не закрывает! //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; }
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; }
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; }
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; }