/** Step out. */
  public void stepOut() throws DebuggerException {
    if (currentThread == null) return;

    setLastAction(ACTION_STEP_OUT);
    currentThread.setLastAction(ACTION_STEP_OUT);
    new Protector("AbstractDebugger.stepOut") { // NOI18N
      public Object protect() throws Exception {
        currentThread.getRemoteThread().stepOut();
        ToolsDebugger.super.stepOut();
        return null;
      }
    }.go(synchronizer, killer);
  }
  /** Trace over. */
  public void traceOver() throws DebuggerException {
    if (currentThread == null) return;

    setLastAction(ACTION_TRACE_OVER);
    currentThread.setLastAction(ACTION_TRACE_OVER);
    new Protector("AbstractDebugger.traceOver") { // NOI18N
      public Object protect() throws Exception {
        currentThread.getRemoteThread().next();
        ToolsDebugger.super.traceOver();
        return null;
      }
    }.go(synchronizer, killer);
  }
  /** Go. */
  public void go() throws DebuggerException {
    if (currentThread == null) return;

    setLastAction(ACTION_GO);
    currentThread.setLastAction(ACTION_GO);
    new Protector("AbstractDebugger.go") { // NOI18N
      public Object protect() throws Exception {
        remoteDebugger.cont();
        ToolsDebugger.super.go();
        return null;
      }
    }.go(synchronizer, killer);

    // threadGroup.setSuspended (false);
  }
 /** Performs stop action. */
 void stop(boolean stop, final AbstractThread thread) {
   /*
       int lastAction = null;
       int currentStackDepth = 0;
       int lastStackDepth = 0;
       if (!stop) { // obtain values only if they are really needed
         lastAction = ((ToolsThread)thread).getLastAction ();
         lastStackDepth = ((ToolsThread)thread).getLastStackDepth ();
         try {
           currentStackDepth = ((ToolsThread)thread).getStackDepth ();
         }
         catch (DebuggerException e) {
           currentStackDepth = lastStackDepth + 1; // the condition in the following 'if' will be false
         }
   }
       if (stop || (lastAction == ACTION_TRACE_INTO) ||
         ((lastAction == ACTION_TRACE_OVER) && (currentStackDepth <= lastStackDepth)) ||
         ((lastAction == ACTION_STEP_OUT) && (currentStackDepth < lastStackDepth))
         ) {
       */
   if (stop) {
     setLastAction(ACTION_BREAKPOINT_HIT);
     setDebuggerState(DEBUGGER_STOPPED);
     SwingUtilities.invokeLater(
         new Runnable() {
           public void run() {
             try {
               threadGroup.threadChanged();
               // 'thread' could be created by Event.getThread (), but we must use a ToolsThread
               // created by threadChanged method (line above)
               AbstractThread tt = threadGroup.getThread(((ToolsThread) thread).getRemoteThread());
               if (tt == null) tt = thread;
               // **************************************************************************************
               tt.setCurrent(true);
               ((ToolsThread) tt).setLastAction(ACTION_BREAKPOINT_HIT);
             } catch (Throwable e) {
               if (e instanceof ThreadDeath) throw (ThreadDeath) e;
               println(bundle.getString("EXC_Debugger") + ": " + e, ERR_OUT); // NOI18N
               return;
             }
             updateWatches();
           }
         });
   } else {
     int lastAction = ((ToolsThread) thread).getLastAction();
     if ((lastAction == ACTION_TRACE_OVER) || (lastAction == ACTION_STEP_OUT))
       new Protector("AbstractDebugger.stepOut") { // NOI18N
         public Object protect() throws Exception {
           ((ToolsThread) thread).getRemoteThread().stepOut();
           return null;
         }
       }.go(synchronizer, killer);
     else {
       new Protector("AbstractDebugger.go") { // NOI18N
         public Object protect() throws Exception {
           remoteDebugger.cont();
           return null;
         }
       }.go(synchronizer, killer);
     }
   }
 }