changeset 15848:424edeca3c66

Redo portions of file editor to use more signals/slots rather than casting. * file-editor-tab.cc, file-editor-tab.h (file_editor_tab::~file_editor_tab): Add. Delete lexer to prevent memory leak. Delete _edit_area to prevent memory leak. (file_editor_tab::conditional_close): Add. Simple slot that uses QWidget pointer as unique ID, not for function call. (file_editor_tab::file_name_query): Add. Simple slot that signals file name to whomever is connected. (file_editor_tab::find, file_editor_tab : public QWidget): Removed use of exec() and keep a pointer to the find_dialog as a member. Toggle hide()/show() via a connected slot to toggle visibility as desired. * file-editor.cc, file-editor.h, file-editor-tab.cc file-editor-tab.h (file_editor : public file_editor_interface, file_editor_tab : public QWidget, file_editor_tab::file_editor_tab, file_editor_tab::closeEvent, file_editor_tab::load_file, file_editor_tab::new_file, file_editor_tab::run_file): Remove _file_editor pointer member from file_editor_tab and rid file_editor::get_main_window from file_editor. There should be no need for such information about higher-level hierarchy inside lower-level objects. (file_editor::request_open_file, file_editor_tab::open_file): Move QFileDialog to file_editor::request_open_file and delete file_editor_tab::open_file since most of the remaining functionality is in file_editor_tab::load_file. (file_editor::active_editor_tab): Deleted. (file_editor::fetab_change_request, file_editor_tab::change_editor_state): Added to initiate a request for the editor tab to change focus. (file_editor_tab::editor_state_changed): Added arguments to pass the copy status and the directory path so that editor doesn't have to call functions for such information. (file_editor::handle_editor_state_changed): Add copying directory of the file_editor_tab to the current editing directory. (file_editor::check_conflict_save, file_editor_tab::editor_check_conflict_save, file_editor_tab::save_file_as, file_editor_tab::handle_save_file_as_answer): Moved a portion of the save-file-as dialog mechanism to the file_editor where all file names can be obtained to check for conflict with already open files. The new signal indicates to the editor that a name check be done, and in turn the editor signals the tab to save the file. * main-window.cc, file-editor.cc, file-editor.h, file-editor-interface.h (file_editor::terminal, file_editor : public file_editor_interface, file_editor_interface : public QDockWidget): Since file_editor_tab no longer looks up to main_window, remove _main_window and _terminal from file_editor and file_editor_interface, as well as file_editor::terminal. * file-editor-tab.cc (file_editor_tab::file_has_changed): Make the dialog boxes non-modal and use slots to handle user answers. (file_editor_tab::closeEvent): Remove portion that accesses upper hierarchy member functions, can find better approaches. (file_editor_tab::file_editor_tab): Make there no parent for QsciScintilla so that window modality can be set to individual editor. * file-editor-tab.cc, file-editor.cc (file_editor_tab::load_file): Use show() member rather than exec() and set modality to window so that rest of application may function. Return a QString with message rather than a boolean. * file-editor-tab.cc, (file_editor_tab::file_has_changed): Remove static variable alreadyAsking. Multiple file_editor_tabs are using this code so do not want to block recognition of multiple file having changed on disk (bug #37406). Instead, simply stop tracking via the file watcher. (file_editor_tab::save_file, file_editor_tab::save_file_as, file_editor_tab::handle_save_file_as_answer, file_editor_tab::handle_save_file_as_answer_close): Added a remove_on_success variable. Changed the QFileDialog to WindowModal and created slots to handle file selected signal and finished signal. Signal/slot connects vary based upon remove_on_success setting. (file_editor_tab::check_file_modified): Changed the QFileDialog to NonModal and attach some slots. Editor tab can't be parent in case deleted, so use read-only state of the editor area. * file-editor-tab.h (file_editor_tab : public QWidget): New signals for file_editor for tab and file name management. (file_editor_tab::get_file_name): Delete. * file-editor.h (file_editor : public file_editor_interface): Make QStringList sessionFileNames a member of file_editor so that it can retain data between file_editor_tab signals. Also can be used for checking precense of filenames and prevent opening multiple copies (bug #36869) Added signals for file editor tabs--settings_changed, fetab_close_request, and query_file_name. Three new slots for tab and file name management. * file-editor-interface.h, file-editor.h (file_editor_interface::add_file_editor_tab, file_editor::add_file_editor_tab): Made the text name for the tab an input variable. * file-editor.cc (file_editor::~file_editor): Replace dynamic_cast with simple signal querying all file editor tabs for file names which end up in savedSessionTabs. (file_editor::handle_file_name_changed): Dynamic cast not necessary since QObject and QWidget are compatible. (file_editor::handle_tab_close_request): Replace dynamic_cast with signal to request file_editor_tab with associated tabID tag should close. (file_editor::handle_tab_remove_request): Rename of handle_tab_close_request. Instead of dynamic cast, loop through pointers comparing QWidget* to QObject*, if same tag remove tab via index and also delete which fixes a memory leak. (file_editor::handle_add_filename_to_list): Simple slot that uses append() of the list member functions. (file_editor::notice_settings): Rather than dynamic cast, emit signal for the file_editor_tabs. (file_editor::add_file_editor_tab): New variety of connections for improved flow. (file_editor::request_open_file): Given error messages are made WindowModal, the tab shouldn't be delete if file open is not successful. The file_editor_tab takes care of that. (file_editor::request_open_file): Added check and message box for the requested file already open in editor. For the non-interactive overloaded version, open a message dialog box to tell the user file not found, e.g., could not find file in the settings when launched. (file_editor::request_open_file): Inquire file names and update list before checking for existence of files. Supply empty title to editor tab then have file_editor_tab update name. * file-editor-tab.h, file-editor-tab.cc, file-editor.cc (file_editor_tab::run_file): New signal process_octave_code. (file_editor::add_file_editor_tab): Connect signal process_octave_code to file_editor's parent's slot handle_command_double_clicked.
author Daniel J Sebald <daniel.sebald@ieee.org>
date Sun, 23 Dec 2012 14:33:48 -0600
parents 13d1e9bfa362
children e55a64f49346
files libgui/src/m-editor/file-editor-interface.h libgui/src/m-editor/file-editor-tab.cc libgui/src/m-editor/file-editor-tab.h libgui/src/m-editor/file-editor.cc libgui/src/m-editor/file-editor.h libgui/src/main-window.cc
diffstat 6 files changed, 1185 insertions(+), 749 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/m-editor/file-editor-interface.h	Tue Dec 25 19:41:12 2012 +0000
+++ b/libgui/src/m-editor/file-editor-interface.h	Sun Dec 23 14:33:48 2012 -0600
@@ -27,20 +27,15 @@
 #include <QMenu>
 #include <QToolBar>
 
-class QTerminal;
-class main_window;
-
 class file_editor_interface : public QDockWidget
 {
   Q_OBJECT
 
   public:
-  file_editor_interface (QTerminal *terminal, main_window *mainWindow)
-    : QDockWidget ((QWidget*)mainWindow) // QDockWidget constructor is explicit, hence the cast.
+  file_editor_interface (QWidget *p)
+    : QDockWidget (p)
   {
     setObjectName ("FileEditor");
-    _terminal = terminal;
-    _main_window = mainWindow;
 
     connect (this, SIGNAL (visibilityChanged (bool)), this,
              SLOT (handle_visibility_changed (bool)));
@@ -57,15 +52,12 @@
 public slots:
   virtual void request_new_file () = 0;
   virtual void request_open_file () = 0;
-  virtual void request_open_file (const QString& fileName, bool silent = false) = 0;
+  virtual void request_open_file (const QString& fileName) = 0;
 
 signals:
   void active_changed (bool active);
 
 protected:
-  QTerminal* _terminal;
-  main_window* _main_window;
-
   void closeEvent (QCloseEvent *e)
   {
     emit active_changed (false);
--- a/libgui/src/m-editor/file-editor-tab.cc	Tue Dec 25 19:41:12 2012 +0000
+++ b/libgui/src/m-editor/file-editor-tab.cc	Sun Dec 23 14:33:48 2012 -0600
@@ -42,19 +42,26 @@
 
 #include "file-editor-tab.h"
 #include "file-editor.h"
-#include "find-dialog.h"
 #include "octave-link.h"
 
 #include "debug.h"
 #include "oct-env.h"
 
-file_editor_tab::file_editor_tab(file_editor *fileEditor)
-  : QWidget ((QWidget*)fileEditor)
+// Make parent null for the file editor tab so that warning
+// WindowModal messages don't affect grandparents.
+file_editor_tab::file_editor_tab (QString directory)
 {
-  _file_editor = fileEditor;
-  _file_name = "";
+  // Make sure there is a slash at the end of the directory name
+  // for identification when saved later.
+  if (directory.count () && directory.at (directory.count () - 1) != '/')
+    directory.append ("/");
+  _file_name = directory;
   _edit_area = new QsciScintilla (this);
 
+  // Leave the find dialog box out of memory until requested.
+  _find_dialog = 0;
+  _find_dialog_is_visible = false;
+
   // symbols
   _edit_area->setMarginType (1, QsciScintilla::SymbolMargin);
   _edit_area->setMarginSensitivity (1, true);
@@ -106,57 +113,60 @@
   connect (&_file_system_watcher, SIGNAL (fileChanged (QString)),
            this, SLOT (file_has_changed (QString)));
 
-  _file_name = "";
-
   notice_settings ();
 }
 
-bool
-file_editor_tab::copy_available ()
+file_editor_tab::~file_editor_tab ()
 {
-  return _copy_available;
+  // Destroy items attached to _edit_area.
+  QsciLexer *lexer = _edit_area->lexer ();
+  if (lexer)
+    {
+      delete lexer;
+      _edit_area->setLexer(0);
+    }
+  if (_find_dialog)
+    {
+      delete _find_dialog;
+      _find_dialog = 0;
+    }
+
+  // Destroy _edit_area.
+  delete _edit_area;
 }
 
 void
 file_editor_tab::closeEvent (QCloseEvent *e)
 {
-  if (_file_editor->get_main_window ()->is_closing ())
+  // ignore close event if file is not saved and user cancels
+  // closing this window
+  if (check_file_modified ("Close File",
+                           QMessageBox::Cancel) == QMessageBox::Cancel)
     {
-      // close whole application: save file or not if modified
-      check_file_modified ("Closing Octave", 0); // no cancel possible
-      e->accept ();
+      e->ignore ();
     }
   else
     {
-      // ignore close event if file is not saved and user cancels
-      // closing this window
-      if (check_file_modified ("Close File",
-                               QMessageBox::Cancel) == QMessageBox::Cancel)
-        {
-          e->ignore ();
-        }
-      else
-        {
-          e->accept();
-        }
+      e->accept();
     }
 }
 
 void
 file_editor_tab::set_file_name (const QString& fileName)
 {
-  if (fileName != UNNAMED_FILE)
-    {
-      // update tracked file if wie really hae a file on disk
-      QStringList trackedFiles = _file_system_watcher.files ();
-      if (!trackedFiles.isEmpty ())
-        _file_system_watcher.removePath (_file_name);
-        _file_system_watcher.addPath (fileName);
-    }
+  // update tracked file if we really have a file on disk
+  QStringList trackedFiles = _file_system_watcher.files ();
+  if (!trackedFiles.isEmpty ())
+    _file_system_watcher.removePath (_file_name);
+  if (!fileName.isEmpty ())
+    _file_system_watcher.addPath (fileName);
   _file_name = fileName;
 
   // update lexer after _file_name change
   update_lexer ();
+
+  // update the file editor with current editing directory
+  emit editor_state_changed (_copy_available, QDir::cleanPath (_file_name));
 }
 
 void
@@ -191,7 +201,7 @@
 void
 file_editor_tab::update_lexer ()
 {
-  QsciLexer *lexer =  _edit_area->lexer ();
+  QsciLexer *lexer = _edit_area->lexer ();
   delete lexer;
 
   if (_file_name.endsWith (".m") || _file_name.endsWith (".M"))
@@ -246,151 +256,114 @@
 }
 
 void
-file_editor_tab::request_add_breakpoint (int line)
+file_editor_tab::undo (const QWidget* ID)
 {
-  QFileInfo file_info (_file_name);
-  QString path = file_info.absolutePath ();
-  QString function_name = file_info.fileName ();
+  if (ID != this)
+    return;
+
+  _edit_area->undo ();
+}
+
+void
+file_editor_tab::redo (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  _edit_area->redo ();
+}
 
-  // We have to cut off the suffix, because octave appends it.
-  function_name.chop (file_info.suffix ().length () + 1);
+void
+file_editor_tab::copy (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  _edit_area->copy ();
+}
 
-  bp_info info (path, function_name, line);
+void
+file_editor_tab::cut (const QWidget* ID)
+{
+  if (ID != this)
+    return;
 
-  octave_link::post_event
-    (this, &file_editor_tab::add_breakpoint_callback, info);
+  _edit_area->cut ();
+}
+
+void
+file_editor_tab::paste (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  _edit_area->paste ();
 }
 
 void
-file_editor_tab::request_remove_breakpoint (int line)
+file_editor_tab::save_file (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  save_file (_file_name);
+}
+void
+
+file_editor_tab::save_file (const QWidget* ID, const QString& fileName, bool remove_on_success)
+{
+  if (ID != this)
+    return;
+
+  save_file (fileName, remove_on_success);
+}
+
+void
+file_editor_tab::save_file_as (const QWidget* ID)
 {
+  if (ID != this)
+    return;
+
+  save_file_as ();
+}
+
+void
+file_editor_tab::run_file_callback (void)
+{
+  // Maybe someday we will do something here?
+}
+
+void
+file_editor_tab::run_file (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  if (_edit_area->isModified ())
+    save_file (_file_name);
+
   QFileInfo file_info (_file_name);
   QString path = file_info.absolutePath ();
+  QString current_path
+    = QString::fromStdString (octave_link::last_working_directory ());
   QString function_name = file_info.fileName ();
 
   // We have to cut off the suffix, because octave appends it.
   function_name.chop (file_info.suffix ().length () + 1);
-
-  bp_info info (path, function_name, line);
-
-  octave_link::post_event
-    (this, &file_editor_tab::remove_breakpoint_callback, info);
-}
-
-void
-file_editor_tab::comment_selected_text ()
-{
-  do_comment_selected_text (true);
-}
-
-void
-file_editor_tab::uncomment_selected_text ()
-{
-  do_comment_selected_text (false);
-}
-
-void
-file_editor_tab::do_comment_selected_text (bool comment)
-{
-  if ( _edit_area->hasSelectedText() )
-    {
-      int lineFrom, lineTo, colFrom, colTo, i;
-      _edit_area->getSelection (&lineFrom,&colFrom,&lineTo,&colTo);
-      if ( colTo == 0 )  // the beginning of last line is not selected
-        lineTo--;        // stop at line above
-      _edit_area->beginUndoAction ();
-      for ( i=lineFrom; i<=lineTo; i++ )
-        {
-          if ( comment )
-            _edit_area->insertAt("%",i,0);
-          else
-            {
-              QString line(_edit_area->text(i));
-              if ( line.startsWith("%") )
-                {
-                  _edit_area->setSelection(i,0,i,1);
-                  _edit_area->removeSelectedText();
-                }
-            }
-        }
-      _edit_area->endUndoAction ();
-    }
-}
-
-void
-file_editor_tab::find ()
-{
-  find_dialog dialog (_edit_area);
-  dialog.exec ();
+  emit process_octave_code (QString ("cd \'%1\'\n%2\n")
+                    .arg(path).arg (function_name));
+ 
+  // TODO: Sending a run event crashes for long scripts. Find out why.
+  // octave_link::post_event
+  //   (this, &file_editor_tab::run_file_callback, _file_name.toStdString ()));
 }
 
 void
-file_editor_tab::update_window_title (bool modified)
-{
-  QString title(_file_name);
-  if ( !_long_title )
-    {
-      QFileInfo file(_file_name);
-      title = file.fileName();
-    }
-
-  if ( modified )
-    {
-      emit file_name_changed (title.prepend("* "));
-    }
-  else
-    emit file_name_changed (title);
-}
-
-void
-file_editor_tab::handle_copy_available(bool enableCopy)
-{
-  _copy_available = enableCopy;
-  emit editor_state_changed ();
-}
-
-int
-file_editor_tab::check_file_modified (const QString& msg, int cancelButton)
+file_editor_tab::toggle_bookmark (const QWidget* ID)
 {
-  int decision = QMessageBox::Yes;
-  if (_edit_area->isModified ())
-    {
-      // file is modified but not saved, ask user what to do
-      decision = QMessageBox::warning (this,
-                                       msg,
-                                       tr ("The file %1\n"
-                                           "has been modified. Do you want to save the changes?").
-                                       arg (_file_name),
-                                       QMessageBox::Save,
-                                       QMessageBox::Discard, cancelButton );
-      if (decision == QMessageBox::Save)
-        {
-          save_file ();
-          if (_edit_area->isModified ())
-            {
-              // If the user attempted to save the file, but it's still
-              // modified, then probably something went wrong, so return
-              // cancel for cancel this operation or try to save files
-              // as if cancel not possible
-              if ( cancelButton )
-                return (QMessageBox::Cancel);
-              else
-                save_file_as ();
-            }
-        }
-    }
-  return (decision);
-}
+  if (ID != this)
+    return;
 
-void
-file_editor_tab::remove_bookmark ()
-{
-  _edit_area->markerDeleteAll (bookmark);
-}
-
-void
-file_editor_tab::toggle_bookmark ()
-{
   int line, cur;
   _edit_area->getCursorPosition (&line,&cur);
   if ( _edit_area->markersAtLine (line) && (1 << bookmark) )
@@ -400,8 +373,11 @@
 }
 
 void
-file_editor_tab::next_bookmark()
+file_editor_tab::next_bookmark (const QWidget* ID)
 {
+  if (ID != this)
+    return;
+
   int line, cur, nextline;
   _edit_area->getCursorPosition (&line, &cur);
   if ( _edit_area->markersAtLine (line) && (1 << bookmark) )
@@ -411,8 +387,11 @@
 }
 
 void
-file_editor_tab::previous_bookmark ()
+file_editor_tab::previous_bookmark (const QWidget* ID)
 {
+  if (ID != this)
+    return;
+
   int line, cur, prevline;
   _edit_area->getCursorPosition (&line, &cur);
   if ( _edit_area->markersAtLine (line) && (1 << bookmark) )
@@ -422,362 +401,12 @@
 }
 
 void
-file_editor_tab::remove_all_breakpoints ()
-{
-  QFileInfo file_info (_file_name);
-  QString path = file_info.absolutePath ();
-  QString function_name = file_info.fileName ();
-
-  // We have to cut off the suffix, because octave appends it.
-  function_name.chop (file_info.suffix ().length () + 1);
-
-  bp_info info (path, function_name, 0);
-
-  octave_link::post_event
-    (this, &file_editor_tab::remove_all_breakpoints_callback, info);
-}
-
-void
-file_editor_tab::toggle_breakpoint ()
-{
-  int line, cur;
-  _edit_area->getCursorPosition (&line, &cur);
-  if ( _edit_area->markersAtLine (line) && (1 << breakpoint) )
-    request_remove_breakpoint (line);
-  else
-    request_add_breakpoint (line);
-}
-
-void
-file_editor_tab::next_breakpoint ()
-{
-  int line, cur, nextline;
-  _edit_area->getCursorPosition (&line, &cur);
-  if ( _edit_area->markersAtLine (line) && (1 << breakpoint) )
-    line++; // we have a breakpoint here, so start search from next line
-  nextline = _edit_area->markerFindNext (line, (1 << breakpoint));
-  _edit_area->setCursorPosition (nextline, 0);
-}
-
-void
-file_editor_tab::previous_breakpoint ()
-{
-  int line, cur, prevline;
-  _edit_area->getCursorPosition (&line, &cur);
-  if ( _edit_area->markersAtLine (line) && (1 << breakpoint) )
-    line--; // we have a breakpoint here, so start search from prev line
-  prevline = _edit_area->markerFindPrevious (line, (1 << breakpoint));
-  _edit_area->setCursorPosition (prevline, 0);
-}
-
-void
-file_editor_tab::cut ()
-{
-  _edit_area->cut ();
-}
-
-void
-file_editor_tab::copy ()
-{
-  _edit_area->copy ();
-}
-
-void
-file_editor_tab::paste ()
-{
-  _edit_area->paste ();
-}
-
-void
-file_editor_tab::undo ()
-{
-  _edit_area->undo ();
-}
-
-void
-file_editor_tab::redo ()
-{
-  _edit_area->redo ();
-}
-
-void
-file_editor_tab::set_debugger_position (int line)
+file_editor_tab::remove_bookmark (const QWidget* ID)
 {
-  _edit_area->markerDeleteAll (debugger_position);
-  if (line > 0)
-    {
-      _edit_area->markerAdd (line, debugger_position);
-    }
-}
-
-void
-file_editor_tab::set_modified (bool modified)
-{
-  _edit_area->setModified (modified);
-}
-
-bool
-file_editor_tab::open_file (const QString& dir)
-{
-  QString openFileName;
-  QFileDialog fileDialog(this);
-  fileDialog.setNameFilter(SAVE_FILE_FILTER);
-  fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
-  fileDialog.setViewMode(QFileDialog::Detail);
-  fileDialog.setDirectory(dir);
-  if (fileDialog.exec () == QDialog::Accepted)
-    {
-      openFileName = fileDialog.selectedFiles().at(0);
-      if (openFileName.isEmpty ())
-        return false;
-
-      return load_file(openFileName);
-    }
-  else
-    {
-      return false;
-    }
-}
-
-bool
-file_editor_tab::load_file(const QString& fileName, bool silent)
-{
-  if (!_file_editor->isVisible ())
-    {
-      _file_editor->show ();
-    }
-
-  QFile file (fileName);
-  if (!file.open (QFile::ReadOnly))
-    {
-      if (silent==false)
-        QMessageBox::warning (this, tr ("Octave Editor"),
-                              tr ("Could not open file %1 for read:\n%2.").arg (fileName).
-                              arg (file.errorString ()));
-      return false;
-    }
-
-  QTextStream in (&file);
-  QApplication::setOverrideCursor (Qt::WaitCursor);
-  _edit_area->setText (in.readAll ());
-  QApplication::restoreOverrideCursor ();
-
-  set_file_name (fileName);
-  update_window_title (false); // window title (no modification)
-  _edit_area->setModified (false); // loaded file is not modified yet
-
-  return true;
-}
-
-void
-file_editor_tab::new_file ()
-{
-  if (!_file_editor->isVisible ())
-    {
-      _file_editor->show ();
-    }
-
-  set_file_name (UNNAMED_FILE);
-  update_window_title (false); // window title (no modification)
-  _edit_area->setText ("");
-  _edit_area->setModified (false); // new file is not modified yet
-}
-
-bool file_editor_tab::save_file()
-{
-  return save_file (_file_name);
-}
-
-bool
-file_editor_tab::save_file (const QString& saveFileName)
-{
-  // it is a new file with the name "<unnamed>" -> call saveFielAs
-  if (saveFileName == UNNAMED_FILE || saveFileName.isEmpty ())
-    {
-      return save_file_as();
-    }
+  if (ID != this)
+    return;
 
-  // remove the file to save from the tracker since we will change it on disk now
-  QStringList watched_files = _file_system_watcher.files();
-  if (!watched_files.isEmpty ())
-    _file_system_watcher.removePath(saveFileName);  
-    
-  // open the file for writing
-  QFile file (saveFileName);
-  if (!file.open (QFile::WriteOnly))
-    {
-      QMessageBox::warning (this, tr ("Octave Editor"),
-                            tr ("Could not open file %1 for write:\n%2.").
-                            arg (saveFileName).arg (file.errorString ()));
-      return false;
-    }
-
-  // save the contents into the file
-  QTextStream out (&file);
-  QApplication::setOverrideCursor (Qt::WaitCursor);
-  out << _edit_area->text ();
-  QApplication::restoreOverrideCursor ();
-  file.close();
-
-  // save file name after closing file otherwise tracker will notice file change
-  set_file_name (saveFileName);
-  // set the window title to actual file name (not modified)
-  update_window_title (false);
-  // files is save -> not modified
-  _edit_area->setModified (false);
-
-  return true;
-}
-
-bool
-file_editor_tab::save_file_as ()
-{
-  QString saveFileName(_file_name);
-  QFileDialog fileDialog(this);
-  if (saveFileName == UNNAMED_FILE || saveFileName.isEmpty ())
-    {
-      QString directory = QString::fromStdString
-        (octave_link::last_working_directory ());
-
-      if (directory.isEmpty ())
-        {
-          directory = QDir::homePath ();
-        }
-
-      fileDialog.setDirectory (directory);
-    }
-  else
-    {
-      fileDialog.selectFile (saveFileName);
-    }
-  fileDialog.setNameFilter (SAVE_FILE_FILTER);
-  fileDialog.setDefaultSuffix ("m");
-  fileDialog.setAcceptMode (QFileDialog::AcceptSave);
-  fileDialog.setViewMode (QFileDialog::Detail);
-
-  if (fileDialog.exec ())
-    {
-      saveFileName = fileDialog.selectedFiles ().at (0);
-      if (saveFileName.isEmpty ())
-        return false;
-
-      return save_file (saveFileName);
-    }
-
-  return false;
-}
-
-void
-file_editor_tab::run_file ()
-{
-  if (_edit_area->isModified ())
-    save_file(_file_name);
-
-  QFileInfo file_info (_file_name);
-  QString path = file_info.absolutePath ();
-  QString current_path
-    = QString::fromStdString (octave_link::last_working_directory ());
-  QString function_name = file_info.fileName ();
-
-  // We have to cut off the suffix, because octave appends it.
-  function_name.chop (file_info.suffix ().length () + 1);
-  _file_editor->terminal ()->sendText (QString ("cd \'%1\'\n%2\n")
-                                       .arg(path).arg (function_name));
-  // TODO: Sending a run event crashes for long scripts. Find out why.
-  // octave_link::post_event
-  //   (this, &file_editor_tab::run_file_callback, _file_name.toStdString ()));
-}
-
-void
-file_editor_tab::file_has_changed (const QString&)
-{
-  if (QFile::exists (_file_name))
-    {
-      // Prevent popping up multiple message boxes when the file has
-      // been changed multiple times.
-      static bool alreadyAsking = false;
-      if (!alreadyAsking)
-        {
-          alreadyAsking = true;
-
-          int decision =
-            QMessageBox::warning (this, tr ("Octave Editor"),
-                                  tr ("It seems that \'%1\' has been modified by another application. Do you want to reload it?").
-                                  arg (_file_name), QMessageBox::Yes,
-                                  QMessageBox::No);
-
-          if (decision == QMessageBox::Yes)
-            {
-              load_file (_file_name);
-            }
-
-          alreadyAsking = false;
-        }
-    }
-  else
-    {
-      int decision =
-        QMessageBox::warning (this, tr ("Octave Editor"),
-                              tr ("It seems that \'%1\' has been deleted or renamed. Do you want to save it now?").
-                              arg (_file_name), QMessageBox::Save,
-                              QMessageBox::Close);
-      if (decision == QMessageBox::Save)
-        {
-          if (!save_file_as ())
-            {
-              set_file_name (UNNAMED_FILE);
-              update_window_title (true); // window title (no modification)
-              set_modified (true);
-            }
-        }
-      else
-        {
-          emit close_request ();
-        }
-    }
-}
-
-void
-file_editor_tab::notice_settings ()
-{
-  QSettings *settings = resource_manager::get_settings ();
-
-  if (settings==NULL)
-    return; // this shouldn't happen!
-
-  _edit_area->setCaretLineVisible(settings->value ("editor/highlightCurrentLine",true).toBool ());
-
-  if (settings->value ("editor/codeCompletion",true).toBool ())
-    _edit_area->setAutoCompletionThreshold (1);
-  else
-    _edit_area->setAutoCompletionThreshold (-1);
-
-  QFont font( settings->value ("editor/fontName","Courier").toString () ,
-              settings->value ("editor/fontSize",10).toInt () );
-  if (settings->value ("editor/showLineNumbers",true).toBool ())
-    {
-      _edit_area->setMarginLineNumbers (2, true);
-      _edit_area->setMarginsFont( font );
-      QFontMetrics metrics( font );
-      _edit_area->setMarginWidth(2, metrics.width("9999"));
-    }
-  else
-    {
-      _edit_area->setMarginLineNumbers (2, false);
-      _edit_area->setMarginWidth(2, 0);
-    }
-
-  update_lexer ();
-
-  _long_title = settings->value ("editor/longWindowTitle",false).toBool ();
-
-  update_window_title (false);
-}
-
-void
-file_editor_tab::run_file_callback (void)
-{
-  // Maybe someday we will do something here?
+  _edit_area->markerDeleteAll (bookmark);
 }
 
 void
@@ -831,3 +460,636 @@
   if (intmap.size() > 0)
     _edit_area->markerDeleteAll (breakpoint);
 }
+
+void
+file_editor_tab::request_add_breakpoint (int line)
+{
+  QFileInfo file_info (_file_name);
+  QString path = file_info.absolutePath ();
+  QString function_name = file_info.fileName ();
+
+  // We have to cut off the suffix, because octave appends it.
+  function_name.chop (file_info.suffix ().length () + 1);
+
+  bp_info info (path, function_name, line);
+
+  octave_link::post_event
+    (this, &file_editor_tab::add_breakpoint_callback, info);
+}
+
+void
+file_editor_tab::request_remove_breakpoint (int line)
+{
+  QFileInfo file_info (_file_name);
+  QString path = file_info.absolutePath ();
+  QString function_name = file_info.fileName ();
+
+  // We have to cut off the suffix, because octave appends it.
+  function_name.chop (file_info.suffix ().length () + 1);
+
+  bp_info info (path, function_name, line);
+
+  octave_link::post_event
+    (this, &file_editor_tab::remove_breakpoint_callback, info);
+}
+
+void
+file_editor_tab::toggle_breakpoint (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  int line, cur;
+  _edit_area->getCursorPosition (&line, &cur);
+  if ( _edit_area->markersAtLine (line) && (1 << breakpoint) )
+    request_remove_breakpoint (line);
+  else
+    request_add_breakpoint (line);
+}
+
+void
+file_editor_tab::next_breakpoint (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  int line, cur, nextline;
+  _edit_area->getCursorPosition (&line, &cur);
+  if ( _edit_area->markersAtLine (line) && (1 << breakpoint) )
+    line++; // we have a breakpoint here, so start search from next line
+  nextline = _edit_area->markerFindNext (line, (1 << breakpoint));
+  _edit_area->setCursorPosition (nextline, 0);
+}
+
+void
+file_editor_tab::previous_breakpoint (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  int line, cur, prevline;
+  _edit_area->getCursorPosition (&line, &cur);
+  if ( _edit_area->markersAtLine (line) && (1 << breakpoint) )
+    line--; // we have a breakpoint here, so start search from prev line
+  prevline = _edit_area->markerFindPrevious (line, (1 << breakpoint));
+  _edit_area->setCursorPosition (prevline, 0);
+}
+
+void
+file_editor_tab::remove_all_breakpoints (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  QFileInfo file_info (_file_name);
+  QString path = file_info.absolutePath ();
+  QString function_name = file_info.fileName ();
+
+  // We have to cut off the suffix, because octave appends it.
+  function_name.chop (file_info.suffix ().length () + 1);
+
+  bp_info info (path, function_name, 0);
+
+  octave_link::post_event
+    (this, &file_editor_tab::remove_all_breakpoints_callback, info);
+}
+
+void
+file_editor_tab::comment_selected_text (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  do_comment_selected_text (true);
+}
+
+void
+file_editor_tab::uncomment_selected_text (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  do_comment_selected_text (false);
+}
+
+void
+file_editor_tab::handle_find_dialog_finished (int)
+{
+  // Find dialog is going to hide.  Save location of window for
+  // when it is reshown.
+  _find_dialog_geometry = _find_dialog->geometry ();
+  _find_dialog_is_visible = false;
+}
+
+void
+file_editor_tab::find (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  // The find_dialog feature doesn't need a slot for return info.
+  // Rather than Qt::DeleteOnClose, let the find feature hang about
+  // in case it contains useful information like previous searches
+  // and so on.  Perhaps one find dialog for the whole editor is
+  // better, but individual find dialogs has the nice feature of
+  // retaining position per file editor tabs, which can be undocked.
+
+  if (!_find_dialog)
+    {
+       _find_dialog = new find_dialog (_edit_area);
+      connect (_find_dialog, SIGNAL (finished (int)),
+               this, SLOT (handle_find_dialog_finished (int)));
+      _find_dialog->setWindowModality (Qt::NonModal);
+      _find_dialog_geometry = _find_dialog->geometry ();
+    }
+
+  if (!_find_dialog->isVisible ())
+    {
+      _find_dialog->setGeometry (_find_dialog_geometry);
+      _find_dialog->show ();
+      _find_dialog_is_visible = true;
+    }
+
+  _find_dialog->activateWindow ();
+}
+
+void
+file_editor_tab::do_comment_selected_text (bool comment)
+{
+  if ( _edit_area->hasSelectedText() )
+    {
+      int lineFrom, lineTo, colFrom, colTo, i;
+      _edit_area->getSelection (&lineFrom,&colFrom,&lineTo,&colTo);
+      if ( colTo == 0 )  // the beginning of last line is not selected
+        lineTo--;        // stop at line above
+      _edit_area->beginUndoAction ();
+      for ( i=lineFrom; i<=lineTo; i++ )
+        {
+          if ( comment )
+            _edit_area->insertAt("%",i,0);
+          else
+            {
+              QString line(_edit_area->text(i));
+              if ( line.startsWith("%") )
+                {
+                  _edit_area->setSelection(i,0,i,1);
+                  _edit_area->removeSelectedText();
+                }
+            }
+        }
+      _edit_area->endUndoAction ();
+    }
+}
+
+void
+file_editor_tab::update_window_title (bool modified)
+{
+  QString title ("");
+  if (_file_name.isEmpty () || _file_name.at (_file_name.count () - 1) == '/')
+    title = UNNAMED_FILE;
+  else
+    title = _file_name;
+  if ( !_long_title )
+    {
+      QFileInfo file(_file_name);
+      title = file.fileName();
+    }
+
+  if ( modified )
+    {
+      emit file_name_changed (title.prepend("* "));
+    }
+  else
+    emit file_name_changed (title);
+}
+
+void
+file_editor_tab::handle_copy_available(bool enableCopy)
+{
+  _copy_available = enableCopy;
+  emit editor_state_changed (_copy_available, QDir::cleanPath (_file_name));
+}
+
+int
+file_editor_tab::check_file_modified (const QString& msg, int cancelButton)
+{
+  int decision = QMessageBox::Yes;
+  if (_edit_area->isModified ())
+    {
+      // File is modified but not saved, ask user what to do.  The file
+      // editor tab can't be made parent because it may be deleted depending
+      // upon the response.  Instead, change the _edit_area to read only.
+      QMessageBox* msgBox = new QMessageBox (
+              QMessageBox::Warning, tr ("Octave Editor"),
+              tr ("The file \'%1\' has been modified. Do you want to save the changes?").
+              arg (_file_name), QMessageBox::Yes | QMessageBox::No, 0);
+      _edit_area->setReadOnly (true);
+      connect (msgBox, SIGNAL (finished (int)),
+               this, SLOT (handle_file_modified_answer (int)));
+      msgBox->setWindowModality (Qt::NonModal);
+      msgBox->setAttribute (Qt::WA_DeleteOnClose);
+      msgBox->show ();
+      return (QMessageBox::Cancel);
+    }
+  else
+    {
+      // Nothing was modified, just remove from editor.
+      emit tab_remove_request ();
+    }
+ 
+  return (decision);
+}
+
+void
+file_editor_tab::handle_file_modified_answer (int decision)
+{
+  if (decision == QMessageBox::Yes)
+    {
+      // Save file, then remove from editor.
+      save_file (_file_name, true);
+    }
+  else if (decision == QMessageBox::No)
+    {
+      // User doesn't want to save, just remove from editor.
+      emit tab_remove_request ();
+    }
+  else
+    {
+      // User canceled, allow editing again.
+      _edit_area->setReadOnly (false);
+    }
+}
+
+void
+file_editor_tab::set_modified (bool modified)
+{
+  _edit_area->setModified (modified);
+}
+
+QString
+file_editor_tab::load_file(const QString& fileName)
+{
+  QFile file (fileName);
+  if (!file.open (QFile::ReadOnly))
+    {
+      return file.errorString ();
+    }
+
+  QTextStream in (&file);
+  QApplication::setOverrideCursor (Qt::WaitCursor);
+  _edit_area->setText (in.readAll ());
+  QApplication::restoreOverrideCursor ();
+
+  set_file_name (fileName);
+  update_window_title (false); // window title (no modification)
+  _edit_area->setModified (false); // loaded file is not modified yet
+
+  return QString ();
+}
+
+void
+file_editor_tab::new_file ()
+{
+  update_window_title (false); // window title (no modification)
+  _edit_area->setText ("");
+  _edit_area->setModified (false); // new file is not modified yet
+}
+
+void
+file_editor_tab::save_file (const QString& saveFileName, bool remove_on_success)
+{
+  // If it is a new file with no name, signal that saveFileAs
+  // should be performed.
+  if (saveFileName.isEmpty () || saveFileName.at (saveFileName.count () - 1) == '/')
+     {
+      save_file_as (remove_on_success);
+      return;
+    }
+
+  // stop watching file
+  QStringList trackedFiles = _file_system_watcher.files ();
+  if (!trackedFiles.isEmpty ())
+    _file_system_watcher.removePath (saveFileName);
+
+  // open the file for writing
+  QFile file (saveFileName);
+  if (!file.open (QIODevice::WriteOnly))
+    {
+      // Unsuccessful, begin watching file again if it was being
+      // watched previously.
+      if (trackedFiles.contains (saveFileName))
+        _file_system_watcher.addPath (saveFileName);
+
+      // Create a NonModal message about error.
+      QMessageBox* msgBox = new QMessageBox (
+              QMessageBox::Critical, tr ("Octave Editor"),
+              tr ("Could not open file %1 for write:\n%2.").
+              arg (saveFileName).arg (file.errorString ()),
+              QMessageBox::Ok, 0);
+      msgBox->setWindowModality (Qt::NonModal);
+      msgBox->setAttribute (Qt::WA_DeleteOnClose);
+      msgBox->show ();
+      return;
+    }
+
+  // save the contents into the file
+  QTextStream out (&file);
+  QApplication::setOverrideCursor (Qt::WaitCursor);
+  out << _edit_area->text ();
+  QApplication::restoreOverrideCursor ();
+  file.close();
+
+  // save file name after closing file as set_file_name starts watching again
+  set_file_name (saveFileName);
+  // set the window title to actual file name (not modified)
+  update_window_title (false);
+  // files is save -> not modified
+  _edit_area->setModified (false);
+
+  if (remove_on_success)
+    {
+      emit tab_remove_request ();
+      return;  // Don't touch member variables after removal
+    }
+}
+
+void
+file_editor_tab::save_file_as (bool remove_on_success)
+{
+  // Simply put up the file chooser dialog box with a slot connection
+  // then return control to the system waiting for a file selection.
+
+  // If the tab is removed in response to a QFileDialog signal, the tab
+  // can't be a parent.
+  QFileDialog* fileDialog;
+  if (remove_on_success)
+    {
+      // If tab is closed, "this" cannot be parent in which case modality
+      // has no effect.  Disable editing instead.
+      _edit_area->setReadOnly (true);
+      fileDialog = new QFileDialog ();
+    }
+  else
+    fileDialog = new QFileDialog (this);
+
+  if (!_file_name.isEmpty () && _file_name.at (_file_name.count () - 1) != '/')
+    {
+      fileDialog->selectFile (_file_name);
+    }
+  else
+    {
+      fileDialog->selectFile ("");
+      if (_file_name.isEmpty ())
+        {
+          fileDialog->setDirectory (QDir::currentPath ());
+        }
+      else
+        {
+          // The file name is actually the directory name from the
+          // constructor argument.
+          fileDialog->setDirectory (_file_name);
+        }
+    }
+  fileDialog->setNameFilter (SAVE_FILE_FILTER);
+  fileDialog->setDefaultSuffix ("m");
+  fileDialog->setAcceptMode (QFileDialog::AcceptSave);
+  fileDialog->setViewMode (QFileDialog::Detail);
+  if (remove_on_success)
+    {
+      connect (fileDialog, SIGNAL (fileSelected (const QString&)),
+               this, SLOT (handle_save_file_as_answer_close (const QString&)));
+      connect (fileDialog, SIGNAL (rejected ()),
+               this, SLOT (handle_save_file_as_answer_cancel ()));
+    }
+  else
+    {
+      connect (fileDialog, SIGNAL (fileSelected (const QString&)),
+               this, SLOT (handle_save_file_as_answer (const QString&)));
+    }
+  fileDialog->setWindowModality (Qt::WindowModal);
+  fileDialog->setAttribute (Qt::WA_DeleteOnClose);
+  fileDialog->show ();
+}
+
+void
+file_editor_tab::message_duplicate_file_name (const QString& saveFileName)
+{
+  // Could overwrite the file here (and tell user the file was
+  // overwritten), but the user could have unintentionally
+  // selected the same name not intending to overwrite.
+
+  // Create a NonModal message about error.
+  QMessageBox* msgBox = new QMessageBox (
+          QMessageBox::Critical, tr ("Octave Editor"),
+          tr ("File not saved!  You've selected a file name\n\n     %1\n\nwhich is the same as the current file name.  Use ""Save"" to overwrite.  (Could allow overwriting, with message, if that is what folks want.)").
+          arg (saveFileName),
+          QMessageBox::Ok, 0);
+  msgBox->setWindowModality (Qt::NonModal);
+  msgBox->setAttribute (Qt::WA_DeleteOnClose);
+  msgBox->show ();
+}
+
+void
+file_editor_tab::handle_save_file_as_answer (const QString& saveFileName)
+{
+  if (saveFileName == _file_name)
+    {
+      message_duplicate_file_name (saveFileName);
+      // Nothing done, allow editing again.
+      _edit_area->setReadOnly (false);
+    }
+  else
+    {
+      // Have editor check for conflict, do not delete tab after save.
+      emit editor_check_conflict_save (saveFileName, false);
+    }
+}
+
+void
+file_editor_tab::handle_save_file_as_answer_close (const QString& saveFileName)
+{
+  if (saveFileName == _file_name)
+    {
+      message_duplicate_file_name (saveFileName);
+      // Nothing done, allow editing again.
+      _edit_area->setReadOnly (false);
+    }
+  else
+    {
+      // Have editor check for conflict, delete tab after save.
+      emit editor_check_conflict_save (saveFileName, true);
+    }
+}
+
+void
+file_editor_tab::handle_save_file_as_answer_cancel ()
+{
+  // User canceled, allow editing again.
+  _edit_area->setReadOnly (false);
+}
+
+void
+file_editor_tab::file_has_changed (const QString&)
+{
+  // Prevent popping up multiple message boxes when the file has
+  // been changed multiple times by temporarily removing from the
+  // file watcher.
+  QStringList trackedFiles = _file_system_watcher.files ();
+  if (!trackedFiles.isEmpty ())
+    _file_system_watcher.removePath (_file_name);
+
+  if (QFile::exists (_file_name))
+    {
+      // Create a WindowModal message that blocks the edit area
+      // by making _edit_area parent.
+      QMessageBox* msgBox = new QMessageBox (
+              QMessageBox::Warning, tr ("Octave Editor"),
+              tr ("It seems that \'%1\' has been modified by another application. Do you want to reload it?").
+              arg (_file_name), QMessageBox::Yes | QMessageBox::No, this);
+      connect (msgBox, SIGNAL (finished (int)),
+               this, SLOT (handle_file_reload_answer (int)));
+      msgBox->setWindowModality (Qt::WindowModal);
+      msgBox->setAttribute (Qt::WA_DeleteOnClose);
+      msgBox->show ();
+    }
+  else
+    {
+      // Create a WindowModal message that blocks the edit area
+      // by making _edit_area parent.
+      QMessageBox* msgBox = new QMessageBox (
+              QMessageBox::Warning, tr ("Octave Editor"),
+              tr ("It seems that \'%1\' has been deleted or renamed. Do you want to save it now?").
+              arg (_file_name), QMessageBox::Save | QMessageBox::Close, this);
+      connect (msgBox, SIGNAL (finished (int)),
+               this, SLOT (handle_file_resave_answer (int)));
+      msgBox->setWindowModality (Qt::WindowModal);
+      msgBox->setAttribute (Qt::WA_DeleteOnClose);
+      msgBox->show ();
+    }
+}
+
+void
+file_editor_tab::notice_settings ()
+{
+  QSettings *settings = resource_manager::get_settings ();
+
+  if (settings==NULL)
+    return; // this shouldn't happen!
+
+  _edit_area->setCaretLineVisible(settings->value ("editor/highlightCurrentLine",true).toBool ());
+
+  if (settings->value ("editor/codeCompletion",true).toBool ())
+    _edit_area->setAutoCompletionThreshold (1);
+  else
+    _edit_area->setAutoCompletionThreshold (-1);
+
+  QFont font( settings->value ("editor/fontName","Courier").toString () ,
+              settings->value ("editor/fontSize",10).toInt () );
+  if (settings->value ("editor/showLineNumbers",true).toBool ())
+    {
+      _edit_area->setMarginLineNumbers (2, true);
+      _edit_area->setMarginsFont( font );
+      QFontMetrics metrics( font );
+      _edit_area->setMarginWidth(2, metrics.width("9999"));
+    }
+  else
+    {
+      _edit_area->setMarginLineNumbers (2, false);
+      _edit_area->setMarginWidth(2, 0);
+    }
+
+  update_lexer ();
+
+  _long_title = settings->value ("editor/longWindowTitle",false).toBool ();
+
+  update_window_title (false);
+}
+
+void
+file_editor_tab::conditional_close (const QWidget* ID)
+{
+  if (ID != this)
+    return;
+
+  close ();
+}
+
+void
+file_editor_tab::change_editor_state (const QWidget* ID)
+{
+  if (ID != this)
+    {
+      // Widget may be going out of focus.  If so, record location.
+      if (_find_dialog)
+        {
+          if (_find_dialog->isVisible ())
+            {
+              _find_dialog_geometry = _find_dialog->geometry ();
+              _find_dialog->hide ();
+            }
+        }
+      return;
+    }
+
+  if (_find_dialog && _find_dialog_is_visible)
+    {
+      _find_dialog->setGeometry (_find_dialog_geometry);
+      _find_dialog->show ();
+    }
+  emit editor_state_changed (_copy_available, QDir::cleanPath (_file_name));
+}
+
+void
+file_editor_tab::file_name_query (const QWidget* ID)
+{
+  // A zero (null pointer) means that all file editor tabs
+  // should respond, otherwise just the desired file editor tab.
+  if (ID != this && ID != 0)
+    return;
+
+  // Unnamed files shouldn't be transmitted.
+  if (!_file_name.isEmpty ())
+    emit add_filename_to_list (_file_name);
+}
+
+void
+file_editor_tab::handle_file_reload_answer (int decision)
+{
+  if (decision == QMessageBox::Yes)
+    {
+      load_file (_file_name);
+    }
+
+  // Start watching file once again.
+  _file_system_watcher.addPath (_file_name);
+}
+
+void
+file_editor_tab::handle_file_resave_answer (int decision)
+{
+  if (decision == QMessageBox::Save)
+    {
+      save_file (_file_name);
+    }
+  else
+    {
+      if (close ())
+        {
+          emit tab_remove_request ();
+          return;  // Don't touch member variables after removal
+        }
+    }
+
+  // Start watching file once again.
+  _file_system_watcher.addPath (_file_name);
+}
+
+void
+file_editor_tab::set_debugger_position (int line)
+{
+  _edit_area->markerDeleteAll (debugger_position);
+  if (line > 0)
+    {
+      _edit_area->markerAdd (line, debugger_position);
+    }
+}
--- a/libgui/src/m-editor/file-editor-tab.h	Tue Dec 25 19:41:12 2012 +0000
+++ b/libgui/src/m-editor/file-editor-tab.h	Sun Dec 23 14:33:48 2012 -0600
@@ -28,61 +28,88 @@
 #include <QCloseEvent>
 #include <QFileSystemWatcher>
 
+#include "find-dialog.h"
+
 class file_editor;
 class file_editor_tab : public QWidget
 {
   Q_OBJECT
   public:
-  file_editor_tab (file_editor *fileEditor);
-  bool copy_available ();
+  file_editor_tab (QString directory = "");
+  ~file_editor_tab ();
 
 public slots:
   void update_window_title(bool modified);
   void handle_copy_available(bool enableCopy);
   void handle_margin_clicked (int line, int margin, Qt::KeyboardModifiers state);
-  void comment_selected_text ();
-  void uncomment_selected_text ();
-  void find ();
-  void remove_bookmark ();
-  void toggle_bookmark ();
-  void next_bookmark ();
-  void previous_bookmark ();
-  void remove_all_breakpoints ();
-  void toggle_breakpoint ();
-  void next_breakpoint ();
-  void previous_breakpoint ();
-  void cut ();
-  void copy ();
-  void paste ();
-  void undo ();
-  void redo ();
+
+  /** Tells the editor tab to react on changed settings. */
+  void notice_settings ();
+  /** Will initiate close if associated with the identifier tag. */
+  void conditional_close (const QWidget* ID);
+  /** Change to a different editor tab by identifier tag. */
+  void change_editor_state (const QWidget* ID);
+  /** Simply transmit file name. */
+  void file_name_query (const QWidget* ID);
+
+  void undo (const QWidget* ID);
+  void redo (const QWidget* ID);
+  void copy (const QWidget* ID);
+  void cut (const QWidget* ID);
+  void paste (const QWidget* ID);
+  void save_file (const QWidget* ID);
+  void save_file (const QWidget* ID, const QString& fileName, bool remove_on_success);
+  void save_file_as (const QWidget* ID);
+  void run_file (const QWidget* ID);
+  void toggle_bookmark (const QWidget* ID);
+  void next_bookmark (const QWidget* ID);
+  void previous_bookmark (const QWidget* ID);
+  void remove_bookmark (const QWidget* ID);
+
+  void toggle_breakpoint (const QWidget* ID);
+  void next_breakpoint (const QWidget* ID);
+  void previous_breakpoint (const QWidget* ID);
+  void remove_all_breakpoints (const QWidget* ID);
+
+  void comment_selected_text (const QWidget* ID);
+  void uncomment_selected_text (const QWidget* ID);
+  void find (const QWidget* ID);
+
   void set_debugger_position (int line);
 
   void set_modified (bool modified = true);
 
-  bool open_file (const QString& dir = QString ());
-  bool load_file (const QString& fileName, bool silent = false);
+  QString load_file (const QString& fileName);
   void new_file ();
-  bool save_file ();
-  bool save_file (const QString& saveFileName);
-  bool save_file_as();
-  void run_file ();
 
   void file_has_changed (const QString& fileName);
-  QString get_file_name () const {return _file_name;}
-
-  /** Tells the editor tab to react on changed settings. */
-  void notice_settings ();
 
 signals:
   void file_name_changed (const QString& fileName);
-  void editor_state_changed ();
-  void close_request ();
+  void editor_state_changed (bool copy_available, const QString& fileName);
+  void tab_remove_request ();
+  void add_filename_to_list (const QString& fileName);
+  void editor_check_conflict_save (const QString& saveFileName, bool remove_on_success);
+  void process_octave_code (const QString& command);
 
 protected:
   void closeEvent (QCloseEvent *event);
   void set_file_name (const QString& fileName);
 
+private slots:
+  /** When user closes message box for reload question. */
+  void handle_file_reload_answer (int decision);
+  /** When user closes message box for resave question. */
+  void handle_file_resave_answer (int decision);
+  /** When user closes message box for modified question. */
+  void handle_file_modified_answer (int decision);
+  /** When user closes find_dialog box. */
+  void handle_find_dialog_finished (int decision);
+  /** When user closes QFileDialog box. */
+  void handle_save_file_as_answer (const QString& fileName);
+  void handle_save_file_as_answer_close (const QString& fileName);
+  void handle_save_file_as_answer_cancel ();
+
 private:
 
   struct bp_info
@@ -96,6 +123,10 @@
     int line;
   };
 
+  void save_file (const QString& saveFileName, bool remove_on_success = false);
+  void save_file_as (bool remove_on_success = false);
+  void message_duplicate_file_name (const QString& fileName);
+
   void update_lexer ();
   void request_add_breakpoint (int line);
   void request_remove_breakpoint (int line);
@@ -108,7 +139,6 @@
   void remove_breakpoint_callback (const bp_info& info);
   void remove_all_breakpoints_callback (const bp_info& info);
 
-  file_editor *         _file_editor;
   QsciScintilla *       _edit_area;
 
   QString               _file_name;
@@ -118,6 +148,10 @@
   bool                  _copy_available;
 
   QFileSystemWatcher    _file_system_watcher;
+
+  find_dialog *         _find_dialog;
+  bool                  _find_dialog_is_visible;
+  QRect                 _find_dialog_geometry;
 };
 
 #endif // FILEEDITORTAB_H
--- a/libgui/src/m-editor/file-editor.cc	Tue Dec 25 19:41:12 2012 +0000
+++ b/libgui/src/m-editor/file-editor.cc	Sun Dec 23 14:33:48 2012 -0600
@@ -35,46 +35,33 @@
 #include <QStyle>
 #include <QTextStream>
 
-file_editor::file_editor (QTerminal *t, main_window *m)
-  : file_editor_interface (t, m)
+#include "octave-link.h"
+
+file_editor::file_editor (QWidget *p)
+  : file_editor_interface (p)
 {
+  // Set current editing directory before construct because loaded
+  // files will change ced accordingly.
+  ced = QDir::currentPath ();
+
   construct ();
 
-  _terminal = t;
-  _main_window = m;
   setVisible (false);
 }
 
 file_editor::~file_editor ()
 {
   QSettings *settings = resource_manager::get_settings ();
-  QStringList sessionFileNames;
+  fetFileNames.clear ();
   if (settings->value ("editor/restoreSession",true).toBool ())
     {
-      for (int n=0;n<_tab_widget->count();++n)
-        {
-          file_editor_tab* tab = dynamic_cast<file_editor_tab*> (_tab_widget->widget (n));
-          if (!tab)
-            continue;
-          sessionFileNames.append (tab->get_file_name ());
-        }
+      // Have all file editor tabs signal what their file names are.
+      emit fetab_file_name_query (0);
     }
-  settings->setValue ("editor/savedSessionTabs", sessionFileNames);
+  settings->setValue ("editor/savedSessionTabs", fetFileNames);
   settings->sync ();
 }
 
-QTerminal *
-file_editor::terminal ()
-{
-  return _terminal;
-}
-
-main_window *
-file_editor::get_main_window ()
-{
-  return _main_window;
-}
-
 QMenu *
 file_editor::debug_menu ()
 {
@@ -102,10 +89,14 @@
 void
 file_editor::request_new_file ()
 {
-  file_editor_tab *fileEditorTab = new file_editor_tab (this);
+  // New file isn't a file_editor_tab function since the file
+  // editor tab has yet to be created and there is no object to
+  // pass a signal to.  Hence, functionality is here.
+
+  file_editor_tab *fileEditorTab = new file_editor_tab (ced);
   if (fileEditorTab)
     {
-      add_file_editor_tab (fileEditorTab);
+      add_file_editor_tab (fileEditorTab, UNNAMED_FILE);
       fileEditorTab->new_file ();
     }
 }
@@ -113,208 +104,263 @@
 void
 file_editor::request_open_file ()
 {
-  file_editor_tab *current_tab = active_editor_tab ();
-  int curr_tab_index = _tab_widget->currentIndex ();
-  file_editor_tab *fileEditorTab = new file_editor_tab (this);
-  if (fileEditorTab)
-    {
-      add_file_editor_tab (fileEditorTab);
-      QString dir = QDir::currentPath ();
-      // get the filename of the last active tab to open a new file from there
-      if (current_tab)
-        dir = QDir::cleanPath (current_tab->get_file_name ());
-      if (!fileEditorTab->open_file (dir))
-        {
-          // If no file was loaded, remove the tab again.
-          _tab_widget->removeTab (_tab_widget->indexOf (fileEditorTab));
-          // restore focus to previous tab
-          if (curr_tab_index>=0)
-            _tab_widget->setCurrentIndex (curr_tab_index);
-        }
-    }
+  // Open file isn't a file_editor_tab function since the file
+  // editor tab has yet to be created and there is no object to
+  // pass a signal to.  Hence, functionality is here.
+
+  // Create a NonModal message.
+  QFileDialog* fileDialog = new QFileDialog (this);
+  fileDialog->setNameFilter (SAVE_FILE_FILTER);
+  fileDialog->setAcceptMode (QFileDialog::AcceptOpen);
+  fileDialog->setViewMode (QFileDialog::Detail);
+  fileDialog->setDirectory (ced);
+  connect (fileDialog, SIGNAL (fileSelected (const QString&)),
+           this, SLOT (request_open_file (const QString&)));
+  fileDialog->setWindowModality (Qt::NonModal);
+  fileDialog->setAttribute (Qt::WA_DeleteOnClose);
+  fileDialog->show ();
 }
 
 void
-file_editor::request_open_file (const QString& fileName, bool silent)
+file_editor::request_open_file (const QString& openFileName)
 {
-  if (!isVisible ())
+  if (openFileName.isEmpty ())
     {
-      show ();
+      // ??  Not sure this will happen.  This routine isn't even called
+      // if the user hasn't selected a file.
     }
+  else
+    {
+      // Have all file editor tabs signal what their file names are.
+      fetFileNames.clear ();
+      emit fetab_file_name_query (0);
 
-  file_editor_tab *fileEditorTab = new file_editor_tab (this);
-  int curr_tab_index = _tab_widget->currentIndex ();
-  if (fileEditorTab)
-    {
-      add_file_editor_tab (fileEditorTab);
-      if (!fileEditorTab->load_file (fileName, silent))
+      // Check whether this file is already open in the editor.
+      if (fetFileNames.contains (openFileName, Qt::CaseSensitive))
         {
-          // If no file was loaded, remove the tab again.
-          _tab_widget->removeTab (_tab_widget->indexOf (fileEditorTab));
-          // restore focus to previous tab
-          _tab_widget->setCurrentIndex (curr_tab_index);
+          // Create a NonModal message so nothing is blocked and
+          // bring the existing file forward.
+          QMessageBox* msgBox = new QMessageBox (
+                  QMessageBox::Critical, tr ("Octave Editor"),
+                  tr ("File %1 is already open in the editor.").
+                  arg (openFileName), QMessageBox::Ok, 0);
+          msgBox->setWindowModality (Qt::NonModal);
+          msgBox->setAttribute (Qt::WA_DeleteOnClose);
+          msgBox->show ();
+          for(int i = 0; i < _tab_widget->count (); i++)
+            {
+              if (_tab_widget->tabText (i) == openFileName)
+                {
+                  _tab_widget->setCurrentIndex (i);
+                  break;
+                }
+            }
+          return;
+        }
+
+      file_editor_tab *fileEditorTab = new file_editor_tab ();
+      if (fileEditorTab)
+        {
+          QString result = fileEditorTab->load_file(openFileName);
+          if (result == "")
+            {
+              // Supply empty title then have the file_editor_tab update
+              // with full or short name.
+              add_file_editor_tab (fileEditorTab, "");
+              fileEditorTab->update_window_title (false);
+            }
+          else
+            {
+              delete fileEditorTab;
+              // Create a NonModal message about error.
+              QMessageBox* msgBox = new QMessageBox (
+                      QMessageBox::Critical, tr ("Octave Editor"),
+                      tr ("Could not open file %1 for read:\n%2.").
+                      arg (openFileName).arg (result),
+                      QMessageBox::Ok, 0);
+              msgBox->setWindowModality (Qt::NonModal);
+              msgBox->setAttribute (Qt::WA_DeleteOnClose);
+              msgBox->show ();
+            }
         }
     }
 }
 
 void
+file_editor::check_conflict_save (const QString& saveFileName, bool remove_on_success)
+{
+  // Have all file editor tabs signal what their file names are.
+  fetFileNames.clear ();
+  emit fetab_file_name_query (0);
+
+  // If one of those names matches the desired name, that's a conflict.
+  if (fetFileNames.contains (saveFileName, Qt::CaseSensitive))
+    {
+      // Note: to overwrite the contents of some other file editor tab
+      // with the same name requires identifying which file editor tab
+      // that is (not too difficult) then close that tab.  Of course,
+      // that could trigger another dialog box if the file editor tab
+      // with the same name has modifications in it.  This could become
+      // somewhat confusing to the user.  For now, opt to do nothing.
+
+      // Create a NonModal message about error.
+      QMessageBox* msgBox = new QMessageBox (
+              QMessageBox::Critical, tr ("Octave Editor"),
+              tr ("File not saved!  You've selected a file name\n\n     %1\n\nwhich is the same as an already open file in the editor.  (Could allow overwriting, with message, if that is what folks want.)").
+              arg (saveFileName),
+              QMessageBox::Ok, 0);
+      msgBox->setWindowModality (Qt::NonModal);
+      msgBox->setAttribute (Qt::WA_DeleteOnClose);
+      msgBox->show ();
+
+      return;
+    }
+
+  QObject* saveFileObject = sender ();
+  QWidget* saveFileWidget = 0;
+  for(int i = 0; i < _tab_widget->count (); i++)
+    {
+      if (_tab_widget->widget (i) == saveFileObject)
+        {
+          saveFileWidget = _tab_widget->widget (i);
+          break;
+        }
+    }
+  if (!saveFileWidget)
+    {
+      // Create a NonModal message about error.
+      QMessageBox* msgBox = new QMessageBox (
+              QMessageBox::Critical, tr ("Octave Editor"),
+              tr ("The associated file editor tab has disappeared.  It was likely closed by some means."),
+              QMessageBox::Ok, 0);
+      msgBox->setWindowModality (Qt::NonModal);
+      msgBox->setAttribute (Qt::WA_DeleteOnClose);
+      msgBox->show ();
+      return;
+    }
+
+  // Can save without conflict, have the file editor tab do so.
+  emit fetab_save_file (saveFileWidget, saveFileName, remove_on_success);
+}
+
+void
 file_editor::request_undo ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->undo ();
+  emit fetab_undo (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_redo ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->redo ();
+  emit fetab_redo (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_copy ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->copy ();
+  emit fetab_copy (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_cut ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->cut ();
+  emit fetab_cut (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_paste ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->paste ();
+  emit fetab_paste (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_save_file ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->save_file ();
+  emit fetab_save_file (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_save_file_as ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->save_file_as ();
+   emit fetab_save_file_as (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_run_file ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->run_file ();
+  emit fetab_run_file (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_toggle_bookmark ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->toggle_bookmark ();
+  emit fetab_toggle_bookmark (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_next_bookmark ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->next_bookmark ();
+  emit fetab_next_bookmark (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_previous_bookmark ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->previous_bookmark ();
+  emit fetab_previous_bookmark (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_remove_bookmark ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->remove_bookmark ();
+  emit fetab_remove_bookmark (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_toggle_breakpoint ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->toggle_breakpoint ();
+  emit fetab_toggle_breakpoint (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_next_breakpoint ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->next_breakpoint ();
+  emit fetab_next_breakpoint (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_previous_breakpoint ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->previous_breakpoint ();
+  emit fetab_previous_breakpoint (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_remove_breakpoint ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->remove_all_breakpoints ();
+  emit fetab_remove_all_breakpoints (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_comment_selected_text ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->comment_selected_text ();
+  emit fetab_comment_selected_text (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_uncomment_selected_text ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->uncomment_selected_text ();
+  emit fetab_uncomment_selected_text (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::request_find ()
 {
-  file_editor_tab *_active_file_editor_tab = active_editor_tab ();
-  if (_active_file_editor_tab)
-    _active_file_editor_tab->find ();
+  emit fetab_find (_tab_widget->currentWidget ());
 }
 
 void
 file_editor::handle_file_name_changed (const QString& fileName)
 {
-  QObject *senderObject = sender ();
-  file_editor_tab *fileEditorTab
-    = dynamic_cast<file_editor_tab*> (senderObject);
+  QObject *fileEditorTab = sender();
   if (fileEditorTab)
     {
       for(int i = 0; i < _tab_widget->count (); i++)
@@ -330,26 +376,72 @@
 void
 file_editor::handle_tab_close_request (int index)
 {
-  file_editor_tab *fileEditorTab
-    = dynamic_cast <file_editor_tab*> (_tab_widget->widget (index));
+  // Signal to the tabs a request to close whomever matches the identifying
+  // tag (i.e., unique widget pointer).  The reason for this indirection is
+  // that it will enable a file editor widget to toss up a non-static
+  // dialog box and later signal that it wants to be removed.
+  QWidget *tabID = _tab_widget->widget (index);
+  emit fetab_close_request (tabID);
+}
+
+void
+file_editor::handle_tab_remove_request ()
+{
+  QObject *fileEditorTab = sender();
   if (fileEditorTab)
-    if (fileEditorTab->close ())
-      {
-        _tab_widget->removeTab (index);
-        delete fileEditorTab;
-      }
+    {
+      for(int i = 0; i < _tab_widget->count (); i++)
+        {
+          if (_tab_widget->widget (i) == fileEditorTab)
+            {
+              _tab_widget->removeTab (i);
+              delete fileEditorTab;
+            }
+        }
+    }
+}
+
+void
+file_editor::handle_add_filename_to_list (const QString& fileName)
+{
+  fetFileNames.append (fileName);
 }
 
 void
-file_editor::handle_tab_close_request ()
+file_editor::active_tab_changed (int index)
+{
+  emit fetab_change_request (_tab_widget->widget (index));
+}
+
+void
+file_editor::handle_editor_state_changed (bool copy_available, const QString& file_name)
 {
-  file_editor_tab *fileEditorTab = dynamic_cast <file_editor_tab*> (sender ());
-  if (fileEditorTab)
-    if (fileEditorTab->close ())
-      {
-        _tab_widget->removeTab (_tab_widget->indexOf (fileEditorTab));
-        delete fileEditorTab;
-      }
+  // In case there is some scenario where traffic could be coming from
+  // all the file editor tabs, just process info from the current active tab.
+  if (sender() == _tab_widget->currentWidget ())
+    {
+      _copy_action->setEnabled (copy_available);
+      _cut_action->setEnabled (copy_available);
+      if (!file_name.isEmpty ())
+        {
+          ced = QDir::cleanPath (file_name);
+          int lastslash = ced.lastIndexOf ('/');
+          // Test against > 0 because if somehow the directory is "/" the
+          // slash should be retained.  Otherwise, last slash is removed.
+          if (lastslash > 0 && lastslash != ced.count ())
+            {
+              ced = ced.left (lastslash);
+            }
+        }
+      setFocusProxy (_tab_widget->currentWidget ());
+    }
+}
+
+void
+file_editor::notice_settings ()
+{
+  // Relay signal to file editor tabs.
+  emit fetab_settings_changed ();
 }
 
 // slot for signal that is emitted when floating property changes
@@ -364,37 +456,6 @@
 }
 
 void
-file_editor::active_tab_changed (int)
-{
-  handle_editor_state_changed ();
-}
-
-void
-file_editor::handle_editor_state_changed ()
-{
-  file_editor_tab *f = active_editor_tab ();
-  if (f)
-    {
-      bool copy_available = f->copy_available ();
-      _copy_action->setEnabled (copy_available);
-      _cut_action->setEnabled (copy_available);
-      setFocusProxy (f);
-    }
-}
-
-void
-file_editor::notice_settings ()
-{
-  for(int i = 0; i < _tab_widget->count (); i++)
-    {
-      file_editor_tab *fileEditorTab
-        = dynamic_cast <file_editor_tab*> (_tab_widget->widget (i));
-      if (fileEditorTab)
-        fileEditorTab->notice_settings ();
-    }
-}
-
-void
 file_editor::construct ()
 {
   QWidget *editor_widget = new QWidget (this);
@@ -607,25 +668,79 @@
       QStringList sessionFileNames = settings->value("editor/savedSessionTabs", QStringList()).toStringList ();
 
       for (int n=0; n < sessionFileNames.count (); ++n)
-        request_open_file (sessionFileNames.at (n), true);
+        request_open_file (sessionFileNames.at (n));
     }
 }
 
 void
-file_editor::add_file_editor_tab (file_editor_tab *f)
+file_editor::add_file_editor_tab (file_editor_tab *f, const QString &fn)
 {
-  _tab_widget->addTab (f, "");
-  connect (f, SIGNAL (file_name_changed(QString)),
-           this, SLOT(handle_file_name_changed(QString)));
-  connect (f, SIGNAL (editor_state_changed ()),
-           this, SLOT (handle_editor_state_changed ()));
-  connect (f, SIGNAL (close_request ()),
-           this, SLOT (handle_tab_close_request ()));
+  _tab_widget->addTab (f, fn);
+
+  // Signals from the file editor_tab
+  connect (f, SIGNAL (file_name_changed (const QString&)),
+           this, SLOT (handle_file_name_changed (const QString&)));
+  connect (f, SIGNAL (editor_state_changed (bool, const QString&)),
+           this, SLOT (handle_editor_state_changed (bool, const QString&)));
+  connect (f, SIGNAL (tab_remove_request ()),
+           this, SLOT (handle_tab_remove_request ()));
+  connect (f, SIGNAL (add_filename_to_list (const QString&)),
+           this, SLOT (handle_add_filename_to_list (const QString&)));
+  connect (f, SIGNAL (editor_check_conflict_save (const QString&, bool)),
+           this, SLOT (check_conflict_save (const QString&, bool)));
+  connect (f, SIGNAL (process_octave_code (const QString&)),
+           parent (), SLOT (handle_command_double_clicked (const QString&)));
+  
+  // Signals from the file_editor non-trivial operations
+  connect (this, SIGNAL (fetab_settings_changed ()),
+           f, SLOT (notice_settings ()));
+  connect (this, SIGNAL (fetab_close_request (const QWidget*)),
+           f, SLOT (conditional_close (const QWidget*)));
+  connect (this, SIGNAL (fetab_change_request (const QWidget*)),
+           f, SLOT (change_editor_state (const QWidget*)));
+  connect (this, SIGNAL (fetab_file_name_query (const QWidget*)),
+           f, SLOT (file_name_query (const QWidget*)));
+  connect (this, SIGNAL (fetab_save_file (const QWidget*, const QString&, bool)),
+           f, SLOT (save_file (const QWidget*, const QString&, bool)));
+  // Signals from the file_editor trivial operations
+  connect (this, SIGNAL (fetab_undo (const QWidget*)),
+           f, SLOT (undo (const QWidget*)));
+  connect (this, SIGNAL (fetab_redo (const QWidget*)),
+           f, SLOT (redo (const QWidget*)));
+  connect (this, SIGNAL (fetab_copy (const QWidget*)),
+           f, SLOT (copy (const QWidget*)));
+  connect (this, SIGNAL (fetab_cut (const QWidget*)),
+           f, SLOT (cut (const QWidget*)));
+  connect (this, SIGNAL (fetab_paste (const QWidget*)),
+           f, SLOT (paste (const QWidget*)));
+  connect (this, SIGNAL (fetab_save_file (const QWidget*)),
+           f, SLOT (save_file (const QWidget*)));
+  connect (this, SIGNAL (fetab_save_file_as (const QWidget*)),
+           f, SLOT (save_file_as (const QWidget*)));
+  connect (this, SIGNAL (fetab_run_file (const QWidget*)),
+           f, SLOT (run_file (const QWidget*)));
+  connect (this, SIGNAL (fetab_toggle_bookmark (const QWidget*)),
+           f, SLOT (toggle_bookmark (const QWidget*)));
+  connect (this, SIGNAL (fetab_next_bookmark (const QWidget*)),
+           f, SLOT (next_bookmark (const QWidget*)));
+  connect (this, SIGNAL (fetab_previous_bookmark (const QWidget*)),
+           f, SLOT (previous_bookmark (const QWidget*)));
+  connect (this, SIGNAL (fetab_remove_bookmark (const QWidget*)),
+           f, SLOT (remove_bookmark (const QWidget*)));
+  connect (this, SIGNAL (fetab_toggle_breakpoint (const QWidget*)),
+           f, SLOT (toggle_breakpoint (const QWidget*)));
+  connect (this, SIGNAL (fetab_next_breakpoint (const QWidget*)),
+           f, SLOT (next_breakpoint (const QWidget*)));
+  connect (this, SIGNAL (fetab_previous_breakpoint (const QWidget*)),
+           f, SLOT (previous_breakpoint (const QWidget*)));
+  connect (this, SIGNAL (fetab_remove_all_breakpoints (const QWidget*)),
+           f, SLOT (remove_all_breakpoints (const QWidget*)));
+  connect (this, SIGNAL (fetab_comment_selected_text (const QWidget*)),
+           f, SLOT (comment_selected_text (const QWidget*)));
+  connect (this, SIGNAL (fetab_uncomment_selected_text (const QWidget*)),
+           f, SLOT (uncomment_selected_text (const QWidget*)));
+  connect (this, SIGNAL (fetab_find (const QWidget*)),
+           f, SLOT (find (const QWidget*)));
+
   _tab_widget->setCurrentWidget (f);
 }
-
-file_editor_tab *
-file_editor::active_editor_tab ()
-{
-  return dynamic_cast<file_editor_tab*> (_tab_widget->currentWidget ());
-}
--- a/libgui/src/m-editor/file-editor.h	Tue Dec 25 19:41:12 2012 +0000
+++ b/libgui/src/m-editor/file-editor.h	Sun Dec 23 14:33:48 2012 -0600
@@ -30,7 +30,6 @@
 #include <QCloseEvent>
 #include <QTabWidget>
 
-#include "main-window.h"
 #include "file-editor-interface.h"
 #include "file-editor-tab.h"
 
@@ -48,23 +47,48 @@
   Q_OBJECT
 
   public:
-  file_editor (QTerminal *terminal, main_window *m);
+  file_editor (QWidget *p);
   ~file_editor ();
   void loadFile (const QString& fileName);
 
-  QTerminal *       terminal ();
-  main_window *     get_main_window ();
-
   QMenu *           debug_menu ();
   QToolBar *        toolbar ();
 
   void handle_entered_debug_mode ();
   void handle_quit_debug_mode ();
 
+signals:
+  void fetab_settings_changed ();
+  void fetab_close_request (const QWidget* ID);
+  void fetab_change_request (const QWidget* ID);
+  void fetab_file_name_query (const QWidget* ID);
+  // Save is a ping-pong type of communication
+  void fetab_save_file (const QWidget* ID, const QString& fileName, bool remove_on_success);
+  // No fetab_open, functionality in editor
+  // No fetab_new, functionality in editor
+  void fetab_undo (const QWidget* ID);
+  void fetab_redo (const QWidget* ID);
+  void fetab_copy (const QWidget* ID);
+  void fetab_cut (const QWidget* ID);
+  void fetab_paste (const QWidget* ID);
+  void fetab_save_file (const QWidget* ID);
+  void fetab_save_file_as (const QWidget* ID);
+  void fetab_run_file (const QWidget* ID);
+  void fetab_toggle_bookmark (const QWidget* ID);
+  void fetab_next_bookmark (const QWidget* ID);
+  void fetab_previous_bookmark (const QWidget* ID);
+  void fetab_remove_bookmark (const QWidget* ID);
+  void fetab_toggle_breakpoint (const QWidget* ID);
+  void fetab_next_breakpoint (const QWidget* ID);
+  void fetab_previous_breakpoint (const QWidget* ID);
+  void fetab_remove_all_breakpoints (const QWidget* ID);
+  void fetab_comment_selected_text (const QWidget* ID);
+  void fetab_uncomment_selected_text (const QWidget* ID);
+  void fetab_find (const QWidget* ID);
+
 public slots:
   void request_new_file ();
   void request_open_file ();
-  void request_open_file (const QString& fileName, bool silent = false);
 
   void request_undo ();
   void request_redo ();
@@ -90,19 +114,28 @@
 
   void handle_file_name_changed (const QString& fileName);
   void handle_tab_close_request (int index);
-  void handle_tab_close_request ();
+  void handle_tab_remove_request ();
+  void handle_add_filename_to_list (const QString& fileName);
   void active_tab_changed (int index);
-  void handle_editor_state_changed ();
+  void handle_editor_state_changed (bool enableCopy, const QString& fileName);
+  void check_conflict_save (const QString& fileName, bool remove_on_success);
+
   /** Slot when floating property changes */
   void top_level_changed (bool floating);
 
   /** Tells the editor to react on changed settings. */
   void notice_settings ();
 
+private slots:
+  void request_open_file (const QString& fileName);
+
 private:
   void construct ();
-  void add_file_editor_tab(file_editor_tab *f);
-  file_editor_tab *active_editor_tab();
+  void add_file_editor_tab(file_editor_tab *f, const QString &fn);
+  void save_file_as (QWidget *fetabID = 0);
+
+  QStringList fetFileNames;
+  QString ced;
 
   QMenuBar *        _menu_bar;
   QToolBar *        _tool_bar;
--- a/libgui/src/main-window.cc	Tue Dec 25 19:41:12 2012 +0000
+++ b/libgui/src/main-window.cc	Sun Dec 23 14:33:48 2012 -0600
@@ -576,7 +576,7 @@
   dummyWidget->hide ();
   setCentralWidget (dummyWidget);
 
-  _file_editor = new file_editor (_terminal, this);
+  _file_editor = new file_editor (this);
 
   QMenu *file_menu = menuBar ()->addMenu (tr ("&File"));