diff --git a/IDE/src/Debugger/DebugManager.bf b/IDE/src/Debugger/DebugManager.bf index 4933ae48..56a6f761 100644 --- a/IDE/src/Debugger/DebugManager.bf +++ b/IDE/src/Debugger/DebugManager.bf @@ -104,6 +104,19 @@ namespace IDE.Debugger AllowStringView = 0x800 } + //[Flags] + public enum OutputFilterFlags + { + None = 0x0, + ModuleLoadMessages = 0x1, + ModuleUnloadMessages = 0x2, + ProcessExitMessages = 0x4, + ThreadCreateMessages = 0x8, + ThreadExitMessages = 0x10, + SymbolLoadMessages = 0x20, + ProgramOutput = 0x30 + } + [Reflect] public enum SymSrvFlags { @@ -386,6 +399,12 @@ namespace IDE.Debugger [CallingConvention(.Stdcall), CLink] static extern char8* Debugger_GetEmitSource(char8* fileName); + [CallingConvention(.Stdcall), CLink] + static extern void Debugger_SetOutputFilterFlags(int32 flags); + + [CallingConvention(.Stdcall), CLink] + static extern int32 Debugger_GetOutputFilterFlags(); + public String mRunningPath ~ delete _; public bool mIsRunning; public bool mIsRunningCompiled; @@ -1285,5 +1304,15 @@ namespace IDE.Debugger outString.Append(stackId); return true; } + + public void SetOutputFilterFlags(OutputFilterFlags outputFilterFlags) + { + Debugger_SetOutputFilterFlags((int32)outputFilterFlags); + } + + public OutputFilterFlags GetOutputFilterFlags() + { + return (OutputFilterFlags)Debugger_GetOutputFilterFlags(); + } } } diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 249f1227..45477335 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -2011,6 +2011,23 @@ namespace IDE } sd.RemoveIfEmpty(); } + + using (sd.CreateObject("OutputFilters")) + { + IDE.Debugger.DebugManager.OutputFilterFlags outputFilterFlags = 0; + if (gApp.mDebugger != null) + { + outputFilterFlags = gApp.mDebugger.GetOutputFilterFlags(); + } + + sd.Add("ModuleLoadMessages", outputFilterFlags.HasFlag(.ModuleLoadMessages)); + sd.Add("ModuleUnloadMessages", outputFilterFlags.HasFlag(.ModuleUnloadMessages)); + sd.Add("ProcessExitMessages", outputFilterFlags.HasFlag(.ProcessExitMessages)); + sd.Add("ThreadCreateMessages", outputFilterFlags.HasFlag(.ThreadCreateMessages)); + sd.Add("ThreadExitMessages", outputFilterFlags.HasFlag(.ThreadExitMessages)); + sd.Add("SymbolLoadMessages", outputFilterFlags.HasFlag(.SymbolLoadMessages)); + sd.Add("ProgramOutput", outputFilterFlags.HasFlag(.ProgramOutput)); + } } bool SaveWorkspaceUserData(bool showErrors = true) @@ -3466,6 +3483,24 @@ namespace IDE mDebugger.CreateStepFilter(filter, false, .NotFiltered); } + using (data.Open("OutputFilters")) + { + IDE.Debugger.DebugManager.OutputFilterFlags outputFilterFlags = 0; + + outputFilterFlags |= data.GetBool("ModuleLoadMessages", false) ? .ModuleLoadMessages : 0; + outputFilterFlags |= data.GetBool("ModuleUnloadMessages", false) ? .ModuleUnloadMessages : 0; + outputFilterFlags |= data.GetBool("ProcessExitMessages", false) ? .ProcessExitMessages : 0; + outputFilterFlags |= data.GetBool("ThreadCreateMessages", false) ? .ThreadCreateMessages : 0; + outputFilterFlags |= data.GetBool("ThreadExitMessages", false) ? .ThreadExitMessages : 0; + outputFilterFlags |= data.GetBool("SymbolLoadMessages", false) ? .SymbolLoadMessages : 0; + outputFilterFlags |= data.GetBool("ProgramOutput", false) ? .ProgramOutput : 0; + + if (gApp.mDebugger != null) + { + gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags); + } + } + return true; } diff --git a/IDE/src/ui/OutputWidget.bf b/IDE/src/ui/OutputWidget.bf index 20c031bb..1f91da0d 100644 --- a/IDE/src/ui/OutputWidget.bf +++ b/IDE/src/ui/OutputWidget.bf @@ -244,15 +244,100 @@ namespace IDE.ui Menu menu = new Menu(); - var menuItem = menu.AddItem("Clear All"); + var menuItemClearAll = menu.AddItem("Clear All"); var panel = mParent.mParent.mParent as TextPanel; - menuItem.mOnMenuItemSelected.Add(new (evt) => - { + menuItemClearAll.mOnMenuItemSelected.Add(new (evt) => + { if (panel != null) panel.Clear(); else - ClearText(); - }); + ClearText(); + }); + + // Separator + menu.AddItem(); + + IDE.Debugger.DebugManager.OutputFilterFlags outputFilterFlags = gApp.mDebugger.GetOutputFilterFlags(); + + var menuItemModuleLoadMessages = menu.AddItem("Module Load Messages"); + if (!outputFilterFlags.HasFlag(.ModuleLoadMessages)) + { + menuItemModuleLoadMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check); + } + + menuItemModuleLoadMessages.mOnMenuItemSelected.Add(new (evt) => + { + gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ModuleLoadMessages); + }); + + var menuItemModuleUnloadMessages = menu.AddItem("Module Unload Messages"); + if (!outputFilterFlags.HasFlag(.ModuleUnloadMessages)) + { + menuItemModuleUnloadMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check); + } + + menuItemModuleUnloadMessages.mOnMenuItemSelected.Add(new (evt) => + { + gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ModuleUnloadMessages); + }); + + var menuItemProcessExitMessages = menu.AddItem("Process Exit Messages"); + if (!outputFilterFlags.HasFlag(.ProcessExitMessages)) + { + menuItemProcessExitMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check); + } + + menuItemProcessExitMessages.mOnMenuItemSelected.Add(new (evt) => + { + gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ProcessExitMessages); + }); + + var menuItemThreadCreateMessages = menu.AddItem("Thread Creation Messages"); + if (!outputFilterFlags.HasFlag(.ThreadCreateMessages)) + { + menuItemThreadCreateMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check); + } + + menuItemThreadCreateMessages.mOnMenuItemSelected.Add(new (evt) => + { + gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ThreadCreateMessages); + }); + + var menuItemThreadExitMessages = menu.AddItem("Thread Exit Messages"); + if (!outputFilterFlags.HasFlag(.ThreadExitMessages)) + { + menuItemThreadExitMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check); + } + + menuItemThreadExitMessages.mOnMenuItemSelected.Add(new (evt) => + { + gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ThreadExitMessages); + }); + + var menuItemSymbolLoadMessages = menu.AddItem("Symbol Load Messages"); + if (!outputFilterFlags.HasFlag(.SymbolLoadMessages)) + { + menuItemSymbolLoadMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check); + } + + menuItemSymbolLoadMessages.mOnMenuItemSelected.Add(new (evt) => + { + gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .SymbolLoadMessages); + }); + + /* Not sure how to filter Program Output, it's handled in BeefSysLib not the IDE/Debugger. Perhaps we would + also need SetOutputFilterFlags() in BeefSysLib + var menuItemProgramOutput = menu.AddItem("Program Output"); + if (!outputFilterFlags.HasFlag(.ProgramOutput)) + { + menuItemProgramOutput.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check); + } + + menuItemProgramOutput.mOnMenuItemSelected.Add(new (evt) => + { + gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ProgramOutput); + }); + */ MenuWidget menuWidget = DarkTheme.sDarkTheme.CreateMenuWidget(menu); menuWidget.Init(this, useX, useY); diff --git a/IDEHelper/COFF.cpp b/IDEHelper/COFF.cpp index aa443f61..647f1a2c 100644 --- a/IDEHelper/COFF.cpp +++ b/IDEHelper/COFF.cpp @@ -6020,7 +6020,7 @@ bool COFF::TryLoadPDB(const String& pdbPath, uint8 wantGuid[16], int32 wantAge) BP_ZONE("COFF::TryLoadPDB"); - if (!isVerifyOnly) + if (!isVerifyOnly && !(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_SymbolLoadMessages)) mDebugger->OutputMessage(StrFormat("Loading PDB %s\n", pdbPath.c_str())); DWORD highFileSize = 0; diff --git a/IDEHelper/DebugManager.cpp b/IDEHelper/DebugManager.cpp index b260034a..9118690f 100644 --- a/IDEHelper/DebugManager.cpp +++ b/IDEHelper/DebugManager.cpp @@ -94,6 +94,8 @@ DebugManager::DebugManager() mSymSrvOptions.mSymbolServers.Add("http://127.0.0.1/symbols"); SetSourceServerCacheDir(); + + mOutputFilterFlags = BfOutputFilterFlags_None; } DebugManager::~DebugManager() @@ -143,6 +145,16 @@ void DebugManager::SetSourceServerCacheDir() #endif } +void DebugManager::SetOutputFilterFlags(BfOutputFilterFlags outputFilterFlags) +{ + mOutputFilterFlags = outputFilterFlags; +} + +BfOutputFilterFlags DebugManager::GetOutputFilterFlags() +{ + return mOutputFilterFlags; +} + //#define CAPTURE_ALLOC_BACKTRACE //#define CAPTURE_ALLOC_SOURCES @@ -1661,6 +1673,24 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetEmitSource(char* inFilePath) return outString.c_str(); } +BF_EXPORT void BF_CALLTYPE Debugger_SetOutputFilterFlags(int flags) +{ + if (gDebugManager != NULL) + { + gDebugManager->SetOutputFilterFlags((BfOutputFilterFlags)flags); + } +} + +BF_EXPORT int BF_CALLTYPE Debugger_GetOutputFilterFlags() +{ + if (gDebugManager != NULL) + { + return (int)gDebugManager->GetOutputFilterFlags(); + } + + return 0; +} + BF_EXPORT NetResult* HTTP_GetFile(char* url, char* destPath) { AutoCrit autoCrit(gDebugManager->mNetManager->mThreadPool.mCritSect); diff --git a/IDEHelper/DebugManager.h b/IDEHelper/DebugManager.h index 97b0a6ea..4128eb2d 100644 --- a/IDEHelper/DebugManager.h +++ b/IDEHelper/DebugManager.h @@ -35,6 +35,18 @@ enum BfStepFilterKind BfStepFilterKind_NotFiltered = 2 }; +enum BfOutputFilterFlags : uint16 + { + BfOutputFilterFlags_None = 0x0, + BfOutputFilterFlags_ModuleLoadMessages = 0x1, + BfOutputFilterFlags_ModuleUnloadMessages = 0x2, + BfOutputFilterFlags_ProcessExitMessages = 0x4, + BfOutputFilterFlags_ThreadCreateMessages = 0x8, + BfOutputFilterFlags_ThreadExitMessages = 0x10, + BfOutputFilterFlags_SymbolLoadMessages = 0x20, + BfOutputFilterFlags_ProgramOutput = 0x40 // Can't trap these easily, they're in BeefSysLib +}; + class StepFilter { public: @@ -81,6 +93,8 @@ public: NetManager* mNetManager; DbgSymSrvOptions mSymSrvOptions; + BfOutputFilterFlags mOutputFilterFlags; + public: DebugManager(); ~DebugManager(); @@ -88,6 +102,9 @@ public: void OutputMessage(const StringImpl& msg); void OutputRawMessage(const StringImpl& msg); void SetSourceServerCacheDir(); + + void SetOutputFilterFlags(BfOutputFilterFlags outputFilterFlags); + BfOutputFilterFlags GetOutputFilterFlags(); }; extern DebugManager* gDebugManager; diff --git a/IDEHelper/WinDebugger.cpp b/IDEHelper/WinDebugger.cpp index a58a02ef..7cb2eb01 100644 --- a/IDEHelper/WinDebugger.cpp +++ b/IDEHelper/WinDebugger.cpp @@ -1708,7 +1708,9 @@ bool WinDebugger::DoUpdate() mDebuggerWaitingThread = newThreadInfo; mThreadList.push_back(mDebuggerWaitingThread); UpdateThreadDebugRegisters(); - OutputMessage(StrFormat("Creating thread from CREATE_PROCESS_DEBUG_EVENT %d\n", mDebugEvent.dwThreadId)); + + if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ThreadCreateMessages)) + OutputMessage(StrFormat("Creating thread from CREATE_PROCESS_DEBUG_EVENT %d\n", mDebugEvent.dwThreadId)); threadInfo = mDebuggerWaitingThread; mProcessInfo.dwThreadId = threadInfo->mThreadId; @@ -1776,10 +1778,14 @@ bool WinDebugger::DoUpdate() else exitCodeStr = StrFormat("%d", exitCode); - if (!exitMessage.IsEmpty()) - OutputMessage(StrFormat("Process terminated. ExitCode: %s (%s).\n", exitCodeStr.c_str(), exitMessage.c_str())); - else - OutputMessage(StrFormat("Process terminated. ExitCode: %s.\n", exitCodeStr.c_str())); + if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ProcessExitMessages)) + { + if (!exitMessage.IsEmpty()) + OutputMessage(StrFormat("Process terminated. ExitCode: %s (%s).\n", exitCodeStr.c_str(), exitMessage.c_str())); + else + OutputMessage(StrFormat("Process terminated. ExitCode: %s.\n", exitCodeStr.c_str())); + } + mRunState = RunState_Terminated; mDebugManager->mOutMessages.push_back("modulesChanged"); } @@ -1858,7 +1864,8 @@ bool WinDebugger::DoUpdate() stream.mFileHandle = 0; } - OutputMessage(loadMsg + "\n"); + if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ModuleLoadMessages)) + OutputMessage(loadMsg + "\n"); if (altFileHandle != INVALID_HANDLE_VALUE) ::CloseHandle(altFileHandle); @@ -1913,7 +1920,7 @@ bool WinDebugger::DoUpdate() mDebugManager->mOutMessages.push_back("modulesChanged"); } - if (!name.empty()) + if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ModuleUnloadMessages) && !name.empty()) OutputMessage(StrFormat("Unloading DLL: %s @ %0s\n", name.c_str(), EncodeDataPtr((addr_target)(intptr)mDebugEvent.u.UnloadDll.lpBaseOfDll, true).c_str())); BfLogDbg("UNLOAD_DLL_DEBUG_EVENT %s\n", name.c_str()); @@ -1959,12 +1966,15 @@ bool WinDebugger::DoUpdate() mDebuggerWaitingThread = threadInfo; mThreadList.push_back(mDebuggerWaitingThread); UpdateThreadDebugRegisters(); - OutputMessage(StrFormat("Creating thread %d\n", mDebugEvent.dwThreadId)); + if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ThreadCreateMessages)) + OutputMessage(StrFormat("Creating thread %d\n", mDebugEvent.dwThreadId)); } break; case EXIT_THREAD_DEBUG_EVENT: { - OutputMessage(StrFormat("Exiting thread %d\n", mDebugEvent.dwThreadId)); + if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ThreadExitMessages)) + OutputMessage(StrFormat("Exiting thread %d\n", mDebugEvent.dwThreadId)); + if (mSteppingThread == threadInfo) { // We were attempting stepping on this thread, but not anymore!