# HG changeset patch
# User Daniel J Sebald <daniel.sebald@ieee.org>
# Date 1365455855 18000
# Node ID bc0b37932f7c25e640dbbd85d7de3ab8f6d486f0
# Parent  7762d56dbc8a38cd9e01880fc9723da1645eba57
New marker class to maintain breakpoints and position in modified files.

* file-editor-tab.cc (file_editor_tab::file_editor_tab):
New unsure_breakpoint, unsure_debugger_position marker definitions. Register
QIntList
(file_editor_tab::~file_editor_tab): Signal to remove all breakpoint and
position objects.
(file_editor_tab::message_cannot_breakpoint_changed_file) New message.
(file_editor_tab::handle_margin_clicked) Emit signal to remove marker. Display
message for modified file.
(file_editor_tab::add_breakpoint_callback,
file_editor_tab::remove_breakpoint_callback,
file_editor_tab::remove_all_breakpoints_callback): STDERR debugging message.
(file_editor_tab::handle_request_remove_breakpoint): Rename. Emit signal to
remove breakpoint. Display message for modified file.
(file_editor_tab::load_file): Prototype code for connecting to "dbstatus".
(file_editor_tab::handle_octave_result): New method. Prototype code for
processing Octave result.
(file_editor_tab::save_file): Record list of breakpoints. Save file. Restore
breakpoints if instructed after save.
(file_editor_tab::notice_settings): Configure _breakpoint_filesave_behavior and
uncertain marker icon set.
(file_editor_tab::insert_debugger_pointer): Compute best guess at debugger
position in modified file. Connect signals/slots to pointer marker.
(file_editor_tab::delete_debugger_pointer): Emit signal to marker.
(file_editor_tab::do_dbstop_marker): If breakpoint doesn't already exist,
construct marker object, connect signals.  Or, emit delete signal to breakpoint
markers.

* file-editor-tab.h (file_editor_tab : public QWidget): Multitude of signal
and slot declarations as described above.
(header): Move editor_markers enumeration to marker.h. Include "marker.h".

* marker.cc, marker.h (marker : public QObject): New files. New marker class
comprised of brief slots to interact with QsciScintalla object and brief signal
for Octave removal request.

* arrow_right_gray.png, redled_gray.png: New marker icons.

* module.mk: Add marker.h, marker.cc, arrow_right_gray.png, redled_gray.png.

* settings-dialog.cc (settings_dialog::settings_dialog): Show options, icons
and settings for debugger/breakpoint_filesave_behavior and
debugger/uncertain_icon_set.
(settings_dialog::write_changed_settings): Write settings for
debugger/breakpoint_filesave_behavior and debugger/uncertain_icon_set.

* settings-dialog.ui: New "Debugger" tab with two group boxes.

* debug.cc (bp_table::do_add_breakpoint, bp_table::do_remove_breakpoint,
bp_table::do_remove_all_breakpoints_in_file) STDERR debugging message.

diff -r 7762d56dbc8a -r bc0b37932f7c libgui/src/icons/arrow_right_gray.png
Binary file libgui/src/icons/arrow_right_gray.png has changed
diff -r 7762d56dbc8a -r bc0b37932f7c libgui/src/icons/redled_gray.png
Binary file libgui/src/icons/redled_gray.png has changed
diff -r 7762d56dbc8a -r bc0b37932f7c libgui/src/m-editor/file-editor-tab.cc
--- a/libgui/src/m-editor/file-editor-tab.cc	Fri Apr 05 16:21:38 2013 -0700
+++ b/libgui/src/m-editor/file-editor-tab.cc	Mon Apr 08 16:17:35 2013 -0500
@@ -42,10 +42,17 @@
 #include <QTextStream>
 #include <QVBoxLayout>
 #include <QInputDialog>
+#include <QStyle>
+#include <QTextBlock>
+#include <QLabel>
+#include <QCheckBox>
+#include <QDialogButtonBox>
+#include <QPushButton>
 
 #include "file-editor-tab.h"
 #include "file-editor.h"
 #include "octave-link.h"
+#include "marker.h"
 
 #include "debug.h"
 #include "oct-env.h"
@@ -71,8 +78,12 @@
   _edit_area->markerDefine (QsciScintilla::RightTriangle, bookmark);
   _edit_area->markerDefine (QPixmap (":/actions/icons/redled.png"),
                             breakpoint);
+  _edit_area->markerDefine (QPixmap (":/actions/icons/redled.png"),
+                            unsure_breakpoint);
   _edit_area->markerDefine (QPixmap (":/actions/icons/arrow_right.png"),
                             debugger_position);
+  _edit_area->markerDefine (QPixmap (":/actions/icons/arrow_right.png"),
+                            unsure_debugger_position);
 
   connect (_edit_area, SIGNAL (marginClicked (int, int,
                                               Qt::KeyboardModifiers)),
@@ -119,10 +130,18 @@
   QSettings *settings = resource_manager::get_settings ();
   if (settings)
     notice_settings (settings);
+
+  // Register QIntList so that list of ints may be part of a signal.
+  /* ONLY NEEDS TO BE DONE ONCE, COULD GO ELSEWHERE */
+  qRegisterMetaType<QIntList> ("QIntList");
 }
 
 file_editor_tab::~file_editor_tab ()
 {
+  // Tell all connected markers to self-destruct.
+  emit remove_all_breakpoints ();
+  emit remove_all_positions ();
+
   // Destroy items attached to _edit_area.
   QsciLexer *lexer = _edit_area->lexer ();
   if (lexer)
@@ -176,8 +195,24 @@
 }
 
 void
-file_editor_tab::handle_margin_clicked(int margin, int line,
-                                       Qt::KeyboardModifiers state)
+file_editor_tab::message_cannot_breakpoint_changed_file (void)
+{
+  // Cannot create a breakpoint when the file is modified
+  // because the line number the editor is providing might
+  // not match what Octave core is interpretting in the
+  // file on disk.
+  QMessageBox* msgBox = new QMessageBox (QMessageBox::Critical,
+                                         tr ("Octave Editor"),
+                                         tr ("Cannot add breakpoint to modified file."),
+                                         QMessageBox::Ok, 0);
+  msgBox->setWindowModality (Qt::ApplicationModal);
+  msgBox->exec ();
+  delete msgBox;
+}
+
+void
+file_editor_tab::handle_margin_clicked (int margin, int line,
+                                        Qt::KeyboardModifiers state)
 {
   if (margin == 1)
     {
@@ -186,19 +221,22 @@
       if (state & Qt::ControlModifier)
         {
           if (markers_mask && (1 << bookmark))
-            _edit_area->markerDelete(line,bookmark);
+            _edit_area->markerDelete (line, bookmark);
           else
-            _edit_area->markerAdd(line,bookmark);
+            _edit_area->markerAdd (line, bookmark);
         }
       else
         {
           if (markers_mask && (1 << breakpoint))
             {
-              request_remove_breakpoint (line);
+              emit request_remove_breakpoint_via_editor_linenr (line);
             }
           else
             {
-              request_add_breakpoint (line);
+              if (_edit_area->isModified ())
+                message_cannot_breakpoint_changed_file ();
+              else
+                handle_request_add_breakpoint (line);
             }
         }
     }
@@ -367,7 +405,7 @@
     return;
 
   int line, cur;
-  _edit_area->getCursorPosition (&line,&cur);
+  _edit_area->getCursorPosition (&line, &cur);
   if ( _edit_area->markersAtLine (line) && (1 << bookmark) )
     _edit_area->markerDelete (line, bookmark);
   else
@@ -419,6 +457,7 @@
 
   std::string previous_directory = octave_env::get_current_directory ();
   octave_env::chdir (info.path);
+fprintf(stderr,"I'm in...add_breakpoint_callback\n");
   intmap = bp_table::add_breakpoint (info.function_name, intmap);
   octave_env::chdir (previous_directory);
   // bp_table::add_breakpoint also sets the marker in the editor
@@ -432,6 +471,7 @@
 
   std::string previous_directory = octave_env::get_current_directory ();
   octave_env::chdir (info.path);
+fprintf(stderr,"I'm in...remove_breakpoint_callback\n");
   bp_table::remove_breakpoint (info.function_name, intmap);
   octave_env::chdir (previous_directory);
 }
@@ -442,15 +482,16 @@
   bp_table::intmap intmap;
   std::string previous_directory = octave_env::get_current_directory ();
   octave_env::chdir (info.path);
+fprintf(stderr,"I'm in...remove_all_breakpoints_callback\n");
   intmap = bp_table::remove_all_breakpoints_in_file (info.function_name, true);
   octave_env::chdir (previous_directory);
 
   if (intmap.size() > 0)
-    _edit_area->markerDeleteAll (breakpoint);
+    emit remove_all_breakpoints ();
 }
 
 void
-file_editor_tab::request_add_breakpoint (int line)
+file_editor_tab::handle_request_add_breakpoint (int line)
 {
   QFileInfo file_info (_file_name);
   QString path = file_info.absolutePath ();
@@ -466,7 +507,7 @@
 }
 
 void
-file_editor_tab::request_remove_breakpoint (int line)
+file_editor_tab::handle_request_remove_breakpoint (int line)
 {
   QFileInfo file_info (_file_name);
   QString path = file_info.absolutePath ();
@@ -490,9 +531,14 @@
   int line, cur;
   _edit_area->getCursorPosition (&line, &cur);
   if ( _edit_area->markersAtLine (line) && (1 << breakpoint) )
-    request_remove_breakpoint (line);
+    request_remove_breakpoint_via_editor_linenr (line);
   else
-    request_add_breakpoint (line);
+    {
+      if (_edit_area->isModified ())
+        message_cannot_breakpoint_changed_file ();
+      else
+        handle_request_add_breakpoint (line);
+    }
 }
 
 void
@@ -753,7 +799,7 @@
 }
 
 QString
-file_editor_tab::load_file(const QString& fileName)
+file_editor_tab::load_file (const QString& fileName)
 {
   QFile file (fileName);
   if (!file.open (QFile::ReadOnly))
@@ -770,10 +816,54 @@
   update_window_title (false); // window title (no modification)
   _edit_area->setModified (false); // loaded file is not modified yet
 
+  // TODO: (BREAKPOINTS) At this point it would be nice to put any set
+  // breakpoints on the margin.  In order to do this, somehow the
+  // "dbstatus" command needs to be accessed.  All it would require is a
+  // routine that does "res = feval("dbstatus") and signals that result
+  // to some slot.  Note how this access to Octave core is done as a
+  // queued event.  The reason is that Octave could be busy running when
+  // the file is opened.  If this were to emit a signal asking for an
+  // immediate response, the GUI could sit indefinitely.  If it is queued,
+  // eventually the breakpoints will appear when Octave core stops at
+  // the command line.
+/*
+  connect (octave_link, SIGNAL (fileSelected (QObject *, const QString&, const octave_value_list&)),
+           this, SLOT (handle_feval_result (QObject *, const QString&, const octave_value_list&)));
+  connect (this, SIGNAL (evaluate_octave_command (const QString&)),
+           octave_link, SLOT (queue_octave_command (const QString&)));
+*/
+
+  emit evaluate_octave_command ("dbstatus");
+
   return QString ();
 }
 
 void
+file_editor_tab::handle_octave_result (QObject *requester, QString& command,
+                                       octave_value_list &result)
+{
+  // Check if this object initiated the command.
+  if (requester == this)
+    {
+      if (command == "dbstatus")
+        {
+          fprintf (stderr, "Should be installing breakpoints in this file.");
+/*
+octave:1> result = dbstatus
+result =
+
+  0x1 struct array containing the fields:
+
+    name
+    file
+    line
+*/
+          // Check for results that match "file".
+        }
+    }
+}
+
+void
 file_editor_tab::new_file ()
 {
   update_window_title (false); // window title (no modification)
@@ -818,6 +908,15 @@
       return;
     }
 
+  // Get a list of all the breakpoint line numbers.
+  QIntList list;
+  emit report_editor_linenr (list);
+  if (! list.isEmpty ())
+    {
+      // At least one breakpoint is present.  Get rid of breakpoints.
+      remove_all_breakpoints (this);
+    }
+
   // save the contents into the file
   QTextStream out (&file);
   QApplication::setOverrideCursor (Qt::WaitCursor);
@@ -837,6 +936,90 @@
       emit tab_remove_request ();
       return;  // Don't touch member variables after removal
     }
+
+  // Attempt to restore the breakpoints if that is desired.
+  if (! list.isEmpty ())
+    {
+      bool restore_breakpoints;
+      if (_breakpoint_filesave_behavior == "RESTORE")
+        restore_breakpoints = true;
+      else if (_breakpoint_filesave_behavior == "DISCARD")
+        restore_breakpoints = false;
+      else
+        {
+          QDialog* dlgBox = new QDialog ();
+
+          QStyle *mbstyle = dlgBox->style ();
+          QIcon tmpIcon = mbstyle->standardIcon (QStyle::SP_MessageBoxQuestion,
+                                                 0, dlgBox);
+          int iconSize = mbstyle->pixelMetric(QStyle::PM_MessageBoxIconSize,
+                                              0, dlgBox);
+          QLabel *questImage = new QLabel ();
+          questImage->setPixmap (tmpIcon.pixmap (iconSize, iconSize));
+          QLabel *questText = new QLabel ("Would you like to restore adjusted breakpoints?");
+          QHBoxLayout *horizontalLayout = new QHBoxLayout;
+          horizontalLayout->addWidget (questImage);
+          horizontalLayout->addWidget (questText);
+
+          QCheckBox *checkBox = new QCheckBox ("Don't ask again.");
+          checkBox->setCheckState (Qt::Unchecked);
+
+          QDialogButtonBox *buttonBox = new QDialogButtonBox ();
+          QPushButton *noButton = buttonBox->addButton (QDialogButtonBox::No);
+          noButton->setAutoDefault (false);
+          buttonBox->addButton (QDialogButtonBox::Yes);
+          QHBoxLayout *buttonsLayout = new QHBoxLayout;
+          buttonsLayout->addStretch (1);
+          buttonsLayout->addWidget (buttonBox);
+
+          QVBoxLayout *mainLayout = new QVBoxLayout;
+          mainLayout->addLayout (horizontalLayout);
+          mainLayout->addSpacing(12);
+          mainLayout->addWidget (checkBox);
+          mainLayout->addSpacing(12);
+          mainLayout->addLayout (buttonsLayout);
+
+          dlgBox->setLayout (mainLayout);
+
+          connect(buttonBox, SIGNAL(accepted()), dlgBox, SLOT(accept()));
+          connect(buttonBox, SIGNAL(rejected()), dlgBox, SLOT(reject()));
+          dlgBox->setWindowModality (Qt::NonModal);
+          dlgBox->exec ();
+
+          restore_breakpoints = (dlgBox->result () == QDialog::Accepted);
+
+          if (checkBox->checkState () == Qt::Checked)
+            {
+              // User no longer wants to be asked so save the setting for
+              // this object...
+              if (restore_breakpoints)
+                _breakpoint_filesave_behavior = "RESTORE";
+              else
+                _breakpoint_filesave_behavior = "DISCARD";
+
+              // ...and on disc (and Preferences...)
+              QSettings *settings = resource_manager::get_settings ();
+              if (settings)
+                {
+                  settings->setValue ("debugger/breakpoint_filesave_behavior",
+                                      _breakpoint_filesave_behavior);
+                  settings->sync ();
+                }
+            }
+
+          delete dlgBox;
+
+        }
+
+      if (restore_breakpoints)
+        {
+          for (int i = 0; i < list.length (); i++)
+{
+fprintf(stderr,"i=%d, val=%d\n",i, list.value (i));
+            handle_request_add_breakpoint (list.value (i));
+}
+        }
+    }
 }
 
 void
@@ -1031,6 +1214,40 @@
 
   _long_title = settings->value ("editor/longWindowTitle",false).toBool ();
 
+  _breakpoint_filesave_behavior = settings->value ("debugger/breakpoint_filesave_behavior", "ASK").
+                                                    toString ();
+
+  QVariant uis = settings->value ("debugger/uncertain_icon_set", "SELECTED");
+  if (uis == "CUSTOM")
+    {
+      _edit_area->markerDefine (QPixmap (":/actions/icons/redled_gray.png"),
+                                unsure_breakpoint);
+      _edit_area->markerDefine (QPixmap (":/actions/icons/arrow_right_gray.png"),
+                                unsure_debugger_position);
+    }
+  else if (uis == "DISABLED")
+    {
+      QPixmap tmpPixmap = QPixmap (":/actions/icons/redled.png");
+      QIcon tmpIcon = QIcon (tmpPixmap);
+      _edit_area->markerDefine (tmpIcon.pixmap (tmpPixmap.size (), QIcon::Disabled),
+                                unsure_breakpoint);
+      tmpPixmap = QPixmap (":/actions/icons/arrow_right.png");
+      tmpIcon = QIcon (tmpPixmap);
+      _edit_area->markerDefine (tmpIcon.pixmap (tmpPixmap.size (), QIcon::Disabled),
+                                unsure_debugger_position);
+    }
+  else
+    {
+      QPixmap tmpPixmap = QPixmap (":/actions/icons/redled.png");
+      QIcon tmpIcon = QIcon (tmpPixmap);
+      _edit_area->markerDefine (tmpIcon.pixmap (tmpPixmap.size (), QIcon::Selected),
+                                unsure_breakpoint);
+      tmpPixmap = QPixmap (":/actions/icons/arrow_right.png");
+      tmpIcon = QIcon (tmpPixmap);
+      _edit_area->markerDefine (tmpIcon.pixmap (tmpPixmap.size (), QIcon::Selected),
+                                unsure_debugger_position);
+    }
+
   update_window_title (false);
 }
 
@@ -1122,7 +1339,52 @@
 
   if (line > 0)
     {
-      _edit_area->markerAdd (line, debugger_position);
+      marker *dp;
+
+      if (_edit_area->isModified ())
+        {
+          // The best that can be done if the editor contents has been
+          // modified is to see if there is a match with the original
+          // line number of any existing breakpoints.  We can put a normal
+          // debugger pointer at that breakpoint position.  Otherwise, it
+          // isn't certain whether the original line number and current line
+          // number match.
+          int editor_linenr = -1;
+          emit find_translated_line_number (line, editor_linenr);
+          if (editor_linenr != -1)
+            {
+              // Match with an existing breakpoint.
+              dp = new marker (_edit_area, line,
+                               debugger_position, editor_linenr);
+            }
+          else
+            {
+              int original_linenr = -1;
+              editor_linenr = -1;
+              emit find_linenr_just_before (line, original_linenr, editor_linenr);
+              if (original_linenr >= 0)
+                {
+                  // Make a guess by using an offset from the breakpoint.
+fprintf(stderr,"Will have to guess from: editorln - %d  linenr - %d  originalln - %d\n",editor_linenr, line, original_linenr);
+                  int linenr_guess = editor_linenr + line - original_linenr;
+                  dp = new marker (_edit_area, line, unsure_debugger_position,
+                                   linenr_guess);
+                }
+              else
+                {
+                  // Can't make a very good guess, so just use the debugger
+                  // line number.
+                  dp = new marker (_edit_area, line, unsure_debugger_position);
+                }
+            }
+        }
+      else
+        dp = new marker (_edit_area, line, debugger_position);
+
+      connect (this, SIGNAL (remove_position_via_debugger_linenr (int)),
+               dp,   SLOT (handle_remove_via_original_linenr (int)));
+      connect (this, SIGNAL (remove_all_positions (void)),
+               dp,   SLOT (handle_remove (void)));
       center_current_line ();
     }
 }
@@ -1134,7 +1396,7 @@
     return;
 
   if (line > 0)
-    _edit_area->markerDelete (line, debugger_position);
+    emit remove_position_via_debugger_linenr (line);
 }
 
 void
@@ -1146,9 +1408,35 @@
   if (line > 0)
     {
       if (insert)
-        _edit_area->markerAdd (line, breakpoint);
+        {
+          int editor_linenr = -1;
+
+          // If comes back indicating a modified editor line number
+          // then there is already a breakpoint marker associated
+          // with this debugger line.
+          emit find_translated_line_number (line, editor_linenr);
+
+          if (editor_linenr == -1)
+            {
+              marker *bp = new marker (_edit_area, line, breakpoint);
+              connect (this, SIGNAL (remove_breakpoint_via_debugger_linenr (int)),
+                       bp,   SLOT (handle_remove_via_original_linenr (int)));
+              connect (this, SIGNAL (request_remove_breakpoint_via_editor_linenr (int)),
+                       bp,   SLOT (handle_request_remove_via_editor_linenr (int)));
+              connect (this, SIGNAL (remove_all_breakpoints (void)),
+                       bp,   SLOT (handle_remove (void)));
+              connect (this, SIGNAL (find_translated_line_number (int, int&)),
+                       bp,   SLOT (handle_find_translation (int, int&)));
+              connect (this, SIGNAL (find_linenr_just_before (int, int&, int&)),
+                       bp,   SLOT (handle_find_just_before (int, int&, int&)));
+              connect (this, SIGNAL (report_editor_linenr (QIntList&)),
+                       bp,   SLOT (handle_report_editor_linenr (QIntList&)));
+              connect (bp,   SIGNAL (request_remove (int)),
+                       this, SLOT (handle_request_remove_breakpoint (int)));
+            }
+        }
       else
-        _edit_area->markerDelete (line, breakpoint);
+        emit remove_breakpoint_via_debugger_linenr (line);
     }
 }
 
diff -r 7762d56dbc8a -r bc0b37932f7c libgui/src/m-editor/file-editor-tab.h
--- a/libgui/src/m-editor/file-editor-tab.h	Fri Apr 05 16:21:38 2013 -0700
+++ b/libgui/src/m-editor/file-editor-tab.h	Mon Apr 08 16:17:35 2013 -0500
@@ -23,6 +23,13 @@
 #ifndef FILEEDITORTAB_H
 #define FILEEDITORTAB_H
 
+// FIXME -- we should not be including config.h in header files.
+// Only needed for octave_value_list type.
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#include "ov.h"
+#endif
+
 #include <Qsci/qsciscintilla.h>
 #include <QWidget>
 #include <QCloseEvent>
@@ -31,6 +38,8 @@
 
 #include "find-dialog.h"
 
+#include "marker.h" /* Only needed for typedef of "QIntList" */
+
 class file_editor;
 class file_editor_tab : public QWidget
 {
@@ -90,6 +99,11 @@
 
   void file_has_changed (const QString& fileName);
 
+  void handle_request_add_breakpoint (int line);
+  void handle_request_remove_breakpoint (int line);
+
+  void handle_octave_result (QObject *requester, QString& command, octave_value_list &result);
+
 signals:
   void file_name_changed (const QString& fileName, const QString& toolTip);
   void editor_state_changed (bool copy_available, const QString& fileName);
@@ -98,6 +112,18 @@
   void mru_add_file (const QString& file_name);
   void editor_check_conflict_save (const QString& saveFileName, bool remove_on_success);
   void process_octave_code (const QString& command);
+  void remove_breakpoint_via_debugger_linenr (int debugger_linenr);
+  void request_remove_breakpoint_via_editor_linenr (int editor_linenr);
+  void remove_all_breakpoints (void);
+  void find_translated_line_number (int original_linenr, int& translated_linenr);
+  void find_linenr_just_before (int linenr, int& original_linenr, int& editor_linenr);
+  void report_editor_linenr (QIntList& int_list);
+  void remove_position_via_debugger_linenr (int debugger_linenr);
+  void remove_all_positions (void);
+  // TODO: The following is similar to "process_octave_code" signal.  However,
+  // currently that signal is connected to something that simply focuses a
+  // window and not actually communicate with Octave.
+  void evaluate_octave_command (const QString& command);
 
 protected:
   void closeEvent (QCloseEvent *event);
@@ -134,9 +160,9 @@
   void save_file_as (bool remove_on_success = false);
   void message_duplicate_file_name (const QString& fileName);
 
+  void message_cannot_breakpoint_changed_file (void);
+
   void update_lexer ();
-  void request_add_breakpoint (int line);
-  void request_remove_breakpoint (int line);
 
   int check_file_modified ();
   void do_comment_selected_text (bool comment);
@@ -155,6 +181,8 @@
   bool                  _long_title;
   bool                  _copy_available;
 
+  QString               _breakpoint_filesave_behavior;
+
   QFileSystemWatcher    _file_system_watcher;
 
   find_dialog *         _find_dialog;
diff -r 7762d56dbc8a -r bc0b37932f7c libgui/src/m-editor/file-editor.h
--- a/libgui/src/m-editor/file-editor.h	Fri Apr 05 16:21:38 2013 -0700
+++ b/libgui/src/m-editor/file-editor.h	Mon Apr 08 16:17:35 2013 -0500
@@ -36,13 +36,6 @@
 #include "file-editor-interface.h"
 #include "file-editor-tab.h"
 
-enum editor_markers
-  {
-    bookmark,
-    breakpoint,
-    debugger_position
-  };
-
 class file_editor : public file_editor_interface
 {
   Q_OBJECT
diff -r 7762d56dbc8a -r bc0b37932f7c libgui/src/m-editor/marker.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/m-editor/marker.cc	Mon Apr 08 16:17:35 2013 -0500
@@ -0,0 +1,196 @@
+/*
+
+Copyright (C) 2011-2012 Jacob Dawid
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_QSCINTILLA
+
+#include <stdio.h>
+
+#include "marker.h"
+
+
+marker::marker (QsciScintilla *area, int original_linenr, editor_markers type,
+                int editor_linenr) : QObject ()
+{
+  construct (area, original_linenr, type, editor_linenr);
+}
+
+
+marker::marker (QsciScintilla *area, int original_linenr,
+                editor_markers type) : QObject ()
+{
+  construct (area, original_linenr, type, original_linenr);
+}
+
+
+marker::~marker (void)
+{
+fprintf(stderr,"Destruct for marker: linenr--%d, markertype--%d\n",_original_linenr,_marker_type);
+}
+
+
+void
+marker::construct (QsciScintilla *area, int original_linenr,
+                   editor_markers type, int editor_linenr)
+{
+  _edit_area = area;
+  _original_linenr = original_linenr;
+  _marker_type = type;
+  _mhandle = _edit_area->markerAdd (editor_linenr, _marker_type);
+
+/* NOT OF MUCH USE
+  connect (_edit_area, SIGNAL (linesChanged (void)),
+           this, SLOT (handle_lines_changed (void)));
+*/
+fprintf(stderr,"Construct for marker: linenr--%d, markertype--%d\n",_original_linenr,_marker_type);
+}
+
+
+void
+marker::handle_remove_via_original_linenr (int linenr)
+{
+fprintf(stderr,"requested number: %d,  my number: %d\n",linenr,_original_linenr);
+  if (_original_linenr == linenr)
+    {
+      _edit_area->markerDeleteHandle(_mhandle);
+      delete this;
+    }
+}
+
+
+void
+marker::handle_request_remove_via_editor_linenr (int linenr)
+{
+  // Get line number from the edit area and if it matches
+  // the requested line number, remove.
+  if (_edit_area->markerLine (_mhandle) == linenr)
+    {
+      // Rather than delete editor marker directly, issue command
+      // to Octave core.  Octave core should signal back to remove
+      // this breakpoint via debugger line number.
+      emit request_remove (_original_linenr);
+fprintf(stderr,"requesting remove breakpoint at line %d\n",_original_linenr);
+    }
+}
+
+
+void
+marker::handle_remove (void)
+{
+  _edit_area->markerDeleteHandle (_mhandle);
+  delete this;
+}
+
+
+void
+marker::handle_find_translation (int linenr, int& translation_linenr)
+{
+  if (_original_linenr == linenr)
+    translation_linenr = _edit_area->markerLine (_mhandle);
+}
+
+
+void
+marker::handle_find_just_before (int linenr, int& original_linenr, int& editor_linenr)
+{
+  if (_original_linenr < linenr && _original_linenr >= original_linenr)
+    {
+      original_linenr = _original_linenr;
+      editor_linenr = _edit_area->markerLine (_mhandle);
+    }
+}
+
+
+void
+marker::handle_find_just_after (int linenr, int& original_linenr, int& editor_linenr)
+{
+  if (_original_linenr > linenr && _original_linenr <= original_linenr)
+    {
+      original_linenr = _original_linenr;
+      editor_linenr = _edit_area->markerLine (_mhandle);
+    }
+}
+
+
+void
+marker::handle_report_editor_linenr (QIntList& list)
+{
+  list << _edit_area->markerLine (_mhandle);
+}
+
+
+/* NOT OF MUCH USE
+void
+marker::handle_lines_changed (void)
+{
+fprintf(stderr,"marker line number: %d\n", _edit_area->markerLine (_mhandle));
+}
+*/
+
+
+void
+marker::handle_marker_line_deleted (int mhandle)
+{
+  // FUTURE SUPPORT: There really should be a signal in QsciScintilla
+  // called markerLineDeleted (int mhandle) because there is no way
+  // of knowing this.  QsciScintilla will place the marker at a
+  // different line rather than remove it from the margin.  Will lobby
+  // for such a signal.
+  if (_mhandle == mhandle)
+    {
+      if (_marker_type == breakpoint || _marker_type == debugger_position)
+        {
+          int editor_linenr = _edit_area->markerLine (_mhandle);
+          _edit_area->markerDeleteHandle(_mhandle);
+          _marker_type = _marker_type == breakpoint ? unsure_breakpoint
+                                                    : unsure_debugger_position;
+          _mhandle = _edit_area->markerAdd (editor_linenr, _marker_type);
+        }
+    }
+}
+
+
+void
+marker::handle_marker_line_undeleted (int mhandle)
+{
+  // FUTURE SUPPORT: There really should be a signal in QsciScintilla
+  // called markerLineUndeleted (int mhandle) because there is no way
+  // of knowing this.  QsciScintilla will place the marker at a
+  // different line rather than remove it from the margin.  Will lobby
+  // for such a signal.
+  if (_mhandle == mhandle)
+    {
+      if (_marker_type == unsure_breakpoint || _marker_type == unsure_debugger_position)
+        {
+          int editor_linenr = _edit_area->markerLine (_mhandle);
+          _edit_area->markerDeleteHandle(_mhandle);
+          _marker_type = _marker_type == unsure_breakpoint ? breakpoint
+                                                           : debugger_position;
+          _mhandle = _edit_area->markerAdd (editor_linenr, _marker_type);
+        }
+    }
+}
+
+#endif
diff -r 7762d56dbc8a -r bc0b37932f7c libgui/src/m-editor/marker.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/m-editor/marker.h	Mon Apr 08 16:17:35 2013 -0500
@@ -0,0 +1,85 @@
+/*
+
+Copyright (C) 2011-2012 Jacob Dawid
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef MARKER_H
+#define MARKER_H
+
+#include <Qsci/qsciscintilla.h>
+#include <QObject>
+
+// Defined for purposes of sending QList<int> as part of signal.
+#include <QList>
+typedef QList<int> QIntList;
+
+// The breakpoint class keeps track of the debug line number that Octave core
+// uses and the handle of the marker inside the editor file.  If the editor
+// contents is modified, the debug line number and editor line number can be
+// out of alignment.  The marker handle can be used to retrieve the editor
+// line.
+
+enum editor_markers
+  {
+    bookmark,
+    breakpoint,
+    unsure_breakpoint,
+    debugger_position,
+    unsure_debugger_position
+  };
+
+class marker;
+class marker : public QObject
+{
+  Q_OBJECT
+
+public:
+  marker (QsciScintilla *edit_area, int original_linenr,
+          editor_markers marker_type);
+  marker (QsciScintilla *edit_area, int original_linenr,
+          editor_markers marker_type, int editor_linenr);
+  ~marker (void);
+
+public slots:
+  void handle_remove_via_original_linenr (int original_linenr);
+  void handle_request_remove_via_editor_linenr (int editor_linenr);
+  void handle_remove (void);
+  void handle_find_translation (int original_linenr, int& editor_linenr);
+  void handle_find_just_before (int linenr, int& original_linenr, int& editor_linenr);
+  void handle_find_just_after (int linenr, int& original_linenr, int& editor_linenr);
+/*  void handle_lines_changed (void);*/
+  void handle_marker_line_deleted (int mhandle);
+  void handle_marker_line_undeleted (int mhandle);
+  void handle_report_editor_linenr (QIntList& int_list);
+
+signals:
+  void request_remove (int original_linenr);
+
+private:
+  void construct (QsciScintilla *edit_area, int original_linenr,
+                  editor_markers marker_type, int editor_linenr);
+
+  QsciScintilla *       _edit_area;
+  int                   _original_linenr;
+  editor_markers        _marker_type;
+  int                   _mhandle;
+};
+
+#endif // MARKER_H
diff -r 7762d56dbc8a -r bc0b37932f7c libgui/src/module.mk
--- a/libgui/src/module.mk	Fri Apr 05 16:21:38 2013 -0700
+++ b/libgui/src/module.mk	Mon Apr 08 16:17:35 2013 -0500
@@ -6,6 +6,7 @@
 
 octave_gui_ICONS = \
   src/icons/arrow_right.png \
+  src/icons/arrow_right_gray.png \
   src/icons/artsbuilderexecute.png \
   src/icons/bookmark.png \
   src/icons/bp_next.png \
@@ -45,6 +46,7 @@
   src/icons/logo.png \
   src/icons/question.png \
   src/icons/redled.png \
+  src/icons/redled_gray.png \
   src/icons/redo.png \
   src/icons/search.png \
   src/icons/star.png \
@@ -63,7 +65,8 @@
   src/m-editor/moc-file-editor-tab.cc \
   src/m-editor/moc-file-editor.cc \
   src/m-editor/moc-find-dialog.cc \
-  src/m-editor/moc-lexer-octave-gui.cc
+  src/m-editor/moc-lexer-octave-gui.cc \
+  src/m-editor/moc-marker.cc
 endif
 
 octave_gui_MOC += \
@@ -103,6 +106,7 @@
   src/m-editor/file-editor.h \
   src/m-editor/find-dialog.h \
   src/m-editor/lexer-octave-gui.h \
+  src/m-editor/marker.h \
   src/main-window.h \
   src/octave-gui.h \
   src/octave-main-thread.h \
@@ -127,6 +131,7 @@
   src/m-editor/file-editor.cc \
   src/m-editor/find-dialog.cc \
   src/m-editor/lexer-octave-gui.cc \
+  src/m-editor/marker.cc \
   src/main-window.cc \
   src/octave-gui.cc \
   src/octave-main-thread.cc \
diff -r 7762d56dbc8a -r bc0b37932f7c libgui/src/resource.qrc
--- a/libgui/src/resource.qrc	Fri Apr 05 16:21:38 2013 -0700
+++ b/libgui/src/resource.qrc	Mon Apr 08 16:17:35 2013 -0500
@@ -14,7 +14,9 @@
         <file>icons/configure.png</file>
         <file>icons/filesaveas.png</file>
         <file>icons/redled.png</file>
+        <file>icons/redled_gray.png</file>
         <file>icons/arrow_right.png</file>
+        <file>icons/arrow_right_gray.png</file>
         <file>icons/bookmark.png</file>
         <file>icons/question.png</file>
         <file>icons/star.png</file>
diff -r 7762d56dbc8a -r bc0b37932f7c libgui/src/settings-dialog.cc
--- a/libgui/src/settings-dialog.cc	Fri Apr 05 16:21:38 2013 -0700
+++ b/libgui/src/settings-dialog.cc	Mon Apr 08 16:17:35 2013 -0500
@@ -76,6 +76,31 @@
   ui->general_icon_graphic-> setChecked (widget_icon_set == "GRAPHIC");
   ui->general_icon_letter-> setChecked (widget_icon_set == "LETTER");
 
+  // how breakpoints should behave when file is saved
+  QString breakpoint_filesave_behavior =
+      settings->value ("debugger/breakpoint_filesave_behavior", "ASK").toString ();
+  ui->debugger_filesave_ask->setChecked (true);  // the default (if invalid set)
+  ui->debugger_filesave_ask->setChecked (breakpoint_filesave_behavior == "ASK");
+  ui->debugger_filesave_restore->setChecked (breakpoint_filesave_behavior == "RESTORE");
+  ui->debugger_filesave_discard->setChecked (breakpoint_filesave_behavior == "DISCARD");
+
+  // what uncertain breakpoints and pointer should look like
+  QString uncertain_icon_set =
+      settings->value ("debugger/uncertain_icon_set", "SELECTED").toString ();
+  QPixmap tmpPixmap = QPixmap (":/actions/icons/arrow_right.png");
+  QIcon tmpIcon = QIcon (tmpPixmap);
+  tmpPixmap = tmpIcon.pixmap (tmpPixmap.size (), QIcon::Selected);
+  ui->debugger_icon_selected->setIcon (QIcon (tmpPixmap));
+  ui->debugger_icon_selected->setChecked (true);  // the default (if invalid set)
+  ui->debugger_icon_selected->setChecked (uncertain_icon_set == "SELECTED");
+  tmpPixmap = QPixmap (":/actions/icons/arrow_right.png");
+  tmpIcon = QIcon (tmpPixmap);
+  tmpPixmap = tmpIcon.pixmap (tmpPixmap.size (), QIcon::Disabled);
+  ui->debugger_icon_disabled->setIcon (QIcon (tmpPixmap));
+  ui->debugger_icon_disabled->setChecked (uncertain_icon_set == "DISABLED");
+  ui->debugger_icon_custom->setIcon (QIcon (QPixmap (":/actions/icons/arrow_right_gray.png")));
+  ui->debugger_icon_custom->setChecked (uncertain_icon_set == "CUSTOM");
+
   ui->useCustomFileEditor->setChecked (settings->value ("useCustomFileEditor",false).toBool ());
   ui->customFileEditor->setText (settings->value ("customFileEditor").toString ());
   ui->editor_showLineNumbers->setChecked (settings->value ("editor/showLineNumbers",true).toBool () );
@@ -231,13 +256,29 @@
   QSettings *settings = resource_manager::get_settings ();
   // FIXME -- what should happen if settings is 0?
 
+  // what uncertain breakpoints and pointer should look like
+  QString uncertain_icon_set = "SELECTED";
+  if (ui->debugger_icon_disabled->isChecked ())
+    uncertain_icon_set = "DISABLED";
+  else if (ui->debugger_icon_custom->isChecked ())
+    uncertain_icon_set = "CUSTOM";
+  settings->setValue ("debugger/uncertain_icon_set", uncertain_icon_set);
+
+  // how breakpoints should be treated when file is saved
+  QString breakpoint_filesave_behavior = "ASK";
+  if (ui->debugger_filesave_restore->isChecked ())
+    breakpoint_filesave_behavior = "RESTORE";
+  else if (ui->debugger_filesave_discard->isChecked ())
+    breakpoint_filesave_behavior = "DISCARD";
+  settings->setValue ("debugger/breakpoint_filesave_behavior", breakpoint_filesave_behavior);
+
   // the icon set
   QString widget_icon_set = "NONE";
   if (ui->general_icon_letter->isChecked ())
     widget_icon_set = "LETTER";
   else if (ui->general_icon_graphic->isChecked ())
     widget_icon_set = "GRAPHIC";
-  settings->setValue ("DockWidgets/widget_icon_set",widget_icon_set);
+  settings->setValue ("DockWidgets/widget_icon_set", widget_icon_set);
 
   // language
   QString language = ui->comboBox_language->currentText ();
diff -r 7762d56dbc8a -r bc0b37932f7c libgui/src/settings-dialog.ui
--- a/libgui/src/settings-dialog.ui	Fri Apr 05 16:21:38 2013 -0700
+++ b/libgui/src/settings-dialog.ui	Mon Apr 08 16:17:35 2013 -0500
@@ -397,6 +397,103 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tab_7">
+      <attribute name="title">
+       <string>Debugger</string>
+      </attribute>
+      <widget class="QWidget" name="verticalLayoutWidget_2">
+       <property name="geometry">
+        <rect>
+         <x>30</x>
+         <y>20</y>
+         <width>481</width>
+         <height>301</height>
+        </rect>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout_8">
+        <item>
+         <widget class="QGroupBox" name="groupBox_3">
+          <property name="title">
+           <string>Uncertain Position/Breakpoint Icon Set</string>
+          </property>
+          <widget class="QWidget" name="verticalLayoutWidget_4">
+           <property name="geometry">
+            <rect>
+             <x>10</x>
+             <y>30</y>
+             <width>325</width>
+             <height>80</height>
+            </rect>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_10">
+            <item>
+             <widget class="QRadioButton" name="debugger_icon_selected">
+              <property name="text">
+               <string>Selected</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QRadioButton" name="debugger_icon_disabled">
+              <property name="text">
+               <string>Disabled</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QRadioButton" name="debugger_icon_custom">
+              <property name="text">
+               <string>Custom</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="groupBox_2">
+          <property name="title">
+           <string>Breakpoint Retention Upon Saving File</string>
+          </property>
+          <widget class="QWidget" name="verticalLayoutWidget_3">
+           <property name="geometry">
+            <rect>
+             <x>10</x>
+             <y>30</y>
+             <width>325</width>
+             <height>80</height>
+            </rect>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_9">
+            <item>
+             <widget class="QRadioButton" name="debugger_filesave_ask">
+              <property name="text">
+               <string>Ask whether breakpoints should be restored</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QRadioButton" name="debugger_filesave_restore">
+              <property name="text">
+               <string>Automatically restore breakpoints</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QRadioButton" name="debugger_filesave_discard">
+              <property name="text">
+               <string>Discard breakpoints</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </widget>
      <widget class="QWidget" name="tab_2">
       <attribute name="title">
        <string>File Browser</string>
diff -r 7762d56dbc8a -r bc0b37932f7c libinterp/interpfcn/debug.cc
--- a/libinterp/interpfcn/debug.cc	Fri Apr 05 16:21:38 2013 -0700
+++ b/libinterp/interpfcn/debug.cc	Mon Apr 08 16:17:35 2013 -0500
@@ -307,7 +307,10 @@
                       std::string file = dbg_fcn->fcn_file_name ();
 
                       if (! file.empty ())
+{
                         octave_link::update_breakpoint (true, file, retval[i]);
+fprintf(stderr,"debug.cc: update_breakpoint, line 312, true\n");
+}
                     }
                 }
             }
@@ -362,7 +365,10 @@
                           cmds->delete_breakpoint (lineno);
 
                           if (! file.empty ())
+{
                             octave_link::update_breakpoint (false, file, lineno);
+fprintf(stderr,"debug.cc: update_breakpoint, line 370, false\n");
+}
                         }
                     }
 
@@ -411,7 +417,10 @@
               retval[i] = lineno;
 
               if (! file.empty ())
+{
                 octave_link::update_breakpoint (false, file, lineno);
+fprintf(stderr,"debug.cc: update_breakpoint, line 422, false\n");
+}
             }
 
           bp_set_iterator it = bp_set.find (fname);
