LPCWSTR CRConFiles::GetFileFromConsole(LPCWSTR asSrc, CEStr& szFull) { CEStr szWinPath; LPCWSTR pszWinPath = MakeWinPath(asSrc, mp_RCon ? mp_RCon->GetMntPrefix() : NULL, szWinPath); if (!pszWinPath || !*pszWinPath) { _ASSERTE(pszWinPath && *pszWinPath); return NULL; } if (IsFilePath(pszWinPath, true)) { if (!FileExists(pszWinPath)) // otherwise it will cover directories too return NULL; szFull.Attach(szWinPath.Detach()); } else { CEStr szDir; LPCWSTR pszDir = mp_RCon->GetConsoleCurDir(szDir, true); // We may get empty dir here if we are in "~" subdir if (!pszDir || !*pszDir) { _ASSERTE(pszDir && *pszDir && wcschr(pszDir,L'/')==NULL); return NULL; } // Попытаться просканировать один-два уровеня подпапок bool bFound = FileExistSubDir(pszDir, pszWinPath, 1, szFull); if (!bFound) { // git diffs style, but with backslashes (they are converted already) // "a/src/ConEmu.cpp" and "b/src/ConEmu.cpp" if (pszWinPath[0] && (pszWinPath[1] == L'\\') && wcschr(L"abicwo", pszWinPath[0])) { LPCWSTR pszSlash = pszWinPath; while (!bFound && ((pszSlash = wcschr(pszSlash, L'\\')) != NULL)) { while (*pszSlash == L'\\') pszSlash++; if (!*pszSlash) break; bFound = FileExistSubDir(pszDir, pszSlash, 1, szFull); if (!bFound) { // Try to go to parent folder (useful while browsing git-diff-s) bFound = CheckParentFolders(pszDir, pszSlash, szFull); } } } else { // let's try to check some paths from #include // for example: #include "src/common/Common.h" LPCWSTR pszSlash = pszWinPath; while (*pszSlash == L'\\') pszSlash++; bFound = CheckParentFolders(pszDir, pszSlash, szFull); } } if (!bFound) { // If there is "src" subfolder in the current folder const wchar_t* predefined[] = {L"trunk", L"src", L"source", L"sources", NULL}; for (size_t i = 0; !bFound && predefined[i]; ++i) { CEStr szSrc(JoinPath(pszDir, predefined[i])); if (DirectoryExists(szSrc)) bFound = FileExistSubDir(szSrc, pszWinPath, 1, szFull); } } if (!bFound) { return NULL; } } if (!szFull.IsEmpty()) { // "src\conemu\realconsole.cpp" --> "src\ConEmu\RealConsole.cpp" MakePathProperCase(szFull); } return szFull; }
bool TermX::GetSubstitute(const MOUSE_EVENT_RECORD& m, TermMouseMode MouseMode, CEStr& lsSubst) { _ASSERTE(lsSubst.IsEmpty()); if (!MouseMode) { lsSubst.Clear(); return false; } wchar_t szSubst[16] = L""; // Deprecated. Mouse events mimic xterm behavior now. #if 0 // http://conemu.github.io/en/VimXterm.html#Vim-scrolling-using-mouse-Wheel // https://github.com/Maximus5/ConEmu/issues/1007 if ((m.dwEventFlags & MOUSE_WHEELED) && (MouseMode & tmm_VIM)) { // If the high word of the dwButtonState member contains // a positive value, the wheel was rotated forward, away from the user. // Otherwise, the wheel was rotated backward, toward the user. short dir = (short)HIWORD(m.dwButtonState); // Ctrl/Alt/Shift DWORD mods = (m.dwControlKeyState & (LEFT_ALT_PRESSED|LEFT_CTRL_PRESSED|RIGHT_ALT_PRESSED|RIGHT_CTRL_PRESSED|SHIFT_PRESSED)); if (mods == 0) { if (dir <= 0) wcscpy_c(szSubst, L"\033[62~"); // <MouseDown> else wcscpy_c(szSubst, L"\033[63~"); // <MouseUp> } else if (mods == SHIFT_PRESSED) { if (dir <= 0) wcscpy_c(szSubst, L"\033[64~"); // <S-MouseDown> else wcscpy_c(szSubst, L"\033[65~"); // <S-MouseUp> } else return false; lsSubst.Set(szSubst); return true; } #endif if ((m.dwEventFlags & MOUSE_WHEELED) && (MouseMode & tmm_SCROLL)) { KEY_EVENT_RECORD k = {TRUE, 1}; short dir = (short)HIWORD(m.dwButtonState); DWORD mods = (m.dwControlKeyState & (LEFT_ALT_PRESSED|LEFT_CTRL_PRESSED|RIGHT_ALT_PRESSED|RIGHT_CTRL_PRESSED|SHIFT_PRESSED)); UINT nCount = 1; if (mods == 0) { k.wVirtualKeyCode = (dir > 0) ? VK_UP : VK_DOWN; nCount = gpConEmu->mouse.GetWheelScrollLines(); } else if (mods == SHIFT_PRESSED) { k.wVirtualKeyCode = (dir > 0) ? VK_PRIOR : VK_NEXT; } else return false; CEStr lsPart; if (!GetSubstitute(k, lsPart) || lsPart.IsEmpty()) return false; if (nCount > 1) { INT_PTR l = lsPart.GetLen(); wchar_t* ptr = lsSubst.GetBuffer(l*nCount); for (UINT i = 1; i <= nCount; ++i, ptr += l) wcscpy_s(ptr, l+1, lsPart); } else { lsSubst.Attach(lsPart.Detach()); } return true; } if (!(MouseMode & ~(tmm_VIM|tmm_SCROLL))) return false; BYTE NewBtns = (m.dwButtonState & 0x1F); if ((NewBtns != MouseButtons) || ((m.dwEventFlags & MOUSE_WHEELED) && HIWORD(m.dwButtonState)) || ((LastMousePos != m.dwMousePosition) && ((MouseMode & tmm_ANY) || ((MouseMode & tmm_BTN) && NewBtns))) ) { // #XTERM_MOUSE Unfortunately, szSubst is too short to pass "missed" coordinates // Like we do for Far events, MouseMove with RBtn pressed in tmm_ANY|tmm_BTN // modes would send all intermediate coordinates between two events BYTE code; bool released = false; if (NewBtns & FROM_LEFT_1ST_BUTTON_PRESSED) code = 0; // MB1 pressed else if (NewBtns & FROM_LEFT_2ND_BUTTON_PRESSED) code = 1; // MB2 pressed else if (NewBtns & RIGHTMOST_BUTTON_PRESSED) code = 2; // MB3 pressed else if (NewBtns & FROM_LEFT_3RD_BUTTON_PRESSED) code = 64; // MB4 pressed else if (NewBtns & FROM_LEFT_4TH_BUTTON_PRESSED) code = 64 + 1; // MB5 pressed else if (m.dwEventFlags & MOUSE_WHEELED) { // #XTERM_MOUSE Post multiple events if dir contains multiple notches short dir = (short)HIWORD(m.dwButtonState); if (dir > 0) code = 64; // MB4 else if (dir < 0) code = 64 + 1; // MB5 } else { released = true; code = 3; } if (m.dwControlKeyState & SHIFT_PRESSED) code |= 4; if (m.dwControlKeyState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)) code |= 8; if (m.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) code |= 16; if ((m.dwEventFlags & MOUSE_MOVED) && (MouseMode & (tmm_BTN|tmm_ANY))) code |= 32; // (1,1) is upper left character position SHORT coord[] = {std::max<SHORT>(0, m.dwMousePosition.X) + 1, std::max<SHORT>(0, m.dwMousePosition.Y) + 1}; if (MouseMode & tmm_XTERM) { msprintf(szSubst, countof(szSubst), L"\033[<%u;%u;%u%c", code, coord[0], coord[1], released ? 'm' : 'M'); } else if (MouseMode & tmm_URXVT) { msprintf(szSubst, countof(szSubst), L"\033[%u;%u;%uM", code + 0x20, coord[0], coord[1]); } else { wcscpy_c(szSubst, L"\033[M"); size_t i = wcslen(szSubst); szSubst[i++] = code + 32; // And coords. Must be in "screen" coordinate space for (size_t s = 0; s < 2; ++s) { // (1,1) is upper left character position if (!(MouseMode & tmm_UTF8)) szSubst[i++] = std::min<unsigned>(255, coord[s] + 32); else if (coord[s] < 0x80) szSubst[i++] = coord[s]; else if (coord[s] < 0x800) { // xterm #262: positions from 96 to 2015 are encoded as a two-byte UTF-8 sequence szSubst[i++] = 0xC0 + (coord[s] >> 6); szSubst[i++] = 0x80 + (coord[s] & 0x3F); } else { // #XTERM_MOUSE Xterm reports out-of-range positions as a NUL byte. szSubst[i++] = 1; // It's impossible to post NUL byte ATM } }