diff --git a/src/ConEmu/About.h b/src/ConEmu/About.h index 725d0123a..5dcefe422 100644 --- a/src/ConEmu/About.h +++ b/src/ConEmu/About.h @@ -467,7 +467,7 @@ _DBGHLP(L"-ZoneId - Try to drop :Zone.Identifier without confirmation.\r\n") \ L" Cmd==4: switch tab direct (no recent mode), Parm=(1,-1)\r\n" \ L" Cmd==5: switch tab recent, Parm=(1,-1)\r\n" \ L" Cmd==6: switch console direct (no recent mode), Parm=(1,-1)\r\n" \ - L" Cmd==7: activate console by number, Parm=(1-based console index or -1 for last tab)\r\n" \ + L" Cmd==7: activate console, Parm=(1-based console index, -1 for the last tab, -2 for the tab of execution)\r\n" \ L" Cmd==8: show tabs list menu (indiffirent Far/Not Far)\r\n" \ L" Cmd==9: close active tab, same as Close(3)\r\n" \ L" Cmd==10: switches visible split-panes, Parm=(1,-1)\r\n" \ diff --git a/src/ConEmu/Macro.cpp b/src/ConEmu/Macro.cpp index ed5b6a1ec..dcf7a4785 100644 --- a/src/ConEmu/Macro.cpp +++ b/src/ConEmu/Macro.cpp @@ -77,7 +77,7 @@ namespace ConEmuMacro static bool mb_ChangeContext = false; static UINT mn_ChangeContextTab = 0, mn_ChangeContextSplit = 0; - CRealConsole* ChangeContext(CRealConsole* apRCon, UINT nTabIndex, UINT nSplitIndex, CVConGuard& VCon, CEStr& pszError); + CRealConsole* ChangeContext(CRealConsole* apRCon, int nTabIndex, UINT nSplitIndex, CVConGuard& VCon, CEStr& pszError); /* ****************************** */ /* ****** Macros functions ****** */ @@ -347,7 +347,7 @@ CEStr ConEmuMacro::ConvertMacro(LPCWSTR asMacro, BYTE FromVersion, bool bShowErr return pszCvt; } -CRealConsole* ConEmuMacro::ChangeContext(CRealConsole* apRCon, UINT nTabIndex, UINT nSplitIndex, CVConGuard& VCon, CEStr& pszError) +CRealConsole* ConEmuMacro::ChangeContext(CRealConsole* apRCon, int nTabIndex, UINT nSplitIndex, CVConGuard& VCon, CEStr& pszError) { if (!nTabIndex && !nSplitIndex) { @@ -361,7 +361,22 @@ CRealConsole* ConEmuMacro::ChangeContext(CRealConsole* apRCon, UINT nTabIndex, U // Special (non-active) tab or split was selected if (nTabIndex) { - gpConEmu->mp_TabBar->GetVConFromTab(nTabIndex - 1, &VConTab, nullptr); + if (nTabIndex > 0) + { + gpConEmu->mp_TabBar->GetVConFromTab(nTabIndex - 1, &VConTab, nullptr); + } + else if (nTabIndex == -1) + { + const int nCon = CVConGroup::GetConCount() - 1; + CVConGroup::GetVCon(nCon, &VConTab, false); + } + else if (nTabIndex == -2) + { + if (apRCon) + { + VConTab.Attach(apRCon->VCon()); + } + } } else if (apRCon) { @@ -378,8 +393,8 @@ CRealConsole* ConEmuMacro::ChangeContext(CRealConsole* apRCon, UINT nTabIndex, U if (nSplitIndex && CVConGroup::isGroup(VConTab.VCon(), &pGr)) { MArray Panes; - int iCount = pGr->GetGroupPanes(&Panes); - if ((int)nSplitIndex > iCount) + const int iCount = pGr->GetGroupPanes(&Panes); + if (static_cast(nSplitIndex) > iCount) { CVConGroup::FreePanesArray(Panes); pszError = lstrdup(L"InvalidSplitIndex"); @@ -2852,13 +2867,13 @@ CEStr ConEmuMacro::Tab(GuiMacro* p, CRealConsole* apRCon, bool abFromPlugin) int nParm = 0; p->GetIntArg(1, nParm); - switch (nTabCmd) + switch (static_cast(nTabCmd)) { case ctc_ShowHide: case ctc_SwitchCommit: // commit lazy changes case ctc_SwitchNext: case ctc_SwitchPrev: - gpConEmu->TabCommand((ConEmuTabCommand)nTabCmd); + CConEmuCtrl::TabCommand(static_cast(nTabCmd)); pszResult = lstrdup(L"OK"); break; case ctc_SwitchDirect: // switch tab direct (no recent mode), parm=(1,-1) @@ -2887,7 +2902,7 @@ CEStr ConEmuMacro::Tab(GuiMacro* p, CRealConsole* apRCon, bool abFromPlugin) break; case ctc_SwitchConsoleDirect: // switch console direct (no recent mode), parm=(1,-1) { - int nActive = gpConEmu->ActiveConNum(); // 0-based + const int nActive = gpConEmu->ActiveConNum(); // 0-based if (nParm == 1) { // Прокрутка вперед (циклически) @@ -2912,7 +2927,7 @@ CEStr ConEmuMacro::Tab(GuiMacro* p, CRealConsole* apRCon, bool abFromPlugin) } else { - int nNew = gpConEmu->GetConCount()-1; + const int nNew = gpConEmu->GetConCount()-1; if (nNew > nActive) { gpConEmu->ConActivate(nNew); @@ -2922,11 +2937,21 @@ CEStr ConEmuMacro::Tab(GuiMacro* p, CRealConsole* apRCon, bool abFromPlugin) } } break; - case ctc_ActivateConsole: // activate console by number, parm=(one-based console index) - if ((nParm >= 1) && CVConGroup::isVConExists(nParm-1)) + case ctc_ActivateConsole: // activate console by number + if ((nParm >= 1) && CVConGroup::isVConExists(nParm-1)) // parm=(one-based console index) { - gpConEmu->ConActivate(nParm-1); - pszResult = lstrdup(L"OK"); + const bool ok = gpConEmu->ConActivate(nParm-1); + pszResult = lstrdup(ok ? L"OK" : L"NotFound"); + } + else if (nParm == -1) // Activate last console + { + const bool ok = gpConEmu->ConActivate(-1); + pszResult = lstrdup(ok ? L"OK" : L"NotFound"); + } + else if (nParm == -2 && apRCon) // Activate console, from which Macro is executed + { + const bool ok = CVConGroup::Activate(apRCon->VCon()); + pszResult = lstrdup(ok ? L"OK" : L"NotFound"); } break; case ctc_ActivateByName: // activate console by renamed title, console title, active process name, root process name @@ -2955,7 +2980,7 @@ CEStr ConEmuMacro::Tab(GuiMacro* p, CRealConsole* apRCon, bool abFromPlugin) case ctc_SwitchPaneDirect: // switch visible panes direct (no recent mode), parm=(1,-1), like ctc_SwitchConsoleDirect but for Splits if (apRCon && (nParm == 1 || nParm == -1)) { - bool bNext = (nParm == 1); + const bool bNext = (nParm == 1); if (CVConGroup::PaneActivateNext(bNext)) { pszResult = lstrdup(L"OK"); @@ -2974,6 +2999,9 @@ CEStr ConEmuMacro::Tab(GuiMacro* p, CRealConsole* apRCon, bool abFromPlugin) }, 0); return data.GetData().Detach(); } + break; // NOLINT(clang-diagnostic-unreachable-code-break) + default: + _ASSERTE(FALSE && "Tab command is unknown"); break; } } diff --git a/src/ConEmu/VConGroup.cpp b/src/ConEmu/VConGroup.cpp index e6f02734e..e7ef45ebd 100644 --- a/src/ConEmu/VConGroup.cpp +++ b/src/ConEmu/VConGroup.cpp @@ -3383,7 +3383,7 @@ bool CVConGroup::Activate(CVirtualConsole* apVCon) { if (gp_VCon[i] == apVCon) { - ConActivate(i); + ConActivate(static_cast(i)); lbRc = (gp_VActive == apVCon); break; } @@ -4044,7 +4044,7 @@ void CVConGroup::StoreActiveVCon(CVirtualConsole* pVCon) } } -bool CVConGroup::ConActivate(CVConGuard& VCon, int nCon) +bool CVConGroup::ConActivate(CVConGuard& VCon, const int nCon) { CVirtualConsole* pVCon = VCon.VCon(); @@ -4147,13 +4147,13 @@ bool CVConGroup::ConActivate(CVConGuard& VCon, int nCon) // nCon - zero-based index of console; -1 for last console bool CVConGroup::ConActivate(int nCon) { - FLASHWINFO fl = {sizeof(FLASHWINFO)}; fl.dwFlags = FLASHW_STOP; fl.hwnd = ghWnd; - FlashWindowEx(&fl); // При многократных созданиях мигать начинает... + FLASHWINFO fl{}; fl.cbSize = sizeof(FLASHWINFO); fl.dwFlags = FLASHW_STOP; fl.hwnd = ghWnd; + FlashWindowEx(&fl); // During multiple creation tab icon might be blinking, stop it if (nCon == -1) nCon = GetConCount() - 1; - if (nCon >= 0 && nCon < (int)countof(gp_VCon)) + if (nCon >= 0 && nCon < static_cast(countof(gp_VCon))) { CVConGuard VCon(gp_VCon[nCon]); CVirtualConsole* pVCon = VCon.VCon(); diff --git a/src/ConEmuCD/GuiMacro.cpp b/src/ConEmuCD/GuiMacro.cpp index c6a6056a0..fe035ae7f 100644 --- a/src/ConEmuCD/GuiMacro.cpp +++ b/src/ConEmuCD/GuiMacro.cpp @@ -256,7 +256,7 @@ void ArgGuiMacro(const CEStr& szArg, MacroInstance& inst) break; pszID = pszEnd; } - else if (wcschr(L"SsTt", pszID[0]) && isDigit(pszID[1])) + else if (wcschr(L"SsTt", pszID[0]) && (isDigit(pszID[1]) || (pszID[1] == L'-' && isDigit(pszID[2])))) { switch (pszID[0]) { @@ -265,8 +265,8 @@ void ArgGuiMacro(const CEStr& szArg, MacroInstance& inst) swprintf_c(szLog, L"Split was requested: %u", inst.nSplitIndex); break; case L'T': case L't': - inst.nTabIndex = wcstoul(pszID+1, &pszEnd, 10); - swprintf_c(szLog, L"Tab was requested: %u", inst.nTabIndex); + inst.nTabIndex = wcstol(pszID+1, &pszEnd, 10); + swprintf_c(szLog, L"Tab was requested: %i", inst.nTabIndex); break; default: _ASSERTE(FALSE && "Should not get here"); @@ -318,7 +318,8 @@ int DoGuiMacro(LPCWSTR asCmdArg, MacroInstance& inst, GuiMacroFlags flags, BSTR* _ASSERTE(inst.hConEmuWnd!=NULL || gState.realConWnd_!=NULL || gState.conemuWnd_!=NULL || (wcscmp(asCmdArg, L"IsConEmu") == 0)); wchar_t szErrInst[80] = L"FAILED:Specified ConEmu instance is not found"; - wchar_t szErrExec[80] = L"FAILED:Unknown GuiMacro execution error"; + // ReSharper disable once CppVariableCanBeMadeConstexpr + const wchar_t szErrExec[80] = L"FAILED:Unknown GuiMacro execution error"; // Don't allow to execute on wrong instance if ((inst.nPID && !inst.hConEmuWnd) @@ -342,14 +343,17 @@ int DoGuiMacro(LPCWSTR asCmdArg, MacroInstance& inst, GuiMacroFlags flags, BSTR* return CERR_GUIMACRO_FAILED; } - auto* const hCallWnd = inst.hConEmuWnd ? inst.hConEmuWnd : GetConEmuWindows(gState.realConWnd_).ConEmuRoot; + auto* const hCallWnd = + (inst.nTabIndex == -2) ? gState.realConWnd_ + : inst.hConEmuWnd ? inst.hConEmuWnd + : GetConEmuWindows(gState.realConWnd_).ConEmuRoot; _ASSERTE(hCallWnd != nullptr); // Все что в asCmdArg - выполнить в Gui int iRc = CERR_GUIMACRO_FAILED; const int nLen = lstrlen(asCmdArg); //SetEnvironmentVariable(CEGUIMACRORETENVVAR, NULL); - CESERVER_REQ *pIn = NULL, *pOut = NULL; + CESERVER_REQ *pIn = nullptr, *pOut = nullptr; pIn = ExecuteNewCmd(CECMD_GUIMACRO, sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_GUIMACRO)+nLen*sizeof(wchar_t)); pIn->GuiMacro.nTabIndex = inst.nTabIndex; pIn->GuiMacro.nSplitIndex = inst.nSplitIndex; diff --git a/src/ConEmuCD/GuiMacro.h b/src/ConEmuCD/GuiMacro.h index d41fe26f9..587976f83 100644 --- a/src/ConEmuCD/GuiMacro.h +++ b/src/ConEmuCD/GuiMacro.h @@ -36,7 +36,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct MacroInstance { HWND hConEmuWnd; // Root! window - DWORD nTabIndex; // Specially selected tab, 1-based + int nTabIndex; // Specially selected tab, 1-based; -1 means last tab; -2 means tab of RCon DWORD nSplitIndex; // Specially selected split, 1-based DWORD nPID; }; diff --git a/src/common/Common.h b/src/common/Common.h index 0b609f4f5..4035d0985 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -2262,7 +2262,7 @@ struct CESERVER_REQ_ACTIVATECONSOLE struct CESERVER_REQ_GUIMACRO { DWORD nSucceeded; - DWORD nTabIndex; // Specially selected tab, 1-based + int nTabIndex; // Specially selected tab, 1-based; -1 means last tab; -2 means tab of RCon DWORD nSplitIndex; // Specially selected split, 1-based wchar_t sMacro[1]; // Variable length }; diff --git a/src/common/ConEmuCheck.cpp b/src/common/ConEmuCheck.cpp index 6f44b9d4b..328bd6109 100644 --- a/src/common/ConEmuCheck.cpp +++ b/src/common/ConEmuCheck.cpp @@ -1082,6 +1082,7 @@ CESERVER_REQ* ConEmuRpc::Execute(CESERVER_REQ* pIn) const { if (lpRet) { + // Might be false positive if GuiMacro Sleep is executed or so _ASSERTE(nDelta <= nWarnExecutionTime || lpRet->hdr.IsDebugging); } else