# HG changeset patch # User Daniel J Sebald # Date 1423934830 21600 # Node ID 21015ca26566a2fa94c4b76d09dce81dc46f24a1 # Parent 1a6fa5a523e4d2a3bf65f04834e9efc63f86249e Restructure shutdown flow and behavior for improved robustness * file-editor-interface.h (file_editor_interface::check_closing): Remove closing_state argument from input. * file-editor-tab.cc (file_editor_tab::_cancelled): New static variable for managing chain of file closes. (file_editor_tab::file_editor_tab): Discard _app_closing and _modal_dialog initializations. (file_editor_tab::closeEvent): Upon accepting the close event, als request tab removal. (file_editor_tab::check_modified_file): New simple routine checking for modified file if there hasn't been cancellation yet. (file_editor_tab::run_file): Remove use of _modal_dialog. (file_editor_tab::show_dialog): Add modal input setting. Remove use of _app_closing and _modal_dialog. (file_editor_tab::check_file_modified): Remove situational message for just one. If modified, call show_dialog with modal true, return QMessageBox::Cancel if anything cancelled, otherwise the user decision. (file_editor_tab::handle_file_modified_answer): Do not remove file editor tab in any case. If user cancelled, set _cancelled true. (file_editor_tab::save_file): Add "false" (non-modal) to show_dialog() call. (file_editor_tab::save_file_as): Add "false" (non-modal) to show_dialog() call. (file_editor_tab::conditional_close): Remove input argument and use of variable _app_closing. * file-editor-tab.h (file_editor_tab::conditional_close): Remove input argument. (file_editor_tab::reset_cancel): New member function declaration for managing cancellation of tab chain saves. (file_editor_tab::was_cancel): New member function for indicating any cancellation when saving modified files. (file_editor_tab::check_modified_file): New slot declaration for checking and saving file modifications. (file_editor_tab::show_dialog): Add modal option input argument. (file_editor_tab::_app_closing, file_editor_tab::_modal_dialog): Remove. (file_editor_tab::_cancelled): Add. * file-editor.cc (file_editor::file_editor): Remove _check_closing_done initialization. (file_editor::~file_editor): Remove use of _check_closing_done and check_closing(). (file_editor::check_closing): Clear cancellation history and check all files for modifications, without closing. Close all tabs and delete associated widgets if no cancellation. Remove use of _check_closing_done. (file_editor::request_close_file): Remove argument from conditional_close() function call. (file_editor::request_close_all_files): Ditto. (file_editor::request_close_other_files): Ditto. (file_editor::handle_tab_close_request): Ditto. (file_editor::handle_tab_remove_request): Add comment about deleting sender. (file_editor::add_file_editor_tab): Connect fetab_check_modified_file signal to check_modified_file slot. * file-editor.h (file_editor::fetab_check_modified_file): New signal. (file_editor::check_closing): Remove input argument. (file_editor::_check_closing_done): Remove. * main-window.cc (main_window::confirm_shutdown_octave): Rename of member function main_window::confirm_exit_octave(). Change return type to void. Set octave/qt link confirmation result then awake worker process. (main_window::exit_app): Rename of member function main_window::exit(). (main_window::closeEvent): Rather than post callback event, queue "exit" in the command buffer. (main_window::construct_octave_qt_link): Connect confirm_shutdown_signal to confirm_shutdown_octave slot. Connect exit_app_signal to exit_app slot. (main_window::exit_callback): Remove. (main_window::confirm_exit_octave): Renamed as confirm_shutdown_octave(). * main-window.h (main_window::confirm_shutdown_octave): Rename of slot confirm_exit_octave(). (main_window::exit): Renamed exit_app(). (main_window::exit_callback): Removed declaration. (main_window::confirm_exit_octave): Renamed confirm_shutdown_octave(). * octave-qt-link.cc (octave_qt_link::do_confirm_shutdown): New virtual function definition for initiating GUI shutdown and confirm exit. Worker process goes into sleep mode after issuing cross-thread signal. Return confirmation result. (octave_qt_link::do_exit): Change exit_signal to exit_app_signal. octave-qt-link.h (octave_qt_link::do_confirm_shutdown): New virtual function declaration for qt GUI. (octave_qt_link::mutex): Added. A QMutex for communicating with Qt GUI. (octave_qt_link::waitcondition): Added. For process wait. (octave_qt_link::shutdown_confirmation): Added. Store confirmation result. (octave_qt_link::_shutdown_confirm_result): Added. Confirmation result. (octave_qt_link::exit_signal): Signal renamed exit_app_signal. (octave_qt_link::confirm_shutdown_signal): Added. (octave_qt_link::exit_app_signal): Renamed of exit_signal. octave-link.h (octave_link::confirm_shutdown): Added. Access virtual function do_confirm_shutdown. (octave_link::do_confirm_shutdown): Added. Virtual function for GUI link. toplev.cc (clean_up_and_exit): Change 'retval' to 'status', as header file uses argument name 'status'. (quit): First initiate GUI shutdown via octave_link::confirm_shutdown() and if not confirmed, immediately return thereby avoiding exit sequence. diff -r 1a6fa5a523e4 -r 21015ca26566 libgui/src/m-editor/file-editor-interface.h --- a/libgui/src/m-editor/file-editor-interface.h Sat Feb 14 09:32:57 2015 -0800 +++ b/libgui/src/m-editor/file-editor-interface.h Sat Feb 14 11:27:10 2015 -0600 @@ -60,7 +60,7 @@ virtual void handle_edit_file_request (const QString& file) = 0; - virtual bool check_closing (int closing_state) = 0; + virtual bool check_closing (void) = 0; virtual void empty_script (bool, bool) = 0; diff -r 1a6fa5a523e4 -r 21015ca26566 libgui/src/m-editor/file-editor-tab.cc --- a/libgui/src/m-editor/file-editor-tab.cc Sat Feb 14 09:32:57 2015 -0800 +++ b/libgui/src/m-editor/file-editor-tab.cc Sat Feb 14 11:27:10 2015 -0600 @@ -63,15 +63,15 @@ #include "defaults.h" #include +bool file_editor_tab::_cancelled = false; + // Make parent null for the file editor tab so that warning // WindowModal messages don't affect grandparents. file_editor_tab::file_editor_tab (const QString& directory_arg) { QString directory = directory_arg; _lexer_apis = 0; - _app_closing = 0; // app is not closing _is_octave_file = true; - _modal_dialog = false; // Make sure there is a slash at the end of the directory name // for identification when saved later. @@ -193,7 +193,10 @@ if (check_file_modified () == QMessageBox::Cancel) e->ignore (); else - e->accept (); + { + e->accept (); + emit tab_remove_request (); + } } void @@ -628,6 +631,16 @@ } void +file_editor_tab::check_modified_file (void) +{ + if (_cancelled) + return; + + if (check_file_modified () == QMessageBox::Cancel) + _cancelled = true; +} + +void file_editor_tab::save_file (const QWidget *ID) { if (ID != this) @@ -635,8 +648,8 @@ save_file (_file_name); } + void - file_editor_tab::save_file (const QWidget *ID, const QString& fileName, bool remove_on_success) { @@ -678,11 +691,7 @@ return; if (_edit_area->isModified () | ! valid_file_name ()) - { - _modal_dialog = true; // force modal dialog if the file is a new one - save_file (_file_name); // save file dialog - _modal_dialog = false; // back to non-modal dialogs - } + save_file (_file_name); // save file dialog QFileInfo info (_file_name); emit run_file_signal (info); @@ -1208,13 +1217,12 @@ _is_octave_file); } -// show_dialog: shows a modal or non modal dialog depeding on the closing -// of the app and the flag _modal_dialog +// show_dialog: shows a modal or non modal dialog depending on input arg void -file_editor_tab::show_dialog (QDialog *dlg) +file_editor_tab::show_dialog (QDialog *dlg, bool modal) { dlg->setAttribute (Qt::WA_DeleteOnClose); - if (_app_closing | _modal_dialog) + if (modal) dlg->exec (); else { @@ -1231,32 +1239,19 @@ { activateWindow (); raise (); + setFocus (); // 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::StandardButtons buttons = QMessageBox::Save | - QMessageBox::Discard; - QString available_actions; - - switch (_app_closing) - { - case -1: // octave is exiting and so does the gui - available_actions = - tr ("Do you want to save or discard the changes?"); - break; + QMessageBox::Discard | + QMessageBox::Cancel; - case 1: // gui is exiting - available_actions = - tr ("Do you want to cancel exiting octave, save or discard the changes?"); - buttons = buttons | QMessageBox::Cancel; - break; - - case 0: // tab is closing - available_actions = - tr ("Do you want to cancel closing, save or discard the changes?"); - buttons = buttons | QMessageBox::Cancel; - break; - } + // For now, just a warning message about closing a tab that has been + // modified seems sufficient. Exit-condition-specific messages could + // be achieved by making 'available_actions' a function input string. + QString available_actions = + tr ("Do you want to cancel closing, save or discard the changes?"); QString file; if (valid_file_name ()) @@ -1266,9 +1261,9 @@ QMessageBox* msgBox = new QMessageBox (QMessageBox::Warning, tr ("Octave Editor"), - tr ("The file\n" - "%1\n" - "is about to be closed but has been modified.\n" + tr ("The file\n\n" + " %1\n\n" + "is about to be closed but has been modified. " "%2"). arg (file). arg (available_actions), buttons, qobject_cast (parent ())); @@ -1278,14 +1273,17 @@ connect (msgBox, SIGNAL (finished (int)), this, SLOT (handle_file_modified_answer (int))); - show_dialog (msgBox); + show_dialog (msgBox, true); - return QMessageBox::Cancel; + if (_cancelled) + return QMessageBox::Cancel; + else + return decision; } else { - // Nothing was modified, just remove from editor. - emit tab_remove_request (); + // Nothing was modified. Leave tab present in case user + // decides to cancel some point further along. } return decision; @@ -1296,18 +1294,18 @@ { if (decision == QMessageBox::Save) { - // Save file, then remove from editor. - save_file (_file_name, true); + // Save file, but do not remove from editor. + save_file (_file_name, false); } else if (decision == QMessageBox::Discard) { - // User doesn't want to save, just remove from editor. - emit tab_remove_request (); + // User doesn't want to save, leave tab and remove subsequently. } else { // User canceled, allow editing again. _edit_area->setReadOnly (false); + _cancelled = true; } } @@ -1497,7 +1495,7 @@ tr ("Could not open file %1 for write:\n%2."). arg (file_to_save).arg (file.errorString ()), QMessageBox::Ok, 0); - show_dialog (msgBox); + show_dialog (msgBox, false); return; } @@ -1646,7 +1644,7 @@ this, SLOT (handle_save_file_as_answer (const QString&))); } - show_dialog (fileDialog); + show_dialog (fileDialog, false); } void @@ -1934,9 +1932,8 @@ // When emitting a signal, only the return value from the last slot // goes back to the sender bool -file_editor_tab::conditional_close (int app_closing) +file_editor_tab::conditional_close (void) { - _app_closing = app_closing; return close (); } diff -r 1a6fa5a523e4 -r 21015ca26566 libgui/src/m-editor/file-editor-tab.h --- a/libgui/src/m-editor/file-editor-tab.h Sat Feb 14 09:32:57 2015 -0800 +++ b/libgui/src/m-editor/file-editor-tab.h Sat Feb 14 11:27:10 2015 -0600 @@ -52,8 +52,10 @@ octave_qscintilla *qsci_edit_area () { return _edit_area; } // Will initiate close if associated with the identifier tag. - bool conditional_close (int app_closing = 0); // default 0: close tab only + bool conditional_close (void); + static void reset_cancel (void) {_cancelled = false;} + static bool was_cancelled (void) {return _cancelled;} public slots: @@ -74,6 +76,7 @@ void set_focus (const QWidget *ID); void context_help (const QWidget *ID, bool); void context_edit (const QWidget *ID); + void check_modified_file (void); void save_file (const QWidget *ID); void save_file (const QWidget *ID, const QString& fileName, bool remove_on_success); @@ -199,7 +202,7 @@ void request_add_breakpoint (int line); void request_remove_breakpoint (int line); - void show_dialog (QDialog *dlg); + void show_dialog (QDialog *dlg, bool modal); int check_file_modified (); void do_comment_selected_text (bool comment); QString comment_string (const QString&); @@ -230,9 +233,7 @@ bool _long_title; bool _copy_available; - int _app_closing; // -1: octave exits, 1: exit request in gui, 0: no exit bool _is_octave_file; - bool _modal_dialog; bool _always_reload_changed_files; QFileSystemWatcher _file_system_watcher; @@ -243,6 +244,8 @@ QsciAPIs *_lexer_apis; QString _prep_apis_file; + + static bool _cancelled; }; #endif diff -r 1a6fa5a523e4 -r 21015ca26566 libgui/src/m-editor/file-editor.cc --- a/libgui/src/m-editor/file-editor.cc Sat Feb 14 09:32:57 2015 -0800 +++ b/libgui/src/m-editor/file-editor.cc Sat Feb 14 11:27:10 2015 -0600 @@ -54,8 +54,6 @@ // files will change ced accordingly. ced = QDir::currentPath (); - _check_closing_done = false; // init flag for closing process - construct (); setVisible (false); @@ -65,22 +63,12 @@ file_editor::~file_editor (void) { - // Close open tabs, if existing. In this case app closing must be - // initiated by octave since check_closing was already done if the gui - // initiated the closing. All tabs will be definetly closed and the - // user can not cancel exiting (close state -1) - // We have to prevent that on case of gui-closing this check is done - // a second time resulting in an empty file list (tabs closed) for the - // the next start, that is what _check_closing_done is for - if (! _check_closing_done) - check_closing (-1); - if (_mru_file_menu) delete _mru_file_menu; } bool -file_editor::check_closing (int closing_state) +file_editor::check_closing (void) { // Save open files for restoring in next session; this only is possible QSettings *settings = resource_manager::get_settings (); @@ -102,31 +90,29 @@ settings->setValue ("editor/savedSessionTabs", fetFileNames); settings->sync (); - // Close all tabs. If exit is requested by the gui (octave still running) - // check whether closing a tab is successful or whether user wnats to cancel - // exiting the program. Return false in the latter case. - file_editor_tab *editor_tab; + // Save all tabs with confirmation. + file_editor_tab::reset_cancel (); + emit fetab_check_modified_file (); - for (int index = _tab_widget->count ()-1; index >= 0; index--) + // Close all tabs if there was no cancellation. + if (file_editor_tab::was_cancelled ()) + return false; + + for (int i = 0; i < _tab_widget->count (); i++) { - editor_tab = static_cast (_tab_widget->widget (index)); - if ((! editor_tab->conditional_close (closing_state)) && closing_state == 1) - return false; + delete _tab_widget->widget (i); + _tab_widget->removeTab (i); } - // Here, we really want to exit and all tabs are closed - _check_closing_done = true; // check is already done, prevent a second check - // which would store an empty file list return true; } - void file_editor::focus (void) { octave_dock_widget::focus (); -// set focus to current tab + // set focus to current tab QWidget *fileEditorTab = _tab_widget->currentWidget (); if (fileEditorTab) emit fetab_set_focus (fileEditorTab); @@ -423,7 +409,7 @@ } else { - // File does not exist, should it be crated? + // File does not exist, should it be created? bool create_file = true; QMessageBox *msgBox; QSettings *settings = resource_manager::get_settings (); @@ -952,7 +938,7 @@ { file_editor_tab *editor_tab = static_cast (_tab_widget->currentWidget ()); - editor_tab->conditional_close (0); // 0: app is not closing, only tab + editor_tab->conditional_close (); } void @@ -964,7 +950,7 @@ for (int index = _tab_widget->count ()-1; index >= 0; index--) { editor_tab = static_cast (_tab_widget->widget (index)); - editor_tab->conditional_close (0); // 0: app is not closing, only tab + editor_tab->conditional_close (); } } @@ -981,7 +967,7 @@ { editor_tab = static_cast (_tab_widget->widget (index)); - editor_tab->conditional_close (0); // 0: app is not closing, only tab + editor_tab->conditional_close (); } } } @@ -992,7 +978,7 @@ { file_editor_tab *editor_tab = static_cast (_tab_widget->widget (index)); - editor_tab->conditional_close (0); // 0: app is not closing, only tab + editor_tab->conditional_close (); } void @@ -1006,6 +992,8 @@ if (_tab_widget->widget (i) == fileEditorTab) { _tab_widget->removeTab (i); + // Deleting sender is dodgy, but works because the signal + // is the last item in the sender's routines. delete fileEditorTab; break; } @@ -1664,6 +1652,9 @@ bool)), f, SLOT (save_file (const QWidget*, const QString&, bool))); + connect (this, SIGNAL (fetab_check_modified_file (void)), + f, SLOT (check_modified_file (void))); + // Signals from the file_editor trivial operations connect (this, SIGNAL (fetab_zoom_in (const QWidget*)), f, SLOT (zoom_in (const QWidget*))); diff -r 1a6fa5a523e4 -r 21015ca26566 libgui/src/m-editor/file-editor.h --- a/libgui/src/m-editor/file-editor.h Sat Feb 14 09:32:57 2015 -0800 +++ b/libgui/src/m-editor/file-editor.h Sat Feb 14 11:27:10 2015 -0600 @@ -76,6 +76,7 @@ // No fetab_new, functionality in editor void fetab_context_help (const QWidget* ID, bool); void fetab_context_edit (const QWidget* ID); + void fetab_check_modified_file (void); void fetab_save_file (const QWidget* ID); void fetab_save_file_as (const QWidget* ID); void fetab_print_file (const QWidget* ID); @@ -117,7 +118,7 @@ void focus (void); void enable_menu_shortcuts (bool); - bool check_closing (int closing_state); + bool check_closing (void); void request_new_file (const QString& commands); void request_new_script (const QString& commands); @@ -351,8 +352,6 @@ QMenu *_mru_file_menu; QAction *_mru_file_actions[MaxMRUFiles]; QStringList _mru_files; - - bool _check_closing_done; }; #endif // FILEEDITORMDISUBWINDOW_H diff -r 1a6fa5a523e4 -r 21015ca26566 libgui/src/main-window.cc --- a/libgui/src/main-window.cc Sat Feb 14 09:32:57 2015 -0800 +++ b/libgui/src/main-window.cc Sat Feb 14 11:27:10 2015 -0600 @@ -777,6 +777,33 @@ resource_manager::update_network_settings (); } +void +main_window::confirm_shutdown_octave (void) +{ + bool closenow = true; + + QSettings *settings = resource_manager::get_settings (); + + if (settings->value ("prompt_to_exit", false).toBool ()) + { + int ans = QMessageBox::question (this, tr ("Octave"), + tr ("Are you sure you want to exit Octave?"), + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); + + if (ans != QMessageBox::Ok) + closenow = false; + } + +#ifdef HAVE_QSCINTILLA + if (closenow) + closenow = editor_window->check_closing (); +#endif + + _octave_qt_link->shutdown_confirmation (closenow); + + // Awake the worker thread so that it continues shutting down (or not). + _octave_qt_link->waitcondition.wakeAll (); +} void main_window::prepare_to_exit (void) @@ -785,7 +812,7 @@ } void -main_window::exit (int status) +main_window::exit_app (int status) { qApp->exit (status); } @@ -985,8 +1012,7 @@ main_window::closeEvent (QCloseEvent *e) { e->ignore (); - if (confirm_exit_octave()) - octave_link::post_event (this, &main_window::exit_callback); + queue_command ("exit"); } void @@ -1435,8 +1461,11 @@ { _octave_qt_link = new octave_qt_link (this); - connect (_octave_qt_link, SIGNAL (exit_signal (int)), - this, SLOT (exit (int))); + connect (_octave_qt_link, SIGNAL (confirm_shutdown_signal ()), + this, SLOT (confirm_shutdown_octave ())); + + connect (_octave_qt_link, SIGNAL (exit_app_signal (int)), + this, SLOT (exit_app (int))); connect (_octave_qt_link, SIGNAL (set_workspace_signal @@ -2138,12 +2167,6 @@ } void -main_window::exit_callback (void) -{ - Fquit (); -} - -void main_window::find_files (const QString &start_dir) { @@ -2358,29 +2381,3 @@ _clipboard->clear (QClipboard::Clipboard); } -bool -main_window::confirm_exit_octave () -{ - bool closenow = true; - - QSettings *settings = resource_manager::get_settings (); - - if (settings->value ("prompt_to_exit", false).toBool ()) - { - int ans = QMessageBox::question (this, tr ("Octave"), - tr ("Are you sure you want to exit Octave?"), - QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); - - if (ans != QMessageBox::Ok) - return false; - - } - -#ifdef HAVE_QSCINTILLA - closenow = editor_window->check_closing (1); // 1: exit request from gui -#endif - - return closenow; -} - - diff -r 1a6fa5a523e4 -r 21015ca26566 libgui/src/main-window.h --- a/libgui/src/main-window.h Sat Feb 14 09:32:57 2015 -0800 +++ b/libgui/src/main-window.h Sat Feb 14 11:27:10 2015 -0600 @@ -132,8 +132,9 @@ = QString ()); void show_about_octave (void); void notice_settings (const QSettings *settings); + void confirm_shutdown_octave (void); void prepare_to_exit (void); - void exit (int status); + void exit_app (int status); void reset_windows (void); void change_directory (const QString& dir); @@ -275,8 +276,6 @@ void change_directory_callback (const std::string& directory); - void exit_callback (void); - void queue_command (QString command); void queue_debug (QString command); @@ -285,8 +284,6 @@ void configure_shortcuts (); - bool confirm_exit_octave (); - workspace_model *_workspace_model; QHash _hash_menu_text; diff -r 1a6fa5a523e4 -r 21015ca26566 libgui/src/octave-qt-link.cc --- a/libgui/src/octave-qt-link.cc Sat Feb 14 09:32:57 2015 -0800 +++ b/libgui/src/octave-qt-link.cc Sat Feb 14 11:27:10 2015 -0600 @@ -67,10 +67,24 @@ } bool +octave_qt_link::do_confirm_shutdown (void) +{ + emit confirm_shutdown_signal (); + + // Wait while the GUI shuts down. + waitcondition.wait (&mutex); + + // The GUI has sent a signal and the process has been awakened. + return _shutdown_confirm_result; +} + +bool octave_qt_link::do_exit (int status) { - emit exit_signal (status); + emit exit_app_signal (status); + // Could wait for a while and then timeout, but for now just + // assume the GUI application exit will be without problems. return true; } diff -r 1a6fa5a523e4 -r 21015ca26566 libgui/src/octave-qt-link.h --- a/libgui/src/octave-qt-link.h Sat Feb 14 09:32:57 2015 -0800 +++ b/libgui/src/octave-qt-link.h Sat Feb 14 11:27:10 2015 -0600 @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "octave-link.h" #include "octave-interpreter.h" @@ -59,6 +61,7 @@ void execute_interpreter (void); + bool do_confirm_shutdown (void); bool do_exit (int status); bool do_edit_file (const std::string& file); @@ -130,9 +133,13 @@ void do_show_doc (const std::string& file); + QMutex mutex; + QWaitCondition waitcondition; + void shutdown_confirmation (bool sd) {_shutdown_confirm_result = sd;} + private: - // No copying! + bool _shutdown_confirm_result; octave_qt_link (const octave_qt_link&); @@ -150,8 +157,6 @@ void execute_interpreter_signal (void); - void exit_signal (int status); - void edit_file_signal (const QString& file); void change_directory_signal (const QString& dir); @@ -185,6 +190,9 @@ void show_doc_signal (const QString &file); + void confirm_shutdown_signal (void); + void exit_app_signal (int status); + public slots: void terminal_interrupt (void); diff -r 1a6fa5a523e4 -r 21015ca26566 libinterp/corefcn/octave-link.h --- a/libinterp/corefcn/octave-link.h Sat Feb 14 09:32:57 2015 -0800 +++ b/libinterp/corefcn/octave-link.h Sat Feb 14 11:27:10 2015 -0600 @@ -79,6 +79,16 @@ instance->do_discard_events (); } + static bool confirm_shutdown (void) + { + bool retval = true; + + if (instance_ok ()) + retval = instance->do_confirm_shutdown (); + + return retval; + } + static bool exit (int status) { bool retval = false; @@ -380,6 +390,7 @@ void do_entered_readline_hook (void) { } void do_finished_readline_hook (void) { } + virtual bool do_confirm_shutdown (void) = 0; virtual bool do_exit (int status) = 0; virtual bool do_edit_file (const std::string& file) = 0; diff -r 1a6fa5a523e4 -r 21015ca26566 libinterp/corefcn/toplev.cc --- a/libinterp/corefcn/toplev.cc Sat Feb 14 09:32:57 2015 -0800 +++ b/libinterp/corefcn/toplev.cc Sat Feb 14 11:27:10 2015 -0600 @@ -757,11 +757,11 @@ } void -clean_up_and_exit (int retval, bool safe_to_return) +clean_up_and_exit (int status, bool safe_to_return) { do_octave_atexit (); - if (octave_link::exit (retval)) + if (octave_link::exit (status)) { if (safe_to_return) return; @@ -782,7 +782,7 @@ else { if (octave_exit) - (*octave_exit) (retval); + (*octave_exit) (status); } } @@ -806,6 +806,12 @@ { octave_value_list retval; + // Confirm OK to shutdown. Note: A dynamic function installation similar + // to overriding polymorphism for which the GUI can install its own "quit" + // yet call this base "quit" could be nice. No link would be needed here. + if (! octave_link::confirm_shutdown ()) + return retval; + if (! quit_allowed) error ("quit: not supported in embedded mode"); else