static int PreAnalise(MMap& map, MMap::iterator it, bool& allsame) { int currentRuleIndex = it->m_pNotTerminal->GetIndex(); int currentRule = it->m_RuleIndex; //Faz todos desta regra (até ela mudar) if (it == map.end()) { return 0; } int sub = 0; allsame = true; while (it->m_pNotTerminal->GetIndex() == currentRuleIndex) { if (currentRule != it->m_RuleIndex) { allsame = false; } sub++; it++; if (it == map.end()) { break; } } //retorna quantos tem destra regra return sub; }
CFindPanel::CFindPanel(CConEmuMain* apConEmu) : mp_ConEmu(apConEmu) , mh_Pane(NULL) , mh_Edit(NULL) , mh_Font(NULL) , mn_KeyDown(0) , mn_RebarHeight(0) { if (!g_FindMap.Initialized()) g_FindMap.Init(16); ms_PrevSearch = new CmdArg(); }
void GenerateTreeDebugBreak(DWORD nExcludePID) { _ASSERTE(gpSrv->DbgInfo.bDebugProcessTree); DWORD dwErr = 0; HMODULE hKernel = GetModuleHandle(L"kernel32.dll"); typedef BOOL (WINAPI* DebugBreakProcess_t)(HANDLE Process); DebugBreakProcess_t DebugBreakProcess_f = (DebugBreakProcess_t)(hKernel ? GetProcAddress(hKernel, "DebugBreakProcess") : NULL); if (DebugBreakProcess_f) { _printf("ConEmuC: Sending DebugBreak event to processes:"); DWORD nPID = 0; HANDLE hProcess = NULL; MMap<DWORD,CEDebugProcessInfo>* pDebugTreeProcesses = gpSrv->DbgInfo.pDebugTreeProcesses; CEDebugProcessInfo pi = {}; if (pDebugTreeProcesses->GetNext(NULL, &nPID, &pi)) { while (nPID) { if (nPID != nExcludePID) { _printf(" %u", nPID); if (!pi.hProcess) { pi.hProcess = GetProcessHandleForDebug(nPID); } if (DebugBreakProcess_f(pi.hProcess)) { gpSrv->DbgInfo.nWaitTreeBreaks++; } else { dwErr = GetLastError(); _printf("\nConEmuC: Sending DebugBreak event failed, Code=x%X\n", dwErr); } } if (!pDebugTreeProcesses->GetNext(&nPID, &nPID, &pi)) break; } _printf("\n"); } } else { _printf("ConEmuC: DebugBreakProcess not found in kernel32.dll\n"); } }
void Print(std::wostream& os, MMap& map, Grammar& g) { for (auto it = map.begin(); it != map.end(); it++) { os << L"[" << it->m_pNotTerminal->GetName() << L", " << it->m_pTerminal->GetName() << L"]"; //Print(os, it->m_pTerminal); os << L" : " ; const Production& production = g.GetProduction(it->m_RuleIndex); Print(os , production); os << std::endl; } }
LRESULT CFindPanel::EditCtrlProc(HWND hCtrl, UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRc = 0; CFindPanel* pPanel = NULL; g_FindMap.Get(hCtrl, &pPanel); if (pPanel) switch (uMsg) { case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_CHAR: if (pPanel->OnKeyboard(uMsg, wParam, lParam, lRc)) goto wrap; break; case WM_RBUTTONDOWN: case WM_RBUTTONUP: if (uMsg == WM_RBUTTONUP) pPanel->ShowMenu(); goto wrap; } if (pPanel && pPanel->mfn_EditProc) lRc = ::CallWindowProc(pPanel->mfn_EditProc, hCtrl, uMsg, wParam, lParam); else lRc = ::DefWindowProc(hCtrl, uMsg, wParam, lParam); wrap: return lRc; }
bool CFindPanel::OnCreateFinished() { RECT rcClient = {}; OnSize(&rcClient); if (!mh_Edit) { mh_Edit = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", L"", WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL|ES_WANTRETURN, rcClient.left, rcClient.top, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, mh_Pane, (HMENU)SearchCtrlId, NULL, NULL); if (!mh_Edit) { return false; } g_FindMap.Set(mh_Edit, this); OnCreateFont(); mfn_EditProc = (WNDPROC)SetWindowLongPtr(mh_Edit, GWLP_WNDPROC, (LONG_PTR)EditCtrlProc); EditIconHint_Set(mh_Pane, mh_Edit, true, SearchHint, false, UM_SEARCH, 0); } return true; }
void CFindPanel::OnDestroy() { g_FindMap.Del(mh_Pane); g_FindMap.Del(mh_Edit); SafeDeleteObject(mh_Font); mh_Pane = mh_Edit = NULL; }
SpritePack *SpriteLoader::Load(const std::string &pack) { auto loaded_it = loaded_packs_.find(pack); if (loaded_it != loaded_packs_.end()) return loaded_it->second.get(); fs::path pack_folder = fs::current_path() / "Assets" / "Sprites" / pack; fs::path desc_path = pack_folder / "Pack.toml"; MMap mmap; if (!mmap.Open(desc_path)) { auto msg = "Failed to open pack `" + pack + "` (" + desc_path.generic_string() + ")"; throw std::runtime_error{ msg }; } auto config = TOML::Value::Parse((const char *)mmap.GetMemory(), mmap.GetLength()); auto &config_root = config->GetTable(); // Read the Pack info auto &pack_desc = config_root["Pack"]->GetTable(); auto pack_type_str = pack_desc["Type"]->GetString(); SpritePackType pack_type; if (pack_type_str == "Sprites") pack_type = SpritePackType::Sprites; else if (pack_type_str == "AnimatedGif") pack_type = SpritePackType::AnimatedGif; else throw std::runtime_error{ "Pack `" + pack + "` has an invalid Pack.Type" }; // Read in the sprite list / animated gif std::unique_ptr<SpritePack> pack_ptr; if (pack_type == SpritePackType::Sprites) { pack_ptr = SpritePack::LoadPack(device_.p, pack_folder, config_root); } else if (pack_type == SpritePackType::AnimatedGif) { pack_ptr = GifPack::LoadGif(device_.p, pack_folder, config_root); } auto ppack = pack_ptr.get(); loaded_packs_[pack] = std::move(pack_ptr); return ppack; }
/* Uniqualizer for Each tab */ CTabID::CTabID(CVirtualConsole* apVCon, LPCWSTR asName, CEFarWindowType anType, int anPID, int anFarWindowID, int anViewEditID) { memset(&Info, 0, sizeof(Info)); memset(&DrawInfo, 0, sizeof(DrawInfo)); Info.pVCon = apVCon; Set(asName, anType, anPID, anFarWindowID, anViewEditID); #ifdef DEBUG_TAB_LIST if (!bTabIdListInit) { gTabIdList.Init(256,true); bTabIdListInit = true; } gTabIdList.Set(this, true); #endif }
BOOL WINAPI HookThreadListClose(HANDLE hSnapshot) { if (hSnapshot && (hSnapshot != INVALID_HANDLE_VALUE)) { HookThreadList* p = (HookThreadList*)hSnapshot; gStartedThreads.ReleasePointer(p->pThreadIDs); free(p); return TRUE; } return FALSE; }
// ssh (msysgit) crash issue. Need to know if thread was started by application but not remotely. HANDLE WINAPI OnCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) { //typedef HANDLE(WINAPI* OnCreateThread_t)(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); ORIGINAL_KRNL(CreateThread); DWORD nTemp = 0; LPDWORD pThreadID = lpThreadId ? lpThreadId : &nTemp; HANDLE hThread = F(CreateThread)(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, pThreadID); if (hThread) gStartedThreads.Set(*pThreadID,true); return hThread; }
/// Creates internal thread enumerator handle /// @param dwFlags must be TH32CS_SNAPTHREAD /// @param th32ProcessID ignored, 0 is expected /// @result INVALID_HANDLE_VALUE on errors, or pointer to HookThreadList HANDLE WINAPI HookThreadListCreate(DWORD dwFlags, DWORD th32ProcessID) { HookThreadList* p = (HookThreadList*)calloc(sizeof(HookThreadList),1); p->iCount = gStartedThreads.GetKeysValues(&p->pThreadIDs, NULL); if ((p->iCount <= 0) || (!p->pThreadIDs)) { _ASSERTE(FALSE && "gStartedThreads.GetKeysValues fails"); free(p); return INVALID_HANDLE_VALUE; } return (HANDLE)p; }
void CConEmuChild::DoDestroyDcWindow() { // Set flag immediately mn_AlreadyDestroyed = GetTickCount(); // Go ghDcInDestroing = mh_WndDC; ghBkInDestroing = mh_WndBack; // Remove from MMap before DestroyWindow, because pVCon is no longer Valid if (mh_WndDC) { gVConDcMap.Del(mh_WndDC); DestroyWindow(mh_WndDC); mh_WndDC = NULL; } if (mh_WndBack) { gVConBkMap.Del(mh_WndBack); DestroyWindow(mh_WndBack); mh_WndBack = NULL; } ghDcInDestroing = NULL; ghBkInDestroing = NULL; }
CTabID::~CTabID() { #ifdef _DEBUG wchar_t szDbg[120]; _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"~CTabID(PID=%u IDX=%u TYP=%u '", Info.nPID, Info.nFarWindowID, (UINT)Type()); int nDbgLen = lstrlen(szDbg); lstrcpyn(szDbg+nDbgLen, GetName(), countof(szDbg)-nDbgLen-5); wcscat_c(szDbg, L"')\n"); DEBUGSTRDEL(szDbg); #endif Name.Release(); Renamed.Release(); ReleaseDrawRegion(); #ifdef DEBUG_TAB_LIST gTabIdList.Del(this); #endif }
bool CFindPanel::OnCreate(CREATESTRUCT* ps) { g_FindMap.Set(mh_Pane, this); return true; }
MMap BuildMTable(const FirstSets& first, const FollowSets& follow, Grammar& g) { MMap M; std::wcout << L"\n Building M table \n"; for (int k = 0; k < g.GetNumOfProductions(); k++) { //Para cada producao da gramatica A = alfa const Production& production = g.GetProduction(k); Print(std::wcout, production); //Aqui o first tem que ser em relacao a "alfa" e não a "A" // pois o A engloba todos os "firsts" e aqui se quer o first especifico // desta producao // Entao o FirstSets& first é o "pior caso" o first de qualquer "A" // No aho novo parece que tem um defeito de escrita e que o first deveria // ser first alfa no dois (esta so no segundo) //Nao testei se o follow teria que ter algo assim std::set<const GrammarSymbol*> f = GetFirstSet(first, g, production); //Regra 1 //auto f = first.Get(production.GetLeftSymbol()); for (auto it = f.begin(); it != f.end(); ++it) { // Para cada terminal a em primeiro(A) const GrammarSymbol* pgs = (*it); if (pgs->IsTerminal() && pgs != g.epsilon()) { //M[A, a] = alfa std::wcout << L"[" << production.GetLeftSymbol()->GetName() << L"," << pgs->GetName() << L"] = " ; Print(std::wcout, production); /*if (M.find(MKey(production.GetLeftSymbol(), pgs)) != M.end()) { std::wcout << L"<-- duplicated" << std::endl; throw std::exception("multiple entries"); }*/ auto MTableIt = M.find(MKey(production.GetLeftSymbol(), pgs, k)); if (MTableIt != M.end()) { if (MTableIt->m_pNotTerminal->GetName() != production.GetLeftSymbol()->GetName()) { //if (MTableIt->) //M.insert(MKey(production.GetLeftSymbol(), pgs, k)); std::string strError; strError = "Multiple entries "; strError += to_utf8_string(production.GetLeftSymbol()->GetName()); strError += " -> "; strError += to_utf8_string(pgs->GetName()); throw std::exception(strError.c_str()); } else { //ja existe a regra igual //std::string strError; //strError = "Multiple entries "; //strError += to_utf8_string(production.GetLeftSymbol()->GetName()); //strError += " -> "; //strError += to_utf8_string(pgs->GetName()); //throw std::exception(strError.c_str()); } } else { //criar a regra std::wcout << std::endl; M.insert(MKey(production.GetLeftSymbol(), pgs, k)); } //M[MKey(production.GetLeftSymbol(), pgs)] = k; } else if (pgs == g.epsilon()) { // Nao existe epsilon o input stream // entao vou fazer para cada follow auto fo = follow.Get(production.GetLeftSymbol()); //se esta em folow for (auto it = fo.begin(); it != fo.end(); ++it) { const GrammarSymbol* b = (*it); if (b->IsTerminal() && b != g.epsilon()) //ou $ que da no mesmo { std::wcout << L"[" << production.GetLeftSymbol()->GetName() << L"," << b->GetName() << L"] = " ; Print(std::wcout, production); auto MTableIt = M.find(MKey(production.GetLeftSymbol(), b, k)); if (MTableIt != M.end()) { if (MTableIt->m_pNotTerminal->GetName() != production.GetLeftSymbol()->GetName()) { std::wcout << L"<-- duplicated" << std::endl; throw std::exception("multiple entries"); } else { //std::wcout << L"<-- duplicated" << std::endl; //throw std::exception("multiple entries"); } } else { std::wcout << std::endl; M.insert(MKey(production.GetLeftSymbol(), b, k)); } //M[MKey(production.GetLeftSymbol(), b)] = k; } } } } } return M; }
/// Returns ThreadID of main thread /// /// If the process was started by standard ConEmuC/ConEmuHk functions, /// this function is called with (bUseCurrentAsMain==true) from DllMain. /// Otherwise we must enumerate **all** processes in system, there is no /// way to enumerate only current process threads unfortunately. /// Also, enumerating threads may cause noticeable lags, but we can't /// do anything with that... However, this is rare situation, and in most /// cases main thread ID is initialized with (bUseCurrentAsMain==true). DWORD GetMainThreadId(bool bUseCurrentAsMain) { // Найти ID основной нити if (!gnHookMainThreadId) { if (bUseCurrentAsMain) { // Only one thread is expected at the moment gnHookMainThreadId = GetCurrentThreadId(); } else { DWORD dwPID = GetCurrentProcessId(); #ifdef FORCE_GETMAINTHREAD_PRINTF wchar_t szInfo[160], szTail[32]; msprintf(szInfo, countof(szInfo), L"\x1B[1;31;40m" L"*** [PID=%u %s] GetMainThreadId is using CreateToolhelp32Snapshot", dwPID, gsExeName); wcscpy_c(szTail, L"\x1B[1;31;40m" L" ***" L"\x1B[0m" L"\n"); WriteProcessed2(szInfo, wcslen(szInfo), NULL, wps_Error); #endif // Unfortunately, dwPID is ignored in TH32CS_SNAPTHREAD HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwPID); if (snapshot != INVALID_HANDLE_VALUE) { THREADENTRY32 module = {sizeof(THREADENTRY32)}; if (Thread32First(snapshot, &module)) { // Don't stop enumeration on first thread, populate gStartedThreads do { if (module.th32OwnerProcessID == dwPID) { DWORD nTID = module.th32ThreadID; if (!gnHookMainThreadId) gnHookMainThreadId = nTID; if (!gStartedThreads.Get(nTID, NULL)) gStartedThreads.Set(nTID, FALSE); } } while (Thread32Next(snapshot, &module)); } CloseHandle(snapshot); } #ifdef FORCE_GETMAINTHREAD_PRINTF WriteProcessed2(szTail, wcslen(szTail), NULL, wps_Error); #endif } } #ifdef _DEBUG char szInfo[100]; msprintf(szInfo, countof(szInfo), "GetMainThreadId()=%u, TID=%u\n", gnHookMainThreadId, GetCurrentThreadId()); //OutputDebugStringA(szInfo); #endif _ASSERTE(gnHookMainThreadId!=0); return gnHookMainThreadId; }
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; }
LRESULT CConEmuChild::ChildWndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam) { LRESULT result = 0; // Logger MSG msgStr = {hWnd, messg, wParam, lParam}; ConEmuMsgLogger::Log(msgStr, ConEmuMsgLogger::msgCanvas); 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) { gVConDcMap.Set(hWnd, pVCon); pVCon->m_TAutoCopy.Init(hWnd, TIMER_AUTOCOPY, TIMER_AUTOCOPY_DELAY); pVCon->m_TScrollShow.Init(hWnd, TIMER_SCROLL_SHOW, TIMER_SCROLL_SHOW_DELAY); pVCon->m_TScrollHide.Init(hWnd, TIMER_SCROLL_HIDE, TIMER_SCROLL_HIDE_DELAY); #ifndef SKIP_HIDE_TIMER pVCon->m_TScrollCheck.Init(hWnd, TIMER_SCROLL_CHECK, TIMER_SCROLL_CHECK_DELAY); #endif } } else if (hWnd != ghDcInDestroing) { if (!gVConDcMap.Get(hWnd, &pVCon) || !guard.Attach(pVCon)) pVCon = NULL; } if (messg == WM_SYSCHAR) { _ASSERTE(FALSE); // по идее, фокуса тут быть не должно // Чтобы не пищало result = TRUE; goto wrap; } if (!pVCon) { _ASSERTE(pVCon!=NULL || hWnd==ghDcInDestroing); result = DefWindowProc(hWnd, messg, wParam, lParam); goto wrap; } switch (messg) { case WM_SHOWWINDOW: { #ifdef _DEBUG HWND hGui = pVCon->GuiWnd(); if (hGui) { _ASSERTE(((wParam==0) || pVCon->RCon()->isGuiForceConView()) && "Show DC while GuiWnd exists"); } #endif result = DefWindowProc(hWnd, messg, wParam, lParam); break; } case WM_SETFOCUS: // Если в консоли работает "GUI" окно (GUI режим), то фокус нужно отдать туда. { // Фокус должен быть в главном окне! За исключением случая работы в GUI режиме. pVCon->setFocus(); } return 0; case WM_ERASEBKGND: result = 0; break; case WM_PAINT: result = pVCon->OnPaint(); break; case WM_PRINTCLIENT: if (wParam && (lParam & PRF_CLIENT)) { pVCon->PrintClient((HDC)wParam, false, NULL); } break; case WM_SIZE: #ifdef _DEBUG { RECT rc; GetClientRect(hWnd, &rc); short cx = LOWORD(lParam); rc.left = rc.left; } #endif result = pVCon->OnSize(wParam, lParam); break; case WM_MOVE: result = pVCon->OnMove(wParam, lParam); break; case WM_CREATE: 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; static bool bInFixStyle = false; if (!bInFixStyle) { hParent = GetParent(hWnd); if (hParent != ghWnd) { // Неправомерные действия плагинов фара? bInFixStyle = true; _ASSERTE(GetParent(hWnd)==ghWnd); SetParent(hWnd, ghWnd); bInFixStyle = false; hParent = ghWnd; } DWORD curStyle = GetWindowLong(hWnd, GWL_STYLE); if ((curStyle & CRITICAL_DCWND_STYLES) != (pVCon->mn_WndDCStyle & CRITICAL_DCWND_STYLES)) { // DC window styles was changed externally! bInFixStyle = true; _ASSERTEX(((curStyle & CRITICAL_DCWND_STYLES) != (pVCon->mn_WndDCStyle & CRITICAL_DCWND_STYLES))); SetWindowLongPtr(hWnd, GWL_STYLE, (LONG_PTR)(DWORD_PTR)pVCon->mn_WndDCStyle); bInFixStyle = false; } } 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_TIMER: { switch(wParam) { #ifndef SKIP_HIDE_TIMER // Не будем прятать по таймеру - только по движению мышки case TIMER_SCROLL_CHECK: if (pVCon->mb_Scroll2Visible) { if (!pVCon->CheckMouseOverScroll()) { pVCon->HideScroll(FALSE/*abImmediate*/); } } break; #endif case TIMER_SCROLL_SHOW: if (pVCon->CheckMouseOverScroll() || pVCon->CheckScrollAutoPopup()) pVCon->ShowScroll(TRUE/*abImmediate*/); else pVCon->mb_Scroll2Visible = FALSE; if (pVCon->m_TScrollShow.IsStarted()) pVCon->m_TScrollShow.Stop(); break; case TIMER_SCROLL_HIDE: if (!pVCon->CheckMouseOverScroll()) pVCon->HideScroll(TRUE/*abImmediate*/); else pVCon->mb_Scroll2Visible = TRUE; if (pVCon->m_TScrollHide.IsStarted()) pVCon->m_TScrollHide.Stop(); break; case TIMER_AUTOCOPY: pVCon->SetAutoCopyTimer(false); if (!isPressed(VK_LBUTTON)) { pVCon->RCon()->AutoCopyTimer(); } break; } break; } // case WM_TIMER: case WM_GESTURENOTIFY: case WM_GESTURE: { gpConEmu->ProcessGestureMessage(hWnd, messg, wParam, lParam, result); break; } // case WM_GESTURE, WM_GESTURENOTIFY default: // Сообщение приходит из ConEmuPlugin if (messg == pVCon->mn_MsgTabChanged) { if (gpSet->isTabs) { //изменились табы, их нужно перечитать #ifdef MSGLOGGER WCHAR szDbg[128]; _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"Tabs:Notified(%i)\n", (DWORD)wParam); DEBUGSTRTABS(szDbg); #endif TODO("здесь хорошо бы вместо OnTimer реально обновить mn_TopProcessID") // иначе во время запуска PID фара еще может быть не известен... //gpConEmu->OnTimer(0,0); не получилось. индекс конмана не менялся, из-за этого индекс активного фара так и остался 0 WARNING("gpConEmu->mp_TabBar->Retrieve() ничего уже не делает вообще"); _ASSERTE(FALSE); gpConEmu->mp_TabBar->Retrieve(); } } else if (messg == pVCon->mn_MsgPostFullPaint) { pVCon->Redraw(); } else if (messg == pVCon->mn_MsgSavePaneSnapshoot) { pVCon->SavePaneSnapshoot(); } else if (messg == pVCon->mn_MsgDetachPosted) { pVCon->RCon()->Detach(true, (lParam == 1)); } else if (messg == gn_MsgVConTerminated) { CVirtualConsole* pVCon = (CVirtualConsole*)lParam; #ifdef _DEBUG int i = -100; wchar_t szDbg[200]; { lstrcpy(szDbg, L"gn_MsgVConTerminated"); i = CVConGroup::GetVConIndex(pVCon); if (i >= 1) { ConEmuTab tab = {0}; pVCon->RCon()->GetTab(0, &tab); tab.Name[128] = 0; // чтобы не вылезло из szDbg wsprintf(szDbg+_tcslen(szDbg), L": #%i: %s", i, tab.Name); } lstrcat(szDbg, L"\n"); DEBUGSTRCONS(szDbg); } #endif // Do not "Guard" lParam here, validation will be made in ProcessVConClosed CConEmuChild::ProcessVConClosed(pVCon, TRUE); return 0; } #ifdef _DEBUG else if (messg == pVCon->mn_MsgCreateDbgDlg) { pVCon->CreateDbgDlg(); } #endif else if (messg) { result = DefWindowProc(hWnd, messg, wParam, lParam); } } wrap: return result; }
void GenerateDescRecC(std::wostream& os, Grammar& g, MMap& map, const std::wstring& tokenPrefix, const std::wstring& parserFileSuffix) { if (map.empty()) { return; } PrintGeneratedFileHeader(os); PrintGeneratedFileLicense(os); os << L"\n"; os << L"#include \"stdafx.h\"\n"; os << L"#include <assert.h>\n"; os << L"\n"; os << L"#include \"" << g.GetModuleName() << L"Lex.h\"\n"; os << L"#include \"" << g.GetModuleName() << parserFileSuffix << L".h\"\n"; os << L"\n"; os << L"\n"; //os << L"#include \"sstream.h\"\n"; //os << L"#include \"errors.h\"\n"; os << L"\n"; os << L"\n"; PrintActionsNames(os, g, false); //PrintActions(os, g, false); os << L"\n"; PrintFowardDeclarations(os, g, map); std::wstring ws(SourceCode); find_replace(ws, L"{GRAMMAR}", g.GetLanguageName()); find_replace(ws, L"{MODULE}", g.GetLanguageName()); os << ws; int i = 0; int currentRuleIndex = -1; auto it = map.begin(); int rulecount = 0; for (; it != map.end();) { int currentRuleIndex = it->m_pNotTerminal->GetIndex(); //Faz todos desta regra (até ela mudar) os << L"Result " << GetFunctionName(g, it->m_pNotTerminal->GetName()) << L"( " << g.GetLanguageName() + L"_Context* ctx)\n"; os << L"{\n"; os << TAB_1 << L"Result result = RESULT_OK;\n"; os << TAB_1 << L"" << g.GetLanguageName() << L"_Tokens token = ctx->token; \n"; os << L"\n"; int sub = 0; rulecount = 0; while (it->m_pNotTerminal->GetIndex() == currentRuleIndex) { int currentResultIndex = it->m_RuleIndex; //faz todos que resultam na mesma producao int count = 0; while (currentResultIndex == it->m_RuleIndex) { if (count == 0) { os << TAB_1; if (rulecount > 0) { os << L"else "; } os << L"if (token == " << tokenPrefix << it->m_pTerminal->GetName(); } else { os << L" ||\n"; os << TAB_1 << L" token == " << tokenPrefix << it->m_pTerminal->GetName(); } auto itcopy = it; it++; count++; if (it == map.end() || currentResultIndex != it->m_RuleIndex) { os << L")\n"; //fecha if const Production& production = g.GetProduction(itcopy->m_RuleIndex); os << TAB_1 << L"{\n"; os << TAB__2; os << L"/*"; Print(os, production); os << L"*/\n"; PrintProduction(os, production, g, tokenPrefix, TAB__2); os << TAB_1 << L"}\n"; break; } if (it == map.end()) { break; } } /* if (it != map.end()) { it++; } */ if (it == map.end()) { break; } rulecount++; } //regra os << TAB_1 << L"else\n"; os << TAB_1 << L"{\n"; os << TAB__2 << g.GetLanguageName() << L"_OnAction(ctx, " << g.GetLanguageName() << L"_OnError); \n"; os << TAB__2 << L"return RESULT_FAIL;\n"; os << TAB_1 << L"}\n"; os << L"\n"; os << TAB_1 << L"return result;\n"; os << L"}\n\n"; } }
void TriMesh::rebuildTopology(Float maxAngle) { typedef std::multimap<Vertex, TopoData, vertex_key_order> MMap; typedef std::pair<Vertex, TopoData> MPair; const Float dpThresh = std::cos(degToRad(maxAngle)); if (m_normals) { delete[] m_normals; m_normals = NULL; } if (m_tangents) { delete[] m_tangents; m_tangents = NULL; } Log(EInfo, "Rebuilding the topology of \"%s\" (" SIZE_T_FMT " triangles, " SIZE_T_FMT " vertices, max. angle = %f)", m_name.c_str(), m_triangleCount, m_vertexCount, maxAngle); ref<Timer> timer = new Timer(); MMap vertexToFace; std::vector<Point> newPositions; std::vector<Point2> newTexcoords; std::vector<Spectrum> newColors; std::vector<Normal> faceNormals(m_triangleCount); Triangle *newTriangles = new Triangle[m_triangleCount]; newPositions.reserve(m_vertexCount); if (m_texcoords != NULL) newTexcoords.reserve(m_vertexCount); if (m_colors != NULL) newColors.reserve(m_vertexCount); /* Create an associative list and precompute a few things */ for (size_t i=0; i<m_triangleCount; ++i) { const Triangle &tri = m_triangles[i]; Vertex v; for (int j=0; j<3; ++j) { v.p = m_positions[tri.idx[j]]; if (m_texcoords) v.uv = m_texcoords[tri.idx[j]]; if (m_colors) v.col = m_colors[tri.idx[j]]; vertexToFace.insert(MPair(v, TopoData(i, false))); } Point v0 = m_positions[tri.idx[0]]; Point v1 = m_positions[tri.idx[1]]; Point v2 = m_positions[tri.idx[2]]; faceNormals[i] = Normal(normalize(cross(v1 - v0, v2 - v0))); for (int j=0; j<3; ++j) newTriangles[i].idx[j] = 0xFFFFFFFFU; } /* Under the reasonable assumption that the vertex degree is bounded by a constant, the following runs in O(n) */ for (MMap::iterator it = vertexToFace.begin(); it != vertexToFace.end();) { MMap::iterator start = vertexToFace.lower_bound(it->first); MMap::iterator end = vertexToFace.upper_bound(it->first); /* Perform a greedy clustering of normals */ for (MMap::iterator it2 = start; it2 != end; it2++) { const Vertex &v = it2->first; const TopoData &t1 = it2->second; Normal n1(faceNormals[t1.idx]); if (t1.clustered) continue; uint32_t vertexIdx = (uint32_t) newPositions.size(); newPositions.push_back(v.p); if (m_texcoords) newTexcoords.push_back(v.uv); if (m_colors) newColors.push_back(v.col); for (MMap::iterator it3 = it2; it3 != end; ++it3) { TopoData &t2 = it3->second; if (t2.clustered) continue; Normal n2(faceNormals[t2.idx]); if (n1 == n2 || dot(n1, n2) > dpThresh) { const Triangle &tri = m_triangles[t2.idx]; Triangle &newTri = newTriangles[t2.idx]; for (int i=0; i<3; ++i) { if (m_positions[tri.idx[i]] == v.p) newTri.idx[i] = vertexIdx; } t2.clustered = true; } } } it = end; } for (size_t i=0; i<m_triangleCount; ++i) for (int j=0; j<3; ++j) Assert(newTriangles[i].idx[j] != 0xFFFFFFFFU); delete[] m_triangles; m_triangles = newTriangles; delete[] m_positions; m_positions = new Point[newPositions.size()]; memcpy(m_positions, &newPositions[0], sizeof(Point) * newPositions.size()); if (m_texcoords) { delete[] m_texcoords; m_texcoords = new Point2[newTexcoords.size()]; memcpy(m_texcoords, &newTexcoords[0], sizeof(Point2) * newTexcoords.size()); } if (m_colors) { delete[] m_colors; m_colors = new Spectrum[newColors.size()]; memcpy(m_colors, &newColors[0], sizeof(Spectrum) * newColors.size()); } m_vertexCount = newPositions.size(); Log(EInfo, "Done after %i ms (mesh now has " SIZE_T_FMT " vertices)", timer->getMilliseconds(), m_vertexCount); computeNormals(); }
static void GenerateDescRec3(std::wostream& os, Grammar& g, MMap& map, const std::wstring& tokenPrefix) { if (map.empty()) { return; } PrintGeneratedFileHeader(os); PrintGeneratedFileLicense(os); os << L"#pragma once\n"; os << L"\n"; os << L"#include <string.h>\n"; os << L"#include \"" << g.GetModuleName() << L"Lex.h\"\n"; os << L"\n"; os << L"\n"; //PrintOutputClass(os, g); PrintFowardDeclarations(os, g, map); int i = 0; int sub = 0; int currentRuleIndex = -1; auto it = map.begin(); for (; it != map.end();) { int currentRuleIndex = it->m_pNotTerminal->GetIndex(); //Faz todos desta regra (até ela mudar) os << TAB_1 << L"int " << GetFunctionName(g, it->m_pNotTerminal->GetName()) << L"( " << g.GetLanguageName() << L"_Context* ctx)\n"; os << TAB_1 << L"{\n"; int sub = 0; bool allsame = false; bool firstPrinted = false; if (PreAnalise(map, it, allsame) == 1) { //se so tem um nao precisa testar pelo token pois sempre haver um teste //a seguir de qualquer forma const Production& production = g.GetProduction(it->m_RuleIndex); os << TAB__2 << L"//"; Print(os, production); os << L"\n"; PrintProduction(os, production, g, tokenPrefix, TAB__2); it++; } else { while (it->m_pNotTerminal->GetIndex() == currentRuleIndex) { //se todos forem iguais nao testa pelo token //e so imprimi o primeiro que eh igual aos outros if (!allsame) { if (sub == 0) { os << TAB__2 << L"if (IsToken(ctx, " << tokenPrefix << it->m_pTerminal->GetName() << L"))\n"; } else { os << TAB__2 << L"else if (IsToken(ctx, " << tokenPrefix << it->m_pTerminal->GetName() << L"))\n"; } } const Production& production = g.GetProduction(it->m_RuleIndex); if (!allsame) { os << TAB__2 << L"{\n"; } if (!allsame || (allsame && !firstPrinted)) { os << (!allsame ? TAB___3 : TAB__2); os << L"/*"; Print(os, production); os << L"*/\n"; PrintProduction(os, production, g, tokenPrefix, !allsame ? TAB___3 : TAB__2); if (!allsame) { os << TAB__2 << L"}\n"; } } sub++; it++; if (it == map.end()) { break; } firstPrinted = true; } } os << TAB_1 << L"}\n\n"; } }
LRESULT CFindPanel::FindPaneProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR lRc = 0; CFindPanel* pPanel = NULL; RECT rcClient = {}; if (uMsg == WM_CREATE) { if (lParam && ((CREATESTRUCT*)lParam)->lpCreateParams) { pPanel = (CFindPanel*)((CREATESTRUCT*)lParam)->lpCreateParams; pPanel->mh_Pane = hWnd; } } else { g_FindMap.Get(hWnd, &pPanel); } if (pPanel && EditIconHint_Process(hWnd, uMsg, wParam, lParam, lRc)) { return lRc; } switch (uMsg) { case WM_CREATE: if (!pPanel || !((CFindPanel*)((CREATESTRUCT*)lParam)->lpCreateParams)->OnCreate((CREATESTRUCT*)lParam)) { lRc = -1; goto wrap; } break; case WM_COMMAND: switch (HIWORD(wParam)) { case BN_CLICKED: goto wrap; } break; case WM_WINDOWPOSCHANGING: if (pPanel) pPanel->OnWindowPosChanging((WINDOWPOS*)lParam); break; case WM_SIZE: case WM_MOVE: if (pPanel) pPanel->OnSize(NULL); break; case WM_DESTROY: if (pPanel) pPanel->OnDestroy(); break; case UM_SEARCH: if (pPanel) pPanel->OnSearch(); break; } lRc = ::DefWindowProc(hWnd, uMsg, wParam, lParam); wrap: return lRc; }
void CTabBarClass::Update(BOOL abPosted/*=FALSE*/) { #ifdef _DEBUG if (this != gpConEmu->mp_TabBar) { _ASSERTE(this == gpConEmu->mp_TabBar); } #endif MCHKHEAP /*if (!_active) { return; }*/ // Теперь - ВСЕГДА! т.к. сами управляем мультиконсолью if (mb_DisableRedraw) { _ASSERTE(FALSE && "mb_DisableRedraw?"); // Надо? return; } if (!isMainThread()) { RequestPostUpdate(); return; } gpConEmu->mp_Status->UpdateStatusBar(); mb_PostUpdateCalled = FALSE; #ifdef _DEBUG _ASSERTE(mn_InUpdate >= 0); if (mn_InUpdate > 0) { _ASSERTE(mn_InUpdate == 0); } #endif mn_InUpdate ++; MCHKHEAP int V, I, tabIdx = 0, nCurTab = -1; BOOL bShowFarWindows = gpSet->bShowFarWindows; // Выполняться должно только в основной нити, так что CriticalSection не нужна #ifdef _DEBUG if (this != gpConEmu->mp_TabBar) { _ASSERTE(this == gpConEmu->mp_TabBar); } #endif TODO("Обработка gpSet->bHideInactiveConsoleTabs для новых табов"); MCHKHEAP // Check if we need to AutoSHOW or AutoHIDE tab bar if (!IsTabsActive() && gpSet->isTabs) { int nTabs = CountActiveTabs(2); if (nTabs > 1) { Activate(); } } else if (IsTabsActive() && gpSet->isTabs==2) { int nTabs = CountActiveTabs(2); if (nTabs <= 1) { Deactivate(); } } // Validation? #ifdef _DEBUG if (this != gpConEmu->mp_TabBar) { _ASSERTE(this == gpConEmu->mp_TabBar); } #endif MCHKHEAP HANDLE hUpdate = m_Tabs.UpdateBegin(); _ASSERTE(hUpdate!=NULL); bool bStackChanged = false; /* ********************* */ /* Go */ /* ********************* */ { MMap<CVConGroup*,CVirtualConsole*> Groups; Groups.Init(MAX_CONSOLE_COUNT, true); for (V = 0; V < MAX_CONSOLE_COUNT; V++) { //if (!(pVCon = gpConEmu->GetVCon(V))) continue; CVConGuard guard; if (!CVConGroup::GetVCon(V, &guard)) continue; CVirtualConsole* pVCon = guard.VCon(); BOOL lbActive = pVCon->isActive(false); if (gpSet->bHideInactiveConsoleTabs && !lbActive) continue; if (gpSet->isOneTabPerGroup) { CVConGroup *pGr; CVConGuard VGrActive; if (CVConGroup::isGroup(pVCon, &pGr, &VGrActive)) { CVirtualConsole* pGrVCon; if (Groups.Get(pGr, &pGrVCon)) continue; // эта группа уже есть pGrVCon = VGrActive.VCon(); Groups.Set(pGr, pGrVCon); // И показывать таб нужно от "активной" консоли, а не от первой в группе if (pVCon != pGrVCon) { guard = pGrVCon; pVCon = pGrVCon; } if (!lbActive) { lbActive = pVCon->isActive(true); } // Показывать редакторы из всех групп? if (gpSet->bShowFarWindows) { MArray<CVConGuard*> Panes; int nPanes = pGr->GetGroupPanes(&Panes); // Только если в группе более одного таба - тогда нужно дополниетльная логика населения... if (nPanes > 1) { // Первым табом - показать текущую панель, либо МОДАЛЬНЫЙ редактор/вьювер // Редакторы из "far /e ..." здесь НЕ добавлять! if (!pVCon->RCon()->isFarPanelAllowed() || !UpdateAddTab(hUpdate, tabIdx, nCurTab, bStackChanged, pVCon, uat_PanelsOrModalsOnly)) { // Если есть - добавить ОДНУ панель, чтобы табы сплита не прыгали туда-сюда for (int K = 0; K < nPanes; K++) { if (Panes[K]->VCon()->RCon()->isFarPanelAllowed()) { if (UpdateAddTab(hUpdate, tabIdx, nCurTab, bStackChanged, Panes[K]->VCon(), uat_PanelsOnly) > 0) break; } } } // Потом - все оставшиеся редакторы/вьюверы (в том числе и "far /e ...") for (int K = 0; K < nPanes; K++) { UpdateAddTab(hUpdate, tabIdx, nCurTab, bStackChanged, Panes[K]->VCon(), uat_NonModals|uat_NonPanels); } // Release CVConGroup::FreePanesArray(Panes); // Already processed, next VCon continue; } } } } UpdateAddTab(hUpdate, tabIdx, nCurTab, bStackChanged, pVCon, uat_AnyTab); } Groups.Release(); } MCHKHEAP // Must be at least one tab ("ConEmu -Detached" for example) if (tabIdx == 0) { m_Tabs.UpdateAppend(hUpdate, mp_DummyTab, FALSE); // Физически (WinAPI) добавляет закладку, или меняет (при необходимости) заголовок существующей mp_Rebar->AddTabInt(gpConEmu->GetDefaultTabLabel(), tabIdx, gpConEmu->mb_IsUacAdmin, -1); nCurTab = tabIdx; tabIdx++; } m_Tabs.UpdateEnd(hUpdate, 0); // Проверим стек последних выбранных if (CheckStack()) bStackChanged = true; #ifdef PRINT_RECENT_STACK PrintRecentStack(); #endif #ifdef _DEBUG static int nPrevVisible, nPrevStacked; { wchar_t szDbg[100]; int nNewVisible = m_Tabs.GetCount(); int nNewStacked = m_TabStack.size(); _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"*** Tab list updated. Visible:%u, Stacked:%u, StackChanged:%s\n", nNewVisible, nNewStacked, bStackChanged ? L"Yes" : L"No"); DEBUGSTRCOUNT(szDbg); nPrevVisible = nNewVisible; nPrevStacked = nNewStacked; } #endif // удалить лишние закладки (визуально) int nCurCount = GetItemCount(); #ifdef _DEBUG wchar_t szDbg[128]; _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"CTabBarClass::Update. ItemCount=%i, PrevItemCount=%i\n", tabIdx, nCurCount); DEBUGSTRTABS(szDbg); #endif if (mp_Rebar->IsTabbarCreated()) { for (I = tabIdx; I < nCurCount; I++) { #ifdef _DEBUG _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L" Deleting tab=%i\n", I+1); DEBUGSTRTABS(szDbg); #endif DeleteItem(tabIdx); } } MCHKHEAP if (mb_InKeySwitching) { if (mn_CurSelTab >= nCurCount) // Если выбранный таб вылез за границы mb_InKeySwitching = false; } if (!mb_InKeySwitching && nCurTab != -1) { SelectTab(nCurTab); } UpdateToolConsoles(); //if (gpSet->isTabsInCaption) //{ // SendMessage(ghWnd, WM_NCPAINT, 0, 0); //} mn_InUpdate --; if (mb_PostUpdateRequested) { mb_PostUpdateCalled = FALSE; mb_PostUpdateRequested = FALSE; RequestPostUpdate(); } MCHKHEAP return; // Just for clearness }
/// Workaround for cygwin's ssh crash when third-party hooking application exists void FixSshThreads(int iStep) { DLOG0("FixSshThreads",iStep); #ifdef _DEBUG char szInfo[120]; DWORD nErr; msprintf(szInfo, countof(szInfo), "FixSshThreads(%u) started\n", iStep); if (!(gnDllState & ds_DllProcessDetach)) OutputDebugStringA(szInfo); #endif switch (iStep) { // Resume suspended threads case 1: { // Was initialized? if (!pThInfo) break; // May occurs in several threads simultaneously long n = InterlockedIncrement(&gnFixSshThreadsResumeOk); if (n > 1) break; // Resume all suspended... for (INT_PTR i = 0; i < pThInfo->size(); i++) ResumeThread((*pThInfo)[i].hThread); break; } // Suspend all third-party threads case 0: { _ASSERTEX(gnHookMainThreadId!=0); pThInfo = new MArray<ThInfoStr>; HANDLE hThread = NULL, hSnap = NULL; DWORD nTID = 0, dwPID = GetCurrentProcessId(); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwPID); if (snapshot == INVALID_HANDLE_VALUE) { #ifdef _DEBUG nErr = GetLastError(); msprintf(szInfo, countof(szInfo), "CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD) failed in FixSshThreads, code=%u\n", nErr); if (!(gnDllState & ds_DllProcessDetach)) OutputDebugStringA(szInfo); #endif } else { THREADENTRY32 module = {sizeof(THREADENTRY32)}; if (!Thread32First(snapshot, &module)) { #ifdef _DEBUG nErr = GetLastError(); msprintf(szInfo, countof(szInfo), "Thread32First failed in FixSshThreads, code=%u\n", nErr); if (!(gnDllState & ds_DllProcessDetach)) OutputDebugStringA(szInfo); #endif } else do { if ((module.th32OwnerProcessID == dwPID) && (gnHookMainThreadId != module.th32ThreadID)) { // JIC, add thread ID to our list. // In theory, all thread must be already initialized // either from DLL_THREAD_ATTACH, or from GetMainThreadId. if (!gStartedThreads.Get(module.th32ThreadID, NULL)) gStartedThreads.Set(module.th32ThreadID, FALSE); // Don't freeze our own threads if (gpHookServer && gpHookServer->IsPipeThread(module.th32ThreadID)) continue; hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, module.th32ThreadID); if (!hThread) { #ifdef _DEBUG nErr = GetLastError(); msprintf(szInfo, countof(szInfo), "OpenThread(%u) failed in FixSshThreads, code=%u\n", module.th32ThreadID, nErr); if (!(gnDllState & ds_DllProcessDetach)) OutputDebugStringA(szInfo); #endif } else { DWORD nSC = SuspendThread(hThread); if (nSC == (DWORD)-1) { // Error! #ifdef _DEBUG nErr = GetLastError(); msprintf(szInfo, countof(szInfo), "SuspendThread(%u) failed in FixSshThreads, code=%u\n", module.th32ThreadID, nErr); if (!(gnDllState & ds_DllProcessDetach)) OutputDebugStringA(szInfo); #endif } else { ThInfoStr th = {module.th32ThreadID, hThread}; pThInfo->push_back(th); #ifdef _DEBUG msprintf(szInfo, countof(szInfo), "Thread %u was suspended\n", module.th32ThreadID); if (!(gnDllState & ds_DllProcessDetach)) OutputDebugStringA(szInfo); #endif } } } } while (Thread32Next(snapshot, &module)); CloseHandle(snapshot); } break; } } #ifdef _DEBUG msprintf(szInfo, countof(szInfo), "FixSshThreads(%u) finished\n", iStep); if (!(gnDllState & ds_DllProcessDetach)) OutputDebugStringA(szInfo); #endif DLOGEND(); }