//
//
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using DebuggerLibrary;
using ICSharpCode.Core;
//using ICSharpCode.Core.Services;
//using ICSharpCode.Core.AddIns;
//using ICSharpCode.Core.Properties;
//using ICSharpCode.Core.AddIns.Codons;
//using ICSharpCode.Core.AddIns.Conditions;
using System.CodeDom.Compiler;
using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Document;
using ICSharpCode.SharpDevelop.Gui;
//using ICSharpCode.SharpDevelop.Gui.Components;
//using ICSharpCode.SharpDevelop.Gui.Pads;
using ICSharpCode.SharpDevelop.Project;
//using ICSharpCode.SharpDevelop.Internal.Project;
//using ICSharpCode.SharpDevelop.Gui.Dialogs;
using ICSharpCode.SharpDevelop.Services;
//using Reflector.UserInterface;
namespace ICSharpCode.SharpDevelop.Services
{
public class WindowsDebugger:IDebugger //, IService
{
public event EventHandler DebugStopped; // FIX: unused
List exceptionHistory = new List();
protected virtual void OnDebugStopped(EventArgs e)
{
if (DebugStopped != null) {
DebugStopped(this, e);
}
}
public void Dispose()// FIX: unused
{
}
MessageViewCategory messageViewCategoryDebug;
MessageViewCategory messageViewCategoryDebuggerLog;
public Thread selectedThread;
public Function selectedFunction;
public bool CanDebug(IProject project)
{
return true;
}
public bool SupportsStepping {
get {
return true;
}
}
public IList ExceptionHistory {
get {
return exceptionHistory.AsReadOnly();
}
}
public WindowsDebugger()
{
InitializeService();
}
#region ICSharpCode.Core.Services.IService interface implementation
public event System.EventHandler Initialize;
public event System.EventHandler Unload;
public void InitializeService()
{
NDebugger.DebuggerTraceMessage += new MessageEventHandler(DebuggerTraceMessage);
NDebugger.LogMessage += new MessageEventHandler(LogMessage);
NDebugger.DebuggingStarted += new DebuggerEventHandler(DebuggingStarted);
NDebugger.DebuggingPaused += new DebuggingPausedEventHandler(DebuggingPaused);
NDebugger.DebuggingResumed += new DebuggerEventHandler(DebuggingResumed);
NDebugger.DebuggingStopped += new DebuggerEventHandler(DebuggingStopped);
NDebugger.IsProcessRunningChanged += new DebuggerEventHandler(DebuggerStateChanged);
NDebugger.Instance.BreakpointStateChanged += new DebuggerLibrary.BreakpointEventHandler(RestoreSharpdevelopBreakpoint);
DebuggerService.BreakPointAdded += new EventHandler(RestoreNDebuggerBreakpoints);
DebuggerService.BreakPointRemoved += new EventHandler(RestoreNDebuggerBreakpoints);
DebuggerService.BreakPointChanged += new EventHandler(RestoreNDebuggerBreakpoints);
if (Initialize != null) {
Initialize(this, null);
}
}
public void UnloadService()
{
NDebugger.DebuggerTraceMessage -= new MessageEventHandler(DebuggerTraceMessage);
NDebugger.LogMessage -= new MessageEventHandler(LogMessage);
NDebugger.DebuggingStarted -= new DebuggerEventHandler(DebuggingStarted);
NDebugger.DebuggingPaused -= new DebuggingPausedEventHandler(DebuggingPaused);
NDebugger.IsProcessRunningChanged -= new DebuggerEventHandler(DebuggerStateChanged);
NDebugger.Instance.BreakpointStateChanged -= new DebuggerLibrary.BreakpointEventHandler(RestoreSharpdevelopBreakpoint);
DebuggerService.BreakPointAdded -= new EventHandler(RestoreNDebuggerBreakpoints);
DebuggerService.BreakPointRemoved -= new EventHandler(RestoreNDebuggerBreakpoints);
DebuggerService.BreakPointChanged -= new EventHandler(RestoreNDebuggerBreakpoints);
if (Unload != null) {
Unload(this, null);
}
}
#endregion
#region ICSharpCode.SharpDevelop.Services.IDebugger interface implementation
public bool IsDebugging {
get {
return NDebugger.IsDebugging;
}
}
public bool IsProcessRunning {
get {
return NDebugger.IsProcessRunning;
}
}
public bool SupportsStartStop {
get {
return true;
}
}
public bool SupportsExecutionControl {
get {
return true;
}
}
public void StartWithoutDebugging(System.Diagnostics.ProcessStartInfo psi)
{
NDebugger.StartWithoutDebugging(psi);
}
public void Start(string fileName, string workingDirectory, string arguments)
{
NDebugger.Start(fileName, workingDirectory, arguments);
}
public void Stop()
{
NDebugger.Terminate();
}
public void Break()
{
NDebugger.Break();
}
public void StepInto()
{
NDebugger.StepInto();
}
public void StepOver()
{
NDebugger.StepOver();
}
public void StepOut()
{
NDebugger.StepOut();
}
public void Continue()
{
NDebugger.Continue();
}
#endregion
public void RestoreNDebuggerBreakpoints(object sender, EventArgs e)
{
NDebugger.Instance.ClearBreakpoints();
foreach (ICSharpCode.Core.Breakpoint b in DebuggerService.Breakpoints) {
DebuggerLibrary.Breakpoint newBreakpoint = new DebuggerLibrary.Breakpoint(b.FileName, b.LineNumber, 0, b.IsEnabled);
newBreakpoint.Tag = b;
b.Tag = newBreakpoint;
NDebugger.Instance.AddBreakpoint(newBreakpoint);
}
}
public void RestoreSharpdevelopBreakpoint(object sender, BreakpointEventArgs e)
{
ICSharpCode.Core.Breakpoint sdBreakpoint = e.Breakpoint.Tag as ICSharpCode.Core.Breakpoint;
if (sdBreakpoint != null) {
sdBreakpoint.IsEnabled = e.Breakpoint.Enabled;
sdBreakpoint.FileName = e.Breakpoint.SourcecodeSegment.SourceFullFilename;
sdBreakpoint.LineNumber = e.Breakpoint.SourcecodeSegment.StartLine;
}
}
// Output messages that report status of debugger
void DebuggerTraceMessage(object sender, MessageEventArgs e)
{
if (messageViewCategoryDebuggerLog != null) {
messageViewCategoryDebuggerLog.AppendText(e.Message + "\n");
System.Console.WriteLine(e.Message);
}
}
// Output messages form debuged program that are caused by System.Diagnostics.Trace.WriteLine(), etc...
void LogMessage(object sender, MessageEventArgs e)
{
DebuggerTraceMessage(this, e);
if (messageViewCategoryDebug != null) {
messageViewCategoryDebug.AppendText(e.Message + "\n");
}
}
void DebuggingStarted(object sender, DebuggerEventArgs e)
{
// Initialize
/*PadDescriptor cmv = (CompilerMessageView)WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView));
if (messageViewCategoryDebug == null) {
messageViewCategoryDebug = cmv.GetCategory("Debug");
}
messageViewCategoryDebug.ClearText();
if (messageViewCategoryDebuggerLog == null) {
messageViewCategoryDebuggerLog = new MessageViewCategory("DebuggerLog", "Debugger log");
//cmv.AddCategory(messageViewCategoryDebuggerLog);
}
messageViewCategoryDebuggerLog.ClearText();*/
}
void DebuggingPaused(object sender, DebuggingPausedEventArgs e)
{
if (e.Reason == PausedReason.Exception) {
exceptionHistory.Add(NDebugger.CurrentThread.CurrentException);
if (NDebugger.CurrentThread.CurrentException.ExceptionType != ExceptionType.DEBUG_EXCEPTION_UNHANDLED && (NDebugger.CatchHandledExceptions == false)) {
// Ignore the exception
Continue();
return;
}
//MessageBox.Show("Exception was thrown in debugee:\n" + NDebugger.CurrentThread.CurrentException.ToString());
ExceptionForm form = new ExceptionForm();
form.label.Text = "Exception " +
NDebugger.CurrentThread.CurrentException.Type +
" was thrown in debugee:\n" +
NDebugger.CurrentThread.CurrentException.Message;
form.pictureBox.Image = ResourceService.GetBitmap((NDebugger.CurrentThread.CurrentException.ExceptionType != ExceptionType.DEBUG_EXCEPTION_UNHANDLED)?"Icons.32x32.Warning":"Icons.32x32.Error");
form.ShowDialog(ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.MainForm);
switch (form.result) {
case ExceptionForm.Result.Break:
break;
case ExceptionForm.Result.Continue:
Continue();
return;
case ExceptionForm.Result.Ignore:
System.Diagnostics.Debug.Fail("Not implemented");
Continue();
return;
}
}
try {
SelectThread(NDebugger.CurrentThread);
} catch (CurrentThreadNotAviableException) {}
JumpToCurrentLine();
}
void DebuggingResumed(object sender, DebuggerEventArgs e)
{
selectedThread = null;
selectedFunction = null;
DebuggerService.RemoveCurrentLineMarker();
}
void DebuggingStopped(object sender, DebuggerEventArgs e)
{
exceptionHistory.Clear();
//DebuggerService.Stop();//TODO: delete
}
public void SelectThread(Thread thread)
{
selectedThread = thread;
try {
selectedFunction = thread.CurrentFunction;
// Prefer first function on callstack that has symbols (source code)
if (selectedFunction.Module.SymbolsLoaded == false) {
foreach (Function f in thread.Callstack) {
if (f.Module.SymbolsLoaded) {
selectedFunction = f;
break;
}
}
}
} catch (CurrentFunctionNotAviableException) {}
}
public void JumpToCurrentLine()
{
//StatusBarService.SetMessage("Source code not aviable!");
try {
if (selectedFunction == null) {
return;
}
SourcecodeSegment nextStatement = selectedFunction.NextStatement;
DebuggerService.JumpToCurrentLine(nextStatement.SourceFullFilename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn);
string stepRanges = "";
foreach (int i in nextStatement.StepRanges) {
stepRanges += i.ToString("X") + " ";
}
//StatusBarService.SetMessage("IL:" + nextStatement.ILOffset.ToString("X") + " StepRange:" + stepRanges + " ");
} catch (NextStatementNotAviableException) {
System.Diagnostics.Debug.Fail("Source code not aviable!");
}
}
public void DebuggerStateChanged(object sender, DebuggerEventArgs e)
{
UpdateToolbars();
}
void UpdateToolbars()
{
((DefaultWorkbench)WorkbenchSingleton.Workbench).Update();
//if (WorkbenchSingleton.Workbench.ActiveWorkbenchWindow != null) {
// WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ActiveViewContent.RedrawContent();
//}
}
///
/// Gets the current value of the variable as string that can be displayed in tooltips.
///
public string GetValueAsString(string variableName)
{
if (!NDebugger.IsDebugging || NDebugger.IsProcessRunning) return null;
VariableCollection collection = NDebugger.LocalVariables;
if (collection == null)
return null;
foreach (Variable v in collection) {
if (v.Name == variableName) {
object val = v.Value;
if (val == null)
return "";
else if (val is string)
return "\"" + val.ToString() + "\"";
else
return val.ToString();
}
}
return null;
}
}
}