# HG changeset patch # User John W. Eaton # Date 1367277220 14400 # Node ID 8abae9ea4cb50553d8f96f6febb2f79eec2c6a09 # Parent 2ed5bc680c71ec32b01352468b1b15cc0dacabf4# Parent 3ce0c312a40b696622408b4fd668c742841d72fe maint: periodic merge of default to classdef diff -r 2ed5bc680c71 -r 8abae9ea4cb5 NEWS --- a/NEWS Mon Apr 22 16:37:53 2013 -0400 +++ b/NEWS Mon Apr 29 19:13:40 2013 -0400 @@ -178,10 +178,11 @@ ** Other new functions added in 3.8.0: - betaincinv dawson fminsearch polyeig strjoin - cmpermute erfcinv importdata rgbplot tetramesh - cmunique erfi iscolormap shrinkfaces - colorcube findfigs lines splinefit + betaincinv ellipj findfigs polyeig tetramesh + cmpermute ellipke fminsearch rgbplot waterfall + cmunique erfcinv importdata shrinkfaces + colorcube erfi iscolormap splinefit + dawson expint lines strjoin ** Deprecated functions. diff -r 2ed5bc680c71 -r 8abae9ea4cb5 doc/interpreter/arith.txi --- a/doc/interpreter/arith.txi Mon Apr 22 16:37:53 2013 -0400 +++ b/doc/interpreter/arith.txi Mon Apr 29 19:13:40 2013 -0400 @@ -287,6 +287,10 @@ @DOCSTRING(dawson) +@DOCSTRING(ellipj) + +@DOCSTRING(ellipke) + @DOCSTRING(erf) @DOCSTRING(erfc) @@ -299,6 +303,8 @@ @DOCSTRING(erfcinv) +@DOCSTRING(expint) + @DOCSTRING(gamma) @DOCSTRING(gammainc) diff -r 2ed5bc680c71 -r 8abae9ea4cb5 doc/interpreter/plot.txi --- a/doc/interpreter/plot.txi Mon Apr 22 16:37:53 2013 -0400 +++ b/doc/interpreter/plot.txi Mon Apr 29 19:13:40 2013 -0400 @@ -392,6 +392,8 @@ @DOCSTRING(scatter3) +@DOCSTRING(waterfall) + @menu * Aspect Ratio:: * Three-dimensional Function Plotting:: diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/Makefile.am --- a/libgui/Makefile.am Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/Makefile.am Mon Apr 29 19:13:40 2013 -0400 @@ -86,8 +86,16 @@ default-qt-settings: default-qt-settings.in $(do_subst_qt_settings) +define moc-command +( echo '#ifdef HAVE_CONFIG_H'; \ + echo '#include '; \ + echo '#endif'; \ + $(MOC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(MOC_CPPFLAGS) $(liboctgui_la_CPPFLAGS) $< ) > $@-t +mv $@-t $@ +endef + moc-%.cc: %.h - $(MOC) -o$@ $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(MOC_CPPFLAGS) $(liboctgui_la_CPPFLAGS) $< + $(moc-command) ui-%.h: %.ui $(UIC) -o $@ $< diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/default-qt-settings.in --- a/libgui/default-qt-settings.in Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/default-qt-settings.in Mon Apr 29 19:13:40 2013 -0400 @@ -19,6 +19,7 @@ longWindowTitle=false restoreSession=false savedSessionTabs=@Invalid() +mru_file_list=@Invalid() [terminal] fontSize=%DEFAULT_TERMINAL_FONT_SIZE% @@ -27,21 +28,21 @@ cursorType=ibeam [MainWindow] -geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\x18\0\0\x3G\0\0\x2\xe9\0\0\0\x1\0\0\0\x33\0\0\x3\x46\0\0\x2\xe8\0\0\0\0\0\0) -windowState=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x1\0\0\x3\x46\0\0\x2x\xfc\x2\0\0\0\x1\xfc\0\0\0(\0\0\x2x\0\0\x1\xc5\0\xff\xff\xff\xfc\x1\0\0\0\x2\xfc\0\0\0\0\0\0\0\xe8\0\0\0R\0\xff\xff\xff\xfc\x2\0\0\0\x3\xfb\0\0\0\x1e\0\x46\0i\0l\0\x65\0s\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0(\0\0\0\xc9\0\0\0\x8d\0\xff\xff\xff\xfb\0\0\0\x1a\0W\0o\0r\0k\0s\0p\0\x61\0\x63\0\x65\0V\0i\0\x65\0w\x1\0\0\0\xf7\0\0\0\xd7\0\0\0k\0\xff\xff\xff\xfb\0\0\0\"\0H\0i\0s\0t\0o\0r\0y\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\x1\xd4\0\0\0\xcc\0\0\0\x8a\0\xff\xff\xff\xfc\0\0\0\xee\0\0\x2X\0\0\x2X\0\xff\xff\xff\xfa\0\0\0\0\x2\0\0\0\x3\xfb\0\0\0$\0T\0\x65\0r\0m\0i\0n\0\x61\0l\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\x1\xa9\0\xff\xff\xff\xfb\0\0\0\x14\0\x46\0i\0l\0\x65\0\x45\0\x64\0i\0t\0o\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0h\0\xff\xff\xff\xfb\0\0\0.\0\x44\0o\0\x63\0u\0m\0\x65\0n\0t\0\x61\0t\0i\0o\0n\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\xac\0\xff\xff\xff\0\0\0\0\0\0\x2x\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x1\0\0\0\x2\0\0\0\x1\xff\xff\xff\xff\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0) -current_directory_list=@Invalid() +geometry="@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\x14\0\0\0'\0\0\x4;\0\0\x3\x4\0\0\0\x1e\0\0\0\x45\0\0\x4\x31\0\0\x2\xfa\0\0\0\0\0\0)" +windowState="@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x1\0\0\x4\x14\0\0\x2]\xfc\x2\0\0\0\x1\xfc\0\0\0\x42\0\0\x2]\0\0\x1\xa7\0\xff\xff\xff\xfc\x1\0\0\0\x2\xfc\0\0\0\0\0\0\x1y\0\0\0X\0\xff\xff\xff\xfc\x2\0\0\0\x3\xfb\0\0\0\x1e\0\x46\0i\0l\0\x65\0s\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0\x42\0\0\0\xc0\0\0\0\x97\0\xff\xff\xff\xfb\0\0\0\x1a\0W\0o\0r\0k\0s\0p\0\x61\0\x63\0\x65\0V\0i\0\x65\0w\x1\0\0\x1\b\0\0\0\xce\0\0\0q\0\xff\xff\xff\xfb\0\0\0\"\0H\0i\0s\0t\0o\0r\0y\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\x1\xdc\0\0\0\xc3\0\0\0\x93\0\xff\xff\xff\xfc\0\0\x1\x7f\0\0\x2\x95\0\0\x1,\0\xff\xff\xff\xfa\0\0\0\0\x2\0\0\0\x3\xfb\0\0\0$\0T\0\x65\0r\0m\0i\0n\0\x61\0l\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\xe1\0\xff\xff\xff\xfb\0\0\0\x14\0\x46\0i\0l\0\x65\0\x45\0\x64\0i\0t\0o\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0k\0\xff\xff\xff\xfb\0\0\0.\0\x44\0o\0\x63\0u\0m\0\x65\0n\0t\0\x61\0t\0i\0o\0n\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\xba\0\xff\xff\xff\0\0\0\0\0\0\x2]\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x1\0\0\0\x2\0\0\0\x1\0\0\0\x16\0M\0\x61\0i\0n\0T\0o\0o\0l\0\x42\0\x61\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0)" +current_directory_list=/scratch/jwe/build/octave [DockWidgets] -TerminalDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\xee\0\0\0(\0\0\x3\x45\0\0\x2\x83\0\0\0\xee\0\0\0(\0\0\x3\x45\0\0\x2\x83\0\0\0\0\0\0) +TerminalDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\x1\x7f\0\0\0\x42\0\0\x4\x13\0\0\x2\x7f\0\0\x1\x7f\0\0\0\x42\0\0\x4\x13\0\0\x2\x7f\0\0\0\0\0\0) TerminalDockWidgetFloating=false TerminalDockWidgetVisible=true -WorkspaceView=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\xf7\0\0\0\xe7\0\0\x1\xcd\0\0\0\0\0\0\0\xf7\0\0\0\xe7\0\0\x1\xcd\0\0\0\0\0\0) +WorkspaceView=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\x1\b\0\0\x1x\0\0\x1\xd5\0\0\0\0\0\0\x1\b\0\0\x1x\0\0\x1\xd5\0\0\0\0\0\0) WorkspaceViewFloating=false WorkspaceViewVisible=true -HistoryDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\x1\xd4\0\0\0\xe7\0\0\x2\x9f\0\0\0\0\0\0\x1\xd4\0\0\0\xe7\0\0\x2\x9f\0\0\0\0\0\0) +HistoryDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\x1\xdc\0\0\x1x\0\0\x2\x9e\0\0\0\0\0\0\x1\xdc\0\0\x1x\0\0\x2\x9e\0\0\0\0\0\0) HistoryDockWidgetFloating=false HistoryDockWidgetVisible=true -FilesDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0(\0\0\0\xe7\0\0\0\xf0\0\0\0\0\0\0\0(\0\0\0\xe7\0\0\0\xf0\0\0\0\0\0\0) +FilesDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\x42\0\0\x1x\0\0\x1\x1\0\0\0\0\0\0\0\x42\0\0\x1x\0\0\x1\x1\0\0\0\0\0\0) FilesDockWidgetFloating=false FilesDockWidgetVisible=true DocumentationDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xfb\xb3\xff\xff\xfb\xb1\xff\xff\xfe\v\xff\xff\xfe\v\xff\xff\xfb\xb3\xff\xff\xfb\xb1\xff\xff\xfe\v\xff\xff\xfe\v\0\0\0\0\0\0) @@ -55,12 +56,12 @@ local_collapsed=false global_collapsed=false persistent_collapsed=false -column_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1\x90\0\0\0\x4\x1\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x1\0\0\x1\x90\0\0\0\x4\0\0\0\0) +column_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1\xf4\0\0\0\x5\x1\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x1\0\0\x1\xf4\0\0\0\x5\0\0\0\0) [filesdockwidget] sort_files_by_column=0 sort_files_by_order=0 -column_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x4\xe\0\0\0\x3\0\0\0\x3\0\0\0\x64\0\0\0\x2\0\0\0\x64\0\0\0\x1\0\0\0\x64\0\0\0\xd4\0\0\0\x4\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x2\0\0\0\xd4\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\0) +column_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x4\xe\0\0\0\x3\0\0\0\x3\0\0\0\x64\0\0\0\x2\0\0\0\x64\0\0\0\x1\0\0\0\x64\0\0\x1\x63\0\0\0\x4\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x2\0\0\x1\x63\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\0) showFilenames=true showFileSize=false showFileType=false diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/qterminal/libqterminal/QTerminal.cc --- a/libgui/qterminal/libqterminal/QTerminal.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/qterminal/libqterminal/QTerminal.cc Mon Apr 29 19:13:40 2013 -0400 @@ -42,9 +42,3 @@ else if (cursorType == "underline") setCursorType(QTerminalInterface::UnderlineCursor, cursorBlinking); } - -void -QTerminal::relay_command (const QString& command) -{ - sendText (command); -} diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/qterminal/libqterminal/QTerminal.h --- a/libgui/qterminal/libqterminal/QTerminal.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/qterminal/libqterminal/QTerminal.h Mon Apr 29 19:13:40 2013 -0400 @@ -38,7 +38,6 @@ public slots: void notice_settings (const QSettings *settings); - void relay_command (const QString& text); }; #else #include "unix/QUnixTerminalImpl.h" @@ -52,7 +51,6 @@ public slots: void notice_settings (const QSettings *settings); - void relay_command (const QString& command); }; #endif diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/dialog.cc --- a/libgui/src/dialog.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/dialog.cc Mon Apr 29 19:13:40 2013 -0400 @@ -31,6 +31,7 @@ #include #include #include +#include // Could replace most of these with #include #include #include @@ -45,7 +46,7 @@ QUIWidgetCreator::QUIWidgetCreator (void) : QObject (), dialog_result (-1), dialog_button (), - string_list (new QStringList ()), list_index (new QIntList ()) + string_list (new QStringList ()), list_index (new QIntList ()), path_name (new QString ()) { } @@ -53,6 +54,7 @@ { delete string_list; delete list_index; + delete path_name; } @@ -72,7 +74,8 @@ void -QUIWidgetCreator::list_select_finished (const QIntList& selected, const int button_pressed) +QUIWidgetCreator::list_select_finished (const QIntList& selected, + int button_pressed) { // Store the value so that builtin functions can retrieve. *list_index = selected; @@ -84,7 +87,7 @@ void -QUIWidgetCreator::input_finished (const QStringList& input, const int button_pressed) +QUIWidgetCreator::input_finished (const QStringList& input, int button_pressed) { // Store the value so that builtin functions can retrieve. *string_list = input; @@ -94,6 +97,20 @@ waitcondition.wakeAll (); } +void +QUIWidgetCreator::filedialog_finished (const QStringList& files, + const QString& path, int filterindex) +{ + // Store the value so that builtin functions can retrieve. + *string_list = files; + dialog_result = filterindex; + *path_name = path; + + // Wake up Octave process so that it continues. + waitcondition.wakeAll (); +} + + MessageDialog::MessageDialog (const QString& message, const QString& title, @@ -261,9 +278,9 @@ connect (buttonCancel, SIGNAL (clicked ()), this, SLOT (buttonCancel_clicked ())); - connect (this, SIGNAL (finish_selection (const QIntList&, const int)), + connect (this, SIGNAL (finish_selection (const QIntList&, int)), &uiwidget_creator, - SLOT (list_select_finished (const QIntList&, const int))); + SLOT (list_select_finished (const QIntList&, int))); } @@ -368,9 +385,9 @@ connect (buttonCancel, SIGNAL (clicked ()), this, SLOT (buttonCancel_clicked ())); - connect (this, SIGNAL (finish_input (const QStringList&, const int)), + connect (this, SIGNAL (finish_input (const QStringList&, int)), &uiwidget_creator, - SLOT (input_finished (const QStringList&, const int))); + SLOT (input_finished (const QStringList&, int))); } @@ -386,7 +403,6 @@ done (QDialog::Accepted); } - void InputDialog::buttonCancel_clicked (void) { @@ -404,83 +420,77 @@ buttonCancel_clicked (); } - -cd_or_addpath_dialog::cd_or_addpath_dialog (const QString& file, - const QString& dir, - bool addpath_option) - : QDialog () +FileDialog::FileDialog (const QStringList& filters, const QString& title, + const QString& filename, const QString& dirname, + const QString& multimode) + : QFileDialog() { - QString prompt_string - = (addpath_option - ? tr ("The file %1 does not exist in the load path. To debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.").arg(file).arg(dir) - : tr ("The file %1 is shadowed by a file with the same name in the load path. To debug the function you are editing, change to the directory %2.").arg(file).arg(dir)); + // Create a NonModal message. + setWindowModality (Qt::NonModal); - QLabel *label = new QLabel (prompt_string); - label->setFixedWidth (500); - label->setWordWrap (true); - // QIcon *question_mark = new QIcon; - QHBoxLayout *horizontalLayout = new QHBoxLayout; - // horizontalLayout->addWidget (question_mark); - horizontalLayout->addWidget (label); - - QPushButton *buttonCd = new QPushButton (tr ("Change directory")); - QPushButton *buttonAddpath = 0; - if (addpath_option) - buttonAddpath = new QPushButton (tr ("Add directory to load path")); - QPushButton *buttonCancel = new QPushButton (tr ("Cancel")); + setWindowTitle (title.isEmpty () ? " " : title); + setDirectory (dirname); - QHBoxLayout *buttonsLayout = new QHBoxLayout; - buttonsLayout->addStretch (1); - buttonsLayout->addWidget (buttonCd); - if (addpath_option) - buttonsLayout->addWidget (buttonAddpath); - buttonsLayout->addWidget (buttonCancel); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addLayout (horizontalLayout); - mainLayout->addSpacing (12); - mainLayout->addLayout (buttonsLayout); - setLayout (mainLayout); + if (multimode == "on") // uigetfile multiselect=on + { + setFileMode (QFileDialog::ExistingFiles); + setAcceptMode (QFileDialog::AcceptOpen); + } + else if (multimode == "create") // uiputfile + { + setFileMode (QFileDialog::AnyFile); + setAcceptMode (QFileDialog::AcceptSave); + setOption (QFileDialog::DontConfirmOverwrite, false); + setConfirmOverwrite(true); + } + else // uigetfile multiselect=off + { + setFileMode (QFileDialog::ExistingFile); + setAcceptMode (QFileDialog::AcceptOpen); + } - setWindowTitle (tr ("Change Directory or Add Directory to Load Path")); - - connect (buttonCd, SIGNAL (clicked ()), - this, SLOT (buttonCd_clicked ())); + setNameFilters (filters); - if (addpath_option) - connect (buttonAddpath, SIGNAL (clicked ()), - this, SLOT (buttonAddpath_clicked ())); - - connect (buttonCancel, SIGNAL (clicked ()), - this, SLOT (buttonCancel_clicked ())); - - connect (this, SIGNAL (finished (int)), - &uiwidget_creator, SLOT (dialog_finished (int))); + selectFile (filename); + + connect (this, + SIGNAL (finish_input (const QStringList&, const QString&, int)), + &uiwidget_creator, + SLOT (filedialog_finished (const QStringList&, const QString&, + int))); } void -cd_or_addpath_dialog::buttonCd_clicked (void) +FileDialog::reject (void) { - emit finished (1); - done (QDialog::Accepted); + QStringList empty; + emit finish_input (empty, "", 0); + done (QDialog::Rejected); + } -void -cd_or_addpath_dialog::buttonAddpath_clicked (void) +void FileDialog::accept(void) { - emit finished (2); + QStringList string_result; + QString path; + int idx = 1; + + string_result = selectedFiles (); + + // Matlab expects just the file name, whereas the file dialog gave us + // pull path names, so fix it. + + for (int i = 0; i < string_result.size (); i++) + string_result[i] = QFileInfo (string_result[i]).fileName (); + + + path = directory ().absolutePath (); + + QStringList filters = nameFilters (); + idx = filters.indexOf (selectedNameFilter ()) + 1; + + // send the selected info + emit finish_input (string_result, path, idx); done (QDialog::Accepted); } -void -cd_or_addpath_dialog::buttonCancel_clicked (void) -{ - emit finished (-1); - done (QDialog::Rejected); -} - -void -cd_or_addpath_dialog::reject (void) -{ - buttonCancel_clicked (); -} diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/dialog.h --- a/libgui/src/dialog.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/dialog.h Mon Apr 29 19:13:40 2013 -0400 @@ -32,6 +32,7 @@ #include #include #include +#include // Defined for purposes of sending QList as part of signal. typedef QList QIntList; @@ -71,7 +72,7 @@ int get_dialog_result (void) { return dialog_result; } - const QString *get_dialog_button (void) { return &dialog_button; } + QString get_dialog_button (void) { return dialog_button; } bool signal_listview (const QStringList& list, const QString& mode, int wd, int ht, const QList& initial, @@ -101,19 +102,18 @@ return true; }; - // The debug dialog functionality may not really belong here, but it - // seems like the easiest thing to do at the moment. + const QStringList *get_string_list (void) { return string_list; } - bool signal_debug_cd_or_addpath (const QString& file, const QString& dir, - bool addpath_option) + bool signal_filedialog (const QStringList& filters, const QString& title, + const QString& filename, const QString& dirname, + const QString &multimode) { - emit create_debug_cd_or_addpath_dialog (file, dir, addpath_option); - + emit create_filedialog (filters, title, filename, dirname, multimode); return true; } - const QStringList *get_string_list (void) { return string_list; } - + const QString *get_dialog_path (void) { return path_name; } + void wait (void) { // Wait while the user is responding to message box. @@ -133,16 +133,19 @@ const QFloatList&, const QFloatList&, const QStringList&); - void create_debug_cd_or_addpath_dialog (const QString&, const QString&, bool); - + void create_filedialog (const QStringList& filters, const QString& title, + const QString& filename, const QString& dirname, + const QString& multimode); public slots: void dialog_button_clicked (QAbstractButton *button); - void list_select_finished (const QIntList& selected, - const int button_pressed); + void list_select_finished (const QIntList& selected, int button_pressed); - void input_finished (const QStringList& input, const int button_pressed); + void input_finished (const QStringList& input, int button_pressed); + + void filedialog_finished (const QStringList& files, const QString& path, + int filterindex); private: @@ -154,6 +157,8 @@ QStringList *string_list; QIntList *list_index; + QString *path_name; + // GUI objects cannot be accessed in the non-GUI thread. However, // signals can be sent to slots across threads with proper // synchronization. Hence, the use of QWaitCondition. @@ -203,7 +208,7 @@ signals: - void finish_selection (const QIntList&, const int); + void finish_selection (const QIntList&, int); public slots: @@ -229,7 +234,7 @@ signals: - void finish_input (const QStringList&, const int); + void finish_input (const QStringList&, int); public slots: @@ -240,24 +245,25 @@ void reject (void); }; -class cd_or_addpath_dialog : public QDialog +class FileDialog : public QFileDialog { Q_OBJECT public: - cd_or_addpath_dialog (const QString& file, const QString& dir, - bool addpath_option); - -public slots: + explicit FileDialog (const QStringList& filters, + const QString& title, const QString& filename, + const QString& dirname, const QString& multimode); - void buttonCd_clicked (void); +signals: - void buttonAddpath_clicked (void); + void finish_input (const QStringList&, const QString&, int); - void buttonCancel_clicked (void); +private slots: void reject (void); + + void accept (void); }; #endif diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/files-dock-widget.cc --- a/libgui/src/files-dock-widget.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/files-dock-widget.cc Mon Apr 29 19:13:40 2013 -0400 @@ -40,6 +40,10 @@ #include #include #include +#include +#include + +#include "load-save.h" files_dock_widget::files_dock_widget (QWidget *p) : octave_dock_widget (p) @@ -175,7 +179,7 @@ this, SLOT (set_current_directory (const QString &))); connect (this, SIGNAL (run_file_signal (const QString&)), - parent (), SLOT (handle_command_double_clicked (const QString&))); + parent (), SLOT (execute_command_in_terminal (const QString&))); QCompleter *completer = new QCompleter (_file_system_model, this); _current_directory->setCompleter (completer); @@ -280,12 +284,30 @@ } else { - if (QFile::exists (fileInfo.absoluteFilePath ())) - emit open_file (fileInfo.absoluteFilePath ()); + QString abs_fname = fileInfo.absoluteFilePath (); + + if (QFile::exists (abs_fname)) + { + if (is_octave_data_file (abs_fname.toStdString ())) + emit load_file_signal (abs_fname); + else + emit open_file (fileInfo.absoluteFilePath ()); + } } } } +void +files_dock_widget::open_item_in_app (const QModelIndex& index) +{ + // Retrieve the file info associated with the model index. + QFileInfo fileInfo = _file_system_model->fileInfo (index); + + QString file = fileInfo.absoluteFilePath (); + + QDesktopServices::openUrl (QUrl::fromLocalFile (file)); +} + void files_dock_widget::contextmenu_requested (const QPoint& mpos) { @@ -301,9 +323,14 @@ menu.addAction (QIcon (":/actions/icons/fileopen.png"), tr("Open"), this, SLOT(contextmenu_open(bool))); + + menu.addAction (tr("Open in Default Application"), + this, SLOT (contextmenu_open_in_app (bool))); + if (info.isFile () && info.suffix () == "m") menu.addAction (QIcon (":/actions/icons/artsbuilderexecute.png"), tr("Run"), this, SLOT(contextmenu_run(bool))); + if (info.isFile ()) menu.addAction (tr("Load Data"), this, SLOT(contextmenu_load(bool))); @@ -350,6 +377,16 @@ } void +files_dock_widget::contextmenu_open_in_app (bool) +{ + QItemSelectionModel *m = _file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); + + for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++) + open_item_in_app (*it); +} + +void files_dock_widget::contextmenu_load (bool) { QItemSelectionModel *m = _file_tree_view->selectionModel (); diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/files-dock-widget.h --- a/libgui/src/files-dock-widget.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/files-dock-widget.h Mon Apr 29 19:13:40 2013 -0400 @@ -85,6 +85,7 @@ /* context menu actions */ void contextmenu_open (bool); + void contextmenu_open_in_app (bool); void contextmenu_run (bool); void contextmenu_load (bool); void contextmenu_rename (bool); @@ -119,6 +120,8 @@ /** set a new directory or open a file **/ void display_directory (const QString& dir, bool set_octave_dir = true); + void open_item_in_app (const QModelIndex& index); + /** Variables for the actions **/ QToolBar * _navigation_tool_bar; QAction * _sync_octave_directory_action; diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/history-dock-widget.cc --- a/libgui/src/history-dock-widget.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/history-dock-widget.cc Mon Apr 29 19:13:40 2013 -0400 @@ -48,7 +48,7 @@ p, SLOT (report_status_message (const QString&))); connect (this, SIGNAL (command_double_clicked (const QString&)), - p, SLOT (handle_command_double_clicked (const QString&))); + p, SLOT (execute_command_in_terminal (const QString&))); construct (); } diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/m-editor/file-editor-interface.h --- a/libgui/src/m-editor/file-editor-interface.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/m-editor/file-editor-interface.h Mon Apr 29 19:13:40 2013 -0400 @@ -65,6 +65,8 @@ public slots: virtual void request_new_file (const QString& command = QString ()) = 0; + virtual void request_new_script (const QString& command = QString ()) = 0; + virtual void request_new_function (const QString& command = QString ()) = 0; virtual void request_open_file () = 0; virtual void request_open_file (const QString& openFileName, int line = -1, bool debug_pointer = false, diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/m-editor/file-editor-tab.cc --- a/libgui/src/m-editor/file-editor-tab.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/m-editor/file-editor-tab.cc Mon Apr 29 19:13:40 2013 -0400 @@ -48,6 +48,8 @@ #include "file-editor-tab.h" #include "file-editor.h" +#include "cmd-edit.h" + #include "builtin-defun-decls.h" #include "debug.h" #include "load-path.h" @@ -57,13 +59,17 @@ // 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_tab::file_editor_tab (const QString& directory_arg) { + QString directory = directory_arg; + // 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. @@ -85,8 +91,8 @@ Qt::KeyboardModifiers))); // line numbers - _edit_area->setMarginsForegroundColor(QColor(96,96,96)); - _edit_area->setMarginsBackgroundColor(QColor(232,232,220)); + _edit_area->setMarginsForegroundColor (QColor (96, 96, 96)); + _edit_area->setMarginsBackgroundColor (QColor (232, 232, 220)); _edit_area->setMarginType (2, QsciScintilla::TextMargin); // code folding @@ -94,7 +100,7 @@ _edit_area->setFolding (QsciScintilla::BoxedTreeFoldStyle , 3); //highlight current line color - _edit_area->setCaretLineBackgroundColor(QColor(245,245,245)); + _edit_area->setCaretLineBackgroundColor (QColor (245, 245, 245)); // other features _edit_area->setBraceMatching (QsciScintilla::StrictBraceMatch); @@ -106,7 +112,7 @@ // auto completion _edit_area->autoCompleteFromAll (); - _edit_area->setAutoCompletionSource(QsciScintilla::AcsAll); + _edit_area->setAutoCompletionSource (QsciScintilla::AcsAll); QVBoxLayout *edit_area_layout = new QVBoxLayout (); edit_area_layout->addWidget (_edit_area); @@ -116,24 +122,26 @@ // connect modified signal connect (_edit_area, SIGNAL (modificationChanged (bool)), this, SLOT (update_window_title (bool))); + connect (_edit_area, SIGNAL (copyAvailable (bool)), this, SLOT (handle_copy_available (bool))); - connect (&_file_system_watcher, SIGNAL (fileChanged (QString)), - this, SLOT (file_has_changed (QString))); + + connect (&_file_system_watcher, SIGNAL (fileChanged (const QString&)), + this, SLOT (file_has_changed (const QString&))); QSettings *settings = resource_manager::get_settings (); if (settings) notice_settings (settings); } -file_editor_tab::~file_editor_tab () +file_editor_tab::~file_editor_tab (void) { // Destroy items attached to _edit_area. QsciLexer *lexer = _edit_area->lexer (); if (lexer) { delete lexer; - _edit_area->setLexer(0); + _edit_area->setLexer (0); } if (_find_dialog) { @@ -151,13 +159,9 @@ // ignore close event if file is not saved and user cancels // closing this window if (check_file_modified () == QMessageBox::Cancel) - { - e->ignore (); - } + e->ignore (); else - { - e->accept(); - } + e->accept (); } void @@ -181,7 +185,7 @@ } void -file_editor_tab::handle_margin_clicked(int margin, int line, +file_editor_tab::handle_margin_clicked (int margin, int line, Qt::KeyboardModifiers state) { if (margin == 1) @@ -191,9 +195,9 @@ if (state & Qt::ControlModifier) { if (markers_mask && (1 << bookmark)) - _edit_area->markerDelete(line,bookmark); + _edit_area->markerDelete (line, bookmark); else - _edit_area->markerAdd(line,bookmark); + _edit_area->markerAdd (line, bookmark); } else { @@ -211,7 +215,9 @@ QsciLexer *lexer = _edit_area->lexer (); delete lexer; - if (_file_name.endsWith (".m") || _file_name.endsWith (".M")) + if (_file_name.endsWith (".m") + || _file_name.endsWith (".M") + || _file_name.endsWith ("octaverc")) { lexer = new lexer_octave_gui (); } @@ -253,7 +259,7 @@ // slot for fetab_set_focus: sets the focus to the current edit area void -file_editor_tab::set_focus (const QWidget* ID) +file_editor_tab::set_focus (const QWidget *ID) { if (ID != this) return; @@ -261,7 +267,7 @@ } void -file_editor_tab::undo (const QWidget* ID) +file_editor_tab::undo (const QWidget *ID) { if (ID != this) return; @@ -270,7 +276,7 @@ } void -file_editor_tab::redo (const QWidget* ID) +file_editor_tab::redo (const QWidget *ID) { if (ID != this) return; @@ -279,7 +285,7 @@ } void -file_editor_tab::copy (const QWidget* ID) +file_editor_tab::copy (const QWidget *ID) { if (ID != this) return; @@ -288,7 +294,7 @@ } void -file_editor_tab::cut (const QWidget* ID) +file_editor_tab::cut (const QWidget *ID) { if (ID != this) return; @@ -297,7 +303,7 @@ } void -file_editor_tab::paste (const QWidget* ID) +file_editor_tab::paste (const QWidget *ID) { if (ID != this) return; @@ -306,7 +312,7 @@ } void -file_editor_tab::save_file (const QWidget* ID) +file_editor_tab::save_file (const QWidget *ID) { if (ID != this) return; @@ -315,7 +321,8 @@ } void -file_editor_tab::save_file (const QWidget* ID, const QString& fileName, bool remove_on_success) +file_editor_tab::save_file (const QWidget *ID, const QString& fileName, + bool remove_on_success) { if (ID != this) return; @@ -324,7 +331,7 @@ } void -file_editor_tab::save_file_as (const QWidget* ID) +file_editor_tab::save_file_as (const QWidget *ID) { if (ID != this) return; @@ -333,31 +340,42 @@ } void -file_editor_tab::print_file (const QWidget* ID) +file_editor_tab::print_file (const QWidget *ID) { if (ID != this) return; - QsciPrinter * printer = new QsciPrinter( QPrinter::HighResolution ); + QsciPrinter *printer = new QsciPrinter (QPrinter::HighResolution); - QPrintDialog printDlg(printer, this); + QPrintDialog printDlg (printer, this); - if(printDlg.exec() == QDialog::Accepted) - { - printer->printRange(_edit_area); - } + if (printDlg.exec () == QDialog::Accepted) + printer->printRange (_edit_area); + delete printer; } void -file_editor_tab::run_file_callback (void) +file_editor_tab::run_file_callback (const bp_info& info) { - // Maybe someday we will do something here? + if (file_in_path (info.file, info.dir)) + { + std::string pending_input = command_editor::get_current_line (); + + command_editor::set_initial_input (pending_input); + + command_editor::replace_line (info.function_name); + command_editor::redisplay (); + + // We are executing inside the command editor event loop. Force + // the current line to be returned for processing. + command_editor::interrupt (); + } } void -file_editor_tab::run_file (const QWidget* ID) +file_editor_tab::run_file (const QWidget *ID) { if (ID != this) return; @@ -366,63 +384,66 @@ save_file (_file_name); QFileInfo file_info (_file_name); - QString path = file_info.absolutePath (); + QString dir = 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); - 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 ())); + + bp_info info (_file_name, dir, function_name, 1); + + octave_link::post_event (this, &file_editor_tab::run_file_callback, info); } void -file_editor_tab::toggle_bookmark (const QWidget* ID) +file_editor_tab::toggle_bookmark (const QWidget *ID) { if (ID != this) return; int line, cur; - _edit_area->getCursorPosition (&line,&cur); - if ( _edit_area->markersAtLine (line) && (1 << bookmark) ) + _edit_area->getCursorPosition (&line, &cur); + + if (_edit_area->markersAtLine (line) && (1 << bookmark)) _edit_area->markerDelete (line, bookmark); else _edit_area->markerAdd (line, bookmark); } void -file_editor_tab::next_bookmark (const QWidget* ID) +file_editor_tab::next_bookmark (const QWidget *ID) { if (ID != this) return; - int line, cur, nextline; + int line, cur; _edit_area->getCursorPosition (&line, &cur); - if ( _edit_area->markersAtLine (line) && (1 << bookmark) ) + + if (_edit_area->markersAtLine (line) && (1 << bookmark)) line++; // we have a breakpoint here, so start search from next line - nextline = _edit_area->markerFindNext (line, (1 << bookmark)); + + int nextline = _edit_area->markerFindNext (line, (1 << bookmark)); + _edit_area->setCursorPosition (nextline, 0); } void -file_editor_tab::previous_bookmark (const QWidget* ID) +file_editor_tab::previous_bookmark (const QWidget *ID) { if (ID != this) return; - int line, cur, prevline; + int line, cur; _edit_area->getCursorPosition (&line, &cur); - if ( _edit_area->markersAtLine (line) && (1 << bookmark) ) + + if (_edit_area->markersAtLine (line) && (1 << bookmark)) line--; // we have a breakpoint here, so start search from prev line - prevline = _edit_area->markerFindPrevious (line, (1 << bookmark)); + + int prevline = _edit_area->markerFindPrevious (line, (1 << bookmark)); + _edit_area->setCursorPosition (prevline, 0); } void -file_editor_tab::remove_bookmark (const QWidget* ID) +file_editor_tab::remove_bookmark (const QWidget *ID) { if (ID != this) return; @@ -431,25 +452,25 @@ } bool -file_editor_tab::file_in_path (const bp_info& info) +file_editor_tab::file_in_path (const std::string& file, const std::string& dir) { bool ok = false; bool addpath_option = true; std::string curr_dir = octave_env::get_current_directory (); - if (curr_dir == info.path) + if (same_file (curr_dir, dir)) ok = true; else { - bool dir_in_load_path = load_path::contains_canonical (info.path); + bool dir_in_load_path = load_path::contains_canonical (dir); - std::string base_file = octave_env::base_pathname (info.file); + std::string base_file = octave_env::base_pathname (file); std::string lp_file = load_path::find_file (base_file); if (dir_in_load_path) { - if (same_file (lp_file, info.file)) + if (same_file (lp_file, file)) ok = true; } else @@ -462,7 +483,7 @@ if (same_file (lp_file, base_file)) { - if (same_file (curr_dir, info.path)) + if (same_file (curr_dir, dir)) ok = true; else addpath_option = false; @@ -473,17 +494,16 @@ if (! ok) { int action - = octave_link::debug_cd_or_addpath_error (info.file, info.path, - addpath_option); + = octave_link::debug_cd_or_addpath_error (file, dir, addpath_option); switch (action) { case 1: - Fcd (ovl (info.path)); + Fcd (ovl (dir)); ok = true; break; case 2: - load_path::prepend (info.path); + load_path::prepend (dir); ok = true; break; @@ -501,7 +521,7 @@ bp_table::intmap line_info; line_info[0] = info.line; - if (file_in_path (info)) + if (file_in_path (info.file, info.dir)) bp_table::add_breakpoint (info.function_name, line_info); } @@ -511,14 +531,14 @@ bp_table::intmap line_info; line_info[0] = info.line; - if (file_in_path (info)) + if (file_in_path (info.file, info.dir)) bp_table::remove_breakpoint (info.function_name, line_info); } void file_editor_tab::remove_all_breakpoints_callback (const bp_info& info) { - if (file_in_path (info)) + if (file_in_path (info.file, info.dir)) bp_table::remove_all_breakpoints_in_file (info.function_name, true); } @@ -526,13 +546,13 @@ file_editor_tab::request_add_breakpoint (int line) { QFileInfo file_info (_file_name); - QString path = file_info.absolutePath (); + QString dir = 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 (_file_name, path, function_name, line+1); + bp_info info (_file_name, dir, function_name, line+1); octave_link::post_event (this, &file_editor_tab::add_breakpoint_callback, info); @@ -542,81 +562,88 @@ file_editor_tab::request_remove_breakpoint (int line) { QFileInfo file_info (_file_name); - QString path = file_info.absolutePath (); + QString dir = 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 (_file_name, path, function_name, line+1); + bp_info info (_file_name, dir, function_name, line+1); octave_link::post_event (this, &file_editor_tab::remove_breakpoint_callback, info); } void -file_editor_tab::toggle_breakpoint (const QWidget* ID) +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) ) + + 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) +file_editor_tab::next_breakpoint (const QWidget *ID) { if (ID != this) return; - int line, cur, nextline; + int line, cur; _edit_area->getCursorPosition (&line, &cur); - if ( _edit_area->markersAtLine (line) && (1 << breakpoint) ) + + 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)); + + int nextline = _edit_area->markerFindNext (line, (1 << breakpoint)); + _edit_area->setCursorPosition (nextline, 0); } void -file_editor_tab::previous_breakpoint (const QWidget* ID) +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) ) + + 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) +file_editor_tab::remove_all_breakpoints (const QWidget *ID) { if (ID != this) return; QFileInfo file_info (_file_name); - QString path = file_info.absolutePath (); + QString dir = 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 (_file_name, path, function_name, 0); + bp_info info (_file_name, dir, 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) +file_editor_tab::comment_selected_text (const QWidget *ID) { if (ID != this) return; @@ -625,7 +652,7 @@ } void -file_editor_tab::uncomment_selected_text (const QWidget* ID) +file_editor_tab::uncomment_selected_text (const QWidget *ID) { if (ID != this) return; @@ -643,7 +670,7 @@ } void -file_editor_tab::find (const QWidget* ID) +file_editor_tab::find (const QWidget *ID) { if (ID != this) return; @@ -658,7 +685,7 @@ if (!_find_dialog) { _find_dialog = new find_dialog (_edit_area, - qobject_cast(sender ())); + qobject_cast (sender ())); connect (_find_dialog, SIGNAL (finished (int)), this, SLOT (handle_find_dialog_finished (int))); _find_dialog->setWindowModality (Qt::NonModal); @@ -678,7 +705,7 @@ } void -file_editor_tab::goto_line (const QWidget* ID, int line) +file_editor_tab::goto_line (const QWidget *ID, int line) { if (ID != this) return; @@ -687,9 +714,10 @@ { bool ok = false; int index; - _edit_area->getCursorPosition(&line, &index); - line = QInputDialog::getInt (_edit_area, tr("Goto line"), tr("Line number"), - line+1, 1, _edit_area->lines(), 1, &ok); + _edit_area->getCursorPosition (&line, &index); + line = QInputDialog::getInt (_edit_area, tr ("Goto line"), + tr ("Line number"), line+1, 1, + _edit_area->lines (), 1, &ok); if (ok) { _edit_area->setCursorPosition (line-1, 0); @@ -697,36 +725,38 @@ } } else // go to given line without dialog - { - _edit_area->setCursorPosition (line-1, 0); - } + _edit_area->setCursorPosition (line-1, 0); } void file_editor_tab::do_comment_selected_text (bool comment) { - if ( _edit_area->hasSelectedText() ) + 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 + int lineFrom, lineTo, colFrom, colTo; + _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++ ) + + for (int i = lineFrom; i <= lineTo; i++) { - if ( comment ) - _edit_area->insertAt("%",i,0); + if (comment) + _edit_area->insertAt ("%", i, 0); else { - QString line(_edit_area->text(i)); - if ( line.startsWith("%") ) + QString line (_edit_area->text (i)); + if (line.startsWith ("%")) { - _edit_area->setSelection(i,0,i,1); - _edit_area->removeSelectedText(); + _edit_area->setSelection (i, 0, i, 1); + _edit_area->removeSelectedText (); } } } + _edit_area->endUndoAction (); } } @@ -736,30 +766,29 @@ { QString title (""); QString tooltip (""); + if (_file_name.isEmpty () || _file_name.at (_file_name.count () - 1) == '/') - title = tr(""); + title = tr (""); else { - if ( _long_title ) + if (_long_title) title = _file_name; else { - QFileInfo file(_file_name); - title = file.fileName(); + QFileInfo file (_file_name); + title = file.fileName (); tooltip = _file_name; } } - if ( modified ) - { - emit file_name_changed (title.prepend("* "), tooltip); - } + if (modified) + emit file_name_changed (title.prepend ("* "), tooltip); else emit file_name_changed (title, tooltip); } void -file_editor_tab::handle_copy_available(bool enableCopy) +file_editor_tab::handle_copy_available (bool enableCopy) { _copy_available = enableCopy; emit editor_state_changed (_copy_available, QDir::cleanPath (_file_name)); @@ -774,14 +803,15 @@ // 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\n" - "%1\n" - "is about to be closed but has been modified.\n" - "Do you want to cancel closing, save or discard the changes?"). - arg (_file_name), - QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard, 0); + 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" + "Do you want to cancel closing, save or discard the changes?"). + arg (_file_name), + QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard, 0); + msgBox->setDefaultButton (QMessageBox::Save); _edit_area->setReadOnly (true); connect (msgBox, SIGNAL (finished (int)), @@ -789,7 +819,8 @@ msgBox->setWindowModality (Qt::NonModal); msgBox->setAttribute (Qt::WA_DeleteOnClose); msgBox->show (); - return (QMessageBox::Cancel); + + return QMessageBox::Cancel; } else { @@ -797,7 +828,7 @@ emit tab_remove_request (); } - return (decision); + return decision; } void @@ -827,13 +858,11 @@ } QString -file_editor_tab::load_file(const QString& fileName) +file_editor_tab::load_file (const QString& fileName) { QFile file (fileName); if (!file.open (QFile::ReadOnly)) - { - return file.errorString (); - } + return file.errorString (); QTextStream in (&file); QApplication::setOverrideCursor (Qt::WaitCursor); @@ -860,7 +889,8 @@ { // If it is a new file with no name, signal that saveFileAs // should be performed. - if (saveFileName.isEmpty () || saveFileName.at (saveFileName.count () - 1) == '/') + if (saveFileName.isEmpty () + || saveFileName.at (saveFileName.count () - 1) == '/') { save_file_as (remove_on_success); return; @@ -881,14 +911,16 @@ _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); + 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; } @@ -897,12 +929,14 @@ QApplication::setOverrideCursor (Qt::WaitCursor); out << _edit_area->text (); QApplication::restoreOverrideCursor (); - file.close(); + 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); @@ -939,10 +973,9 @@ else { fileDialog->selectFile (""); + if (_file_name.isEmpty ()) - { - fileDialog->setDirectory (QDir::currentPath ()); - } + fileDialog->setDirectory (QDir::currentPath ()); else { // The file name is actually the directory name from the @@ -950,14 +983,17 @@ fileDialog->setDirectory (_file_name); } } - fileDialog->setNameFilter (tr("Octave Files (*.m);;All Files (*.*)")); + + fileDialog->setNameFilter (tr ("Octave Files (*.m);;All Files (*)")); 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 ())); } @@ -966,6 +1002,7 @@ 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 (); @@ -979,12 +1016,13 @@ // 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! The selected file name\n%1\n" - "is the same as the current file name"). - arg (saveFileName), - QMessageBox::Ok, 0); + QMessageBox* msgBox + = new QMessageBox (QMessageBox::Critical, tr ("Octave Editor"), + tr ("File not saved! The selected file name\n%1\n" + "is the same as the current file name"). + arg (saveFileName), + QMessageBox::Ok, 0); + msgBox->setWindowModality (Qt::NonModal); msgBox->setAttribute (Qt::WA_DeleteOnClose); msgBox->show (); @@ -1043,12 +1081,16 @@ { // 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); + 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 (); @@ -1058,19 +1100,23 @@ QString modified = ""; if (_edit_area->isModified ()) modified = tr ("\n\nWarning: The contents in the editor is modified!"); + // Create a WindowModal message. 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 ("It seems that the file\n" - "%1\n" - "has been deleted or renamed. Do you want to save it now?%2"). - arg (_file_name).arg (modified), - QMessageBox::Save | QMessageBox::Close, 0); + QMessageBox* msgBox + = new QMessageBox (QMessageBox::Warning, tr ("Octave Editor"), + tr ("It seems that the file\n" + "%1\n" + "has been deleted or renamed. Do you want to save it now?%2"). + arg (_file_name).arg (modified), + QMessageBox::Save | QMessageBox::Close, 0); + _edit_area->setReadOnly (true); + connect (msgBox, SIGNAL (finished (int)), this, SLOT (handle_file_resave_answer (int))); + msgBox->setWindowModality (Qt::WindowModal); msgBox->setAttribute (Qt::WA_DeleteOnClose); msgBox->show (); @@ -1083,33 +1129,35 @@ // QSettings pointer is checked before emitting. update_lexer (); + QFontMetrics lexer_font_metrics (_edit_area->lexer ()->defaultFont (0)); - _edit_area->setCaretLineVisible(settings->value ("editor/highlightCurrentLine",true).toBool ()); + _edit_area->setCaretLineVisible + (settings->value ("editor/highlightCurrentLine", true).toBool ()); - if (settings->value ("editor/codeCompletion",true).toBool ()) + if (settings->value ("editor/codeCompletion", true).toBool ()) _edit_area->setAutoCompletionThreshold (1); else _edit_area->setAutoCompletionThreshold (-1); - if (settings->value ("editor/showLineNumbers",true).toBool ()) + if (settings->value ("editor/showLineNumbers", true).toBool ()) { _edit_area->setMarginLineNumbers (2, true); - _edit_area->setMarginWidth(2, lexer_font_metrics.width("9999")); + _edit_area->setMarginWidth (2, lexer_font_metrics.width ("9999")); } else { _edit_area->setMarginLineNumbers (2, false); - _edit_area->setMarginWidth(2, 0); + _edit_area->setMarginWidth (2, 0); } - _long_title = settings->value ("editor/longWindowTitle",false).toBool (); + _long_title = settings->value ("editor/longWindowTitle", false).toBool (); update_window_title (false); } void -file_editor_tab::conditional_close (const QWidget* ID) +file_editor_tab::conditional_close (const QWidget *ID) { if (ID != this) return; @@ -1118,7 +1166,7 @@ } void -file_editor_tab::change_editor_state (const QWidget* ID) +file_editor_tab::change_editor_state (const QWidget *ID) { if (ID != this) { @@ -1139,11 +1187,12 @@ _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) +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. @@ -1159,11 +1208,13 @@ file_editor_tab::handle_file_reload_answer (int decision) { if (decision == QMessageBox::Yes) - { // reload: file is readded to the file watcher in set_file_name () + { + // reload: file is readded to the file watcher in set_file_name () load_file (_file_name); } else - { // do not reload: readd to the file watche + { + // do not reload: readd to the file watche _file_system_watcher.addPath (_file_name); } } @@ -1230,15 +1281,18 @@ void file_editor_tab::center_current_line () { - long int visible_lines = _edit_area->SendScintilla - (QsciScintillaBase::SCI_LINESONSCREEN); + long int visible_lines + = _edit_area->SendScintilla (QsciScintillaBase::SCI_LINESONSCREEN); + if (visible_lines > 2) { int line, index; - _edit_area->getCursorPosition(&line,&index); + _edit_area->getCursorPosition (&line, &index); + int first_line = _edit_area->firstVisibleLine (); first_line = first_line + (line - first_line - (visible_lines-1)/2); - _edit_area->setFirstVisibleLine (first_line); + + _edit_area->SendScintilla (2613,first_line); // SCI_SETFIRSTVISIBLELINE } } diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/m-editor/file-editor-tab.h --- a/libgui/src/m-editor/file-editor-tab.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/m-editor/file-editor-tab.h Mon Apr 29 19:13:40 2013 -0400 @@ -20,64 +20,75 @@ */ -#ifndef FILEEDITORTAB_H -#define FILEEDITORTAB_H +#if !defined (file_editor_tab_h) +#define file_editor_tab_h 1 -#include #include #include #include #include +#include + #include "find-dialog.h" class file_editor; + class file_editor_tab : public QWidget { Q_OBJECT - public: - file_editor_tab (QString directory = ""); - ~file_editor_tab (); + +public: + + file_editor_tab (const QString& directory = ""); + + ~file_editor_tab (void); 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); - /** Tells the editor tab to react on changed settings. */ + void update_window_title (bool modified); + void handle_copy_available (bool enableCopy); + void handle_margin_clicked (int line, int margin, + Qt::KeyboardModifiers state); + + // Tells the editor tab to react on changed settings. void notice_settings (const QSettings *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); + + // 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 set_focus (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 print_file (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 set_focus (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 print_file (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 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 goto_line (const QWidget* ID, int line = -1); + void comment_selected_text (const QWidget *ID); + void uncomment_selected_text (const QWidget *ID); + void find (const QWidget *ID); + void goto_line (const QWidget *ID, int line = -1); void insert_debugger_pointer (const QWidget *ID, int line = -1); void delete_debugger_pointer (const QWidget *ID, int line = -1); @@ -92,43 +103,58 @@ void file_has_changed (const QString& fileName); signals: + void file_name_changed (const QString& fileName, const QString& toolTip); void editor_state_changed (bool copy_available, const QString& fileName); void tab_remove_request (); void add_filename_to_list (const QString&, QWidget *); void mru_add_file (const QString& file_name); - void editor_check_conflict_save (const QString& saveFileName, bool remove_on_success); + 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. */ + + // When user closes message box for reload question. void handle_file_reload_answer (int decision); - /** When user closes message box for resave question. */ + + // When user closes message box for resave question. void handle_file_resave_answer (int decision); - /** When user closes message box for modified question. */ + + // When user closes message box for modified question. void handle_file_modified_answer (int decision); - /** When user closes find_dialog box. */ + + // When user closes find_dialog box. void handle_find_dialog_finished (int decision); - /** When user closes QFileDialog box. */ + + // 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: + enum editor_markers + { + bookmark, + breakpoint, + debugger_position + }; + struct bp_info { - bp_info (const QString& f, const QString& p, const QString& fn, int l) - : file (f.toStdString ()), path (p.toStdString ()), + bp_info (const QString& f, const QString& d, const QString& fn, int l) + : file (f.toStdString ()), dir (d.toStdString ()), function_name (fn.toStdString ()), line (l) { } std::string file; - std::string path; + std::string dir; std::string function_name; int line; }; @@ -144,28 +170,28 @@ int check_file_modified (); void do_comment_selected_text (bool comment); - void run_file_callback (void); + void run_file_callback (const bp_info& info); - bool file_in_path (const bp_info& info); + bool file_in_path (const std::string& file, const std::string& dir); void add_breakpoint_callback (const bp_info& info); void remove_breakpoint_callback (const bp_info& info); void remove_all_breakpoints_callback (const bp_info& info); void center_current_line (); - QsciScintilla * _edit_area; + QsciScintilla *_edit_area; - QString _file_name; - QString _file_name_short; + QString _file_name; + QString _file_name_short; - bool _long_title; - bool _copy_available; + bool _long_title; + bool _copy_available; - QFileSystemWatcher _file_system_watcher; + QFileSystemWatcher _file_system_watcher; - find_dialog * _find_dialog; - bool _find_dialog_is_visible; - QRect _find_dialog_geometry; + find_dialog *_find_dialog; + bool _find_dialog_is_visible; + QRect _find_dialog_geometry; }; -#endif // FILEEDITORTAB_H +#endif diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/m-editor/file-editor.cc --- a/libgui/src/m-editor/file-editor.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/m-editor/file-editor.cc Mon Apr 29 19:13:40 2013 -0400 @@ -53,11 +53,13 @@ setVisible (false); } -file_editor::~file_editor () +file_editor::~file_editor (void) { QSettings *settings = resource_manager::get_settings (); + editor_tab_map.clear (); - if (settings->value ("editor/restoreSession",true).toBool ()) + + if (settings->value ("editor/restoreSession", true).toBool ()) { // Have all file editor tabs signal what their file names are. emit fetab_file_name_query (0); @@ -96,7 +98,7 @@ // set focus to editor and its current tab void -file_editor::set_focus () +file_editor::set_focus (void) { if (!isVisible ()) setVisible (true); @@ -109,13 +111,13 @@ } QMenu * -file_editor::debug_menu () +file_editor::debug_menu (void) { return _debug_menu; } QToolBar * -file_editor::toolbar () +file_editor::toolbar (void) { return _tool_bar; } @@ -149,20 +151,47 @@ } void -file_editor::request_open_file () +file_editor::request_new_script (const QString& commands) +{ + request_new_file (commands); +} + +void +file_editor::request_new_function (const QString& commands) +{ + QString text = commands; + + if (text.isEmpty ()) + text = "## Copyright (C)\n" + "\n" + "## -*- texinfo -*-\n" + "## @deftypefn {Function File} {[outputs] =} unamed_function (inputs)\n" + "## @end deftypefn\n" + "\n" + "function [outputs] = unnamed_function (inputs)\n" + "\n" + "endfunction\n"; + + request_new_file (text); +} + +void +file_editor::request_open_file (void) { // 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 (tr("Octave Files (*.m);;All Files (*.*)")); + QFileDialog *fileDialog = new QFileDialog (this); + fileDialog->setNameFilter (tr ("Octave Files (*.m);;All Files (*)")); 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 (); @@ -199,11 +228,11 @@ if (settings->value ("useCustomFileEditor").toBool ()) { QString editor = settings->value ("customFileEditor").toString (); - editor.replace ("%f",openFileName); - editor.replace ("%l",QString::number (line)); + editor.replace ("%f", openFileName); + editor.replace ("%l", QString::number (line)); QProcess::startDetached (editor); if (line < 0) - handle_mru_add_file(QDir::cleanPath (openFileName)); + handle_mru_add_file (QDir::cleanPath (openFileName)); return; } @@ -243,7 +272,7 @@ file_editor_tab *fileEditorTab = new file_editor_tab (); if (fileEditorTab) { - QString result = fileEditorTab->load_file(openFileName); + QString result = fileEditorTab->load_file (openFileName); if (result == "") { // Supply empty title then have the file_editor_tab update @@ -251,7 +280,7 @@ add_file_editor_tab (fileEditorTab, ""); fileEditorTab->update_window_title (false); // file already loaded, add file to mru list here - handle_mru_add_file(QDir::cleanPath (openFileName)); + handle_mru_add_file (QDir::cleanPath (openFileName)); if (line > 0) { @@ -269,11 +298,13 @@ { 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); + 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 (); @@ -288,9 +319,9 @@ // open a file from the mru list void -file_editor::request_mru_open_file () +file_editor::request_mru_open_file (void) { - QAction *action = qobject_cast(sender ()); + QAction *action = qobject_cast (sender ()); if (action) { request_open_file (action->data ().toString ()); @@ -318,12 +349,13 @@ // 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! A file with the selected name\n%1\n" - "is already open in the editor"). - arg (saveFileName), - QMessageBox::Ok, 0); + QMessageBox *msgBox + = new QMessageBox (QMessageBox::Critical, tr ("Octave Editor"), + tr ("File not saved! A file with the selected name\n%1\n" + "is already open in the editor"). + arg (saveFileName), + QMessageBox::Ok, 0); + msgBox->setWindowModality (Qt::NonModal); msgBox->setAttribute (Qt::WA_DeleteOnClose); msgBox->show (); @@ -331,9 +363,10 @@ return; } - QObject* saveFileObject = sender (); - QWidget* saveFileWidget = 0; - for(int i = 0; i < _tab_widget->count (); i++) + QObject *saveFileObject = sender (); + QWidget *saveFileWidget = 0; + + for (int i = 0; i < _tab_widget->count (); i++) { if (_tab_widget->widget (i) == saveFileObject) { @@ -344,13 +377,15 @@ 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); + 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; } @@ -359,13 +394,15 @@ } void -file_editor::handle_insert_debugger_pointer_request (const QString& file, int line) +file_editor::handle_insert_debugger_pointer_request (const QString& file, + int line) { request_open_file (file, line, true); } void -file_editor::handle_delete_debugger_pointer_request (const QString& file, int line) +file_editor::handle_delete_debugger_pointer_request (const QString& file, + int line) { if (! file.isEmpty ()) { @@ -390,7 +427,8 @@ void file_editor::handle_update_breakpoint_marker_request (bool insert, - const QString& file, int line) + const QString& file, + int line) { request_open_file (file, line, false, true, insert); } @@ -402,128 +440,128 @@ } void -file_editor::request_undo () +file_editor::request_undo (void) { emit fetab_undo (_tab_widget->currentWidget ()); } void -file_editor::request_redo () +file_editor::request_redo (void) { emit fetab_redo (_tab_widget->currentWidget ()); } void -file_editor::request_copy () +file_editor::request_copy (void) { emit fetab_copy (_tab_widget->currentWidget ()); } void -file_editor::request_cut () +file_editor::request_cut (void) { emit fetab_cut (_tab_widget->currentWidget ()); } void -file_editor::request_paste () +file_editor::request_paste (void) { emit fetab_paste (_tab_widget->currentWidget ()); } void -file_editor::request_save_file () +file_editor::request_save_file (void) { emit fetab_save_file (_tab_widget->currentWidget ()); } void -file_editor::request_save_file_as () +file_editor::request_save_file_as (void) { emit fetab_save_file_as (_tab_widget->currentWidget ()); } void -file_editor::request_print_file () +file_editor::request_print_file (void) { emit fetab_print_file (_tab_widget->currentWidget ()); } void -file_editor::request_run_file () +file_editor::request_run_file (void) { emit fetab_run_file (_tab_widget->currentWidget ()); } void -file_editor::request_toggle_bookmark () +file_editor::request_toggle_bookmark (void) { emit fetab_toggle_bookmark (_tab_widget->currentWidget ()); } void -file_editor::request_next_bookmark () +file_editor::request_next_bookmark (void) { emit fetab_next_bookmark (_tab_widget->currentWidget ()); } void -file_editor::request_previous_bookmark () +file_editor::request_previous_bookmark (void) { emit fetab_previous_bookmark (_tab_widget->currentWidget ()); } void -file_editor::request_remove_bookmark () +file_editor::request_remove_bookmark (void) { emit fetab_remove_bookmark (_tab_widget->currentWidget ()); } void -file_editor::request_toggle_breakpoint () +file_editor::request_toggle_breakpoint (void) { emit fetab_toggle_breakpoint (_tab_widget->currentWidget ()); } void -file_editor::request_next_breakpoint () +file_editor::request_next_breakpoint (void) { emit fetab_next_breakpoint (_tab_widget->currentWidget ()); } void -file_editor::request_previous_breakpoint () +file_editor::request_previous_breakpoint (void) { emit fetab_previous_breakpoint (_tab_widget->currentWidget ()); } void -file_editor::request_remove_breakpoint () +file_editor::request_remove_breakpoint (void) { emit fetab_remove_all_breakpoints (_tab_widget->currentWidget ()); } void -file_editor::request_comment_selected_text () +file_editor::request_comment_selected_text (void) { emit fetab_comment_selected_text (_tab_widget->currentWidget ()); } void -file_editor::request_uncomment_selected_text () +file_editor::request_uncomment_selected_text (void) { emit fetab_uncomment_selected_text (_tab_widget->currentWidget ()); } void -file_editor::request_find () +file_editor::request_find (void) { emit fetab_find (_tab_widget->currentWidget ()); } void -file_editor::request_goto_line () +file_editor::request_goto_line (void) { emit fetab_goto_line (_tab_widget->currentWidget ()); } @@ -538,28 +576,33 @@ } void -file_editor::mru_menu_update () +file_editor::mru_menu_update (void) { - int num_files = qMin (_mru_files.size(), int (MaxMRUFiles)); + int num_files = qMin (_mru_files.size (), int (MaxMRUFiles)); + // configure and show active actions of mru-menu for (int i = 0; i < num_files; ++i) { - QString text = tr("&%1 %2"). + QString text = tr ("&%1 %2"). arg ((i+1) % int (MaxMRUFiles)).arg (_mru_files.at (i)); _mru_file_actions[i]->setText (text); _mru_file_actions[i]->setData (_mru_files.at (i)); _mru_file_actions[i]->setVisible (true); } + // hide unused mru-menu entries for (int j = num_files; j < MaxMRUFiles; ++j) _mru_file_actions[j]->setVisible (false); + // delete entries in string-list beyond MaxMRUFiles while (_mru_files.size () > MaxMRUFiles) _mru_files.removeLast (); + // save actual mru-list in settings QSettings *settings = resource_manager::get_settings (); + // FIXME -- what should happen if settings is 0? - settings->setValue ("editor/mru_file_list",_mru_files); + settings->setValue ("editor/mru_file_list", _mru_files); settings->sync (); } @@ -567,10 +610,10 @@ file_editor::handle_file_name_changed (const QString& fname, const QString& tip) { - QObject *fileEditorTab = sender(); + QObject *fileEditorTab = sender (); if (fileEditorTab) { - for(int i = 0; i < _tab_widget->count (); i++) + for (int i = 0; i < _tab_widget->count (); i++) { if (_tab_widget->widget (i) == fileEditorTab) { @@ -593,12 +636,12 @@ } void -file_editor::handle_tab_remove_request () +file_editor::handle_tab_remove_request (void) { - QObject *fileEditorTab = sender(); + QObject *fileEditorTab = sender (); if (fileEditorTab) { - for(int i = 0; i < _tab_widget->count (); i++) + for (int i = 0; i < _tab_widget->count (); i++) { if (_tab_widget->widget (i) == fileEditorTab) { @@ -624,25 +667,27 @@ } void -file_editor::handle_editor_state_changed (bool copy_available, const QString& file_name) +file_editor::handle_editor_state_changed (bool copy_available, + const QString& file_name) { // 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 ()) + 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); - } + ced = ced.left (lastslash); } + setFocusProxy (_tab_widget->currentWidget ()); } } @@ -650,14 +695,14 @@ void file_editor::notice_settings (const QSettings *settings) { - int icon_size = settings->value ("toolbar_icon_size",24).toInt (); - _tool_bar->setIconSize (QSize (icon_size,icon_size)); + int icon_size = settings->value ("toolbar_icon_size", 24).toInt (); + _tool_bar->setIconSize (QSize (icon_size, icon_size)); // Relay signal to file editor tabs. emit fetab_settings_changed (settings); } void -file_editor::construct () +file_editor::construct (void) { QWidget *editor_widget = new QWidget (this); @@ -669,42 +714,50 @@ _tab_widget = new QTabWidget (editor_widget); _tab_widget->setTabsClosable (true); - QAction *new_action = new QAction (QIcon(":/actions/icons/filenew.png"), - tr("&New File"), _tool_bar); + QAction *new_action = new QAction (QIcon (":/actions/icons/filenew.png"), + tr ("&New File"), _tool_bar); - QAction *open_action = new QAction (QIcon(":/actions/icons/fileopen.png"), - tr("&Open File"), _tool_bar); + QAction *open_action = new QAction (QIcon (":/actions/icons/fileopen.png"), + tr ("&Open File"), _tool_bar); - QAction *save_action = new QAction (QIcon(":/actions/icons/filesave.png"), - tr("&Save File"), _tool_bar); + QAction *save_action = new QAction (QIcon (":/actions/icons/filesave.png"), + tr ("&Save File"), _tool_bar); QAction *save_as_action - = new QAction (QIcon(":/actions/icons/filesaveas.png"), - tr("Save File &As"), _tool_bar); + = new QAction (QIcon (":/actions/icons/filesaveas.png"), + tr ("Save File &As"), _tool_bar); QAction *print_action - = new QAction ( QIcon(":/actions/icons/fileprint.png"), + = new QAction ( QIcon (":/actions/icons/fileprint.png"), tr ("Print"), _tool_bar); - QAction *undo_action = new QAction (QIcon(":/actions/icons/undo.png"), - tr("&Undo"), _tool_bar); + QAction *undo_action = new QAction (QIcon (":/actions/icons/undo.png"), + tr ("&Undo"), _tool_bar); - QAction *redo_action = new QAction (QIcon(":/actions/icons/redo.png"), - tr("&Redo"), _tool_bar); + QAction *redo_action = new QAction (QIcon (":/actions/icons/redo.png"), + tr ("&Redo"), _tool_bar); - _copy_action = new QAction (QIcon(":/actions/icons/editcopy.png"), + _copy_action = new QAction (QIcon (":/actions/icons/editcopy.png"), tr ("&Copy"), _tool_bar); - _cut_action = new QAction (QIcon(":/actions/icons/editcut.png"), + _cut_action = new QAction (QIcon (":/actions/icons/editcut.png"), tr ("Cu&t"), _tool_bar); QAction *paste_action = new QAction (QIcon (":/actions/icons/editpaste.png"), - tr("Paste"), _tool_bar); - QAction *next_bookmark_action = new QAction (tr ("&Next Bookmark"),_tool_bar); - QAction *previous_bookmark_action = new QAction (tr ("Pre&vious Bookmark"),_tool_bar); - QAction *toggle_bookmark_action = new QAction (tr ("Toggle &Bookmark"),_tool_bar); - QAction *remove_bookmark_action = new QAction (tr ("&Remove All Bookmarks"),_tool_bar); + tr ("Paste"), _tool_bar); + + QAction *next_bookmark_action + = new QAction (tr ("&Next Bookmark"), _tool_bar); + + QAction *previous_bookmark_action + = new QAction (tr ("Pre&vious Bookmark"), _tool_bar); + + QAction *toggle_bookmark_action + = new QAction (tr ("Toggle &Bookmark"), _tool_bar); + + QAction *remove_bookmark_action + = new QAction (tr ("&Remove All Bookmarks"), _tool_bar); QAction *next_breakpoint_action = new QAction (QIcon (":/actions/icons/bp_next.png"), @@ -719,16 +772,19 @@ = new QAction (QIcon (":/actions/icons/bp_rm_all.png"), tr ("&Remove All breakpoints"), _tool_bar); - QAction *comment_selection_action = new QAction (tr ("&Comment Selected Text"),_tool_bar); - QAction *uncomment_selection_action = new QAction (tr ("&Uncomment Selected Text"),_tool_bar); + QAction *comment_selection_action + = new QAction (tr ("&Comment Selected Text"), _tool_bar); - QAction *find_action = new QAction (QIcon(":/actions/icons/search.png"), + QAction *uncomment_selection_action + = new QAction (tr ("&Uncomment Selected Text"), _tool_bar); + + QAction *find_action = new QAction (QIcon (":/actions/icons/search.png"), tr ("&Find and Replace"), _tool_bar); - _run_action = new QAction (QIcon(":/actions/icons/artsbuilderexecute.png"), - tr("Save File And Run"), _tool_bar); + _run_action = new QAction (QIcon (":/actions/icons/artsbuilderexecute.png"), + tr ("Save File And Run"), _tool_bar); - QAction *goto_line_action = new QAction (tr ("Go&to Line"), _tool_bar); + QAction *goto_line_action = new QAction (tr ("Go&to Line"), _tool_bar); // the mru-list and an empty array of actions QSettings *settings = resource_manager::get_settings (); @@ -741,32 +797,32 @@ } // some actions are disabled from the beginning - _copy_action->setEnabled(false); - _cut_action->setEnabled(false); - _run_action->setShortcut (Qt::ControlModifier+ Qt::Key_R); - _run_action->setShortcutContext (Qt::WindowShortcut); - save_action->setShortcut (QKeySequence::Save); - save_action->setShortcutContext (Qt::WindowShortcut); - save_as_action->setShortcut (QKeySequence::SaveAs); - save_as_action->setShortcutContext (Qt::WindowShortcut); + _copy_action->setEnabled (false); + _cut_action->setEnabled (false); + _run_action->setShortcut (Qt::ControlModifier+ Qt::Key_R); + _run_action->setShortcutContext (Qt::WindowShortcut); + save_action->setShortcut (QKeySequence::Save); + save_action->setShortcutContext (Qt::WindowShortcut); + save_as_action->setShortcut (QKeySequence::SaveAs); + save_as_action->setShortcutContext (Qt::WindowShortcut); - print_action->setShortcut (QKeySequence::Print); - print_action->setShortcutContext (Qt::WindowShortcut); + print_action->setShortcut (QKeySequence::Print); + print_action->setShortcutContext (Qt::WindowShortcut); - next_bookmark_action->setShortcut (Qt::Key_F2); - next_bookmark_action->setShortcutContext (Qt::WindowShortcut); - previous_bookmark_action->setShortcut (Qt::SHIFT + Qt::Key_F2); - previous_bookmark_action->setShortcutContext (Qt::WindowShortcut); - toggle_bookmark_action->setShortcut (Qt::Key_F7); - toggle_bookmark_action->setShortcutContext (Qt::WindowShortcut); - comment_selection_action->setShortcut (Qt::ControlModifier + Qt::Key_7); - comment_selection_action->setShortcutContext (Qt::WindowShortcut); - uncomment_selection_action->setShortcut (Qt::ControlModifier + Qt::Key_8); - uncomment_selection_action->setShortcutContext(Qt::WindowShortcut); - find_action->setShortcut (QKeySequence::Find); - find_action->setShortcutContext (Qt::WindowShortcut); - goto_line_action->setShortcut (Qt::ControlModifier+ Qt::Key_G); - goto_line_action->setShortcutContext (Qt::WindowShortcut); + next_bookmark_action->setShortcut (Qt::Key_F2); + next_bookmark_action->setShortcutContext (Qt::WindowShortcut); + previous_bookmark_action->setShortcut (Qt::SHIFT + Qt::Key_F2); + previous_bookmark_action->setShortcutContext (Qt::WindowShortcut); + toggle_bookmark_action->setShortcut (Qt::Key_F7); + toggle_bookmark_action->setShortcutContext (Qt::WindowShortcut); + comment_selection_action->setShortcut (Qt::ControlModifier + Qt::Key_7); + comment_selection_action->setShortcutContext (Qt::WindowShortcut); + uncomment_selection_action->setShortcut (Qt::ControlModifier + Qt::Key_8); + uncomment_selection_action->setShortcutContext (Qt::WindowShortcut); + find_action->setShortcut (QKeySequence::Find); + find_action->setShortcutContext (Qt::WindowShortcut); + goto_line_action->setShortcut (Qt::ControlModifier+ Qt::Key_G); + goto_line_action->setShortcutContext (Qt::WindowShortcut); // toolbar _tool_bar->addAction (new_action); @@ -774,7 +830,7 @@ _tool_bar->addAction (save_action); _tool_bar->addAction (save_as_action); _tool_bar->addSeparator (); - _tool_bar->addAction(print_action); + _tool_bar->addAction (print_action); _tool_bar->addSeparator (); _tool_bar->addAction (undo_action); _tool_bar->addAction (redo_action); @@ -798,10 +854,10 @@ fileMenu->addAction (save_as_action); fileMenu->addSeparator (); _mru_file_menu = new QMenu (tr ("&Recent Editor Files"), fileMenu); + for (int i = 0; i < MaxMRUFiles; ++i) - { - _mru_file_menu->addAction (_mru_file_actions[i]); - } + _mru_file_menu->addAction (_mru_file_actions[i]); + fileMenu->addMenu (_mru_file_menu); _menu_bar->addMenu (fileMenu); @@ -859,162 +915,226 @@ connect (parent (), SIGNAL (open_file_signal (const QString&)), this, SLOT (request_open_file (const QString&))); - connect (new_action, - SIGNAL (triggered ()), this, SLOT (request_new_file ())); - connect (open_action, - SIGNAL (triggered ()), this, SLOT (request_open_file ())); - connect (undo_action, - SIGNAL (triggered ()), this, SLOT (request_undo ())); - connect (redo_action, - SIGNAL (triggered ()), this, SLOT (request_redo ())); - connect (_copy_action, - SIGNAL (triggered ()), this, SLOT (request_copy ())); - connect (_cut_action, - SIGNAL (triggered ()), this, SLOT (request_cut ())); - connect (paste_action, - SIGNAL (triggered ()), this, SLOT (request_paste ())); - connect (save_action, - SIGNAL (triggered ()), this, SLOT (request_save_file ())); - connect (save_as_action, - SIGNAL (triggered ()), this, SLOT (request_save_file_as ())); - connect (print_action, - SIGNAL (triggered ()), this, SLOT (request_print_file ())); - connect (_run_action, - SIGNAL (triggered ()), this, SLOT (request_run_file ())); - connect (toggle_bookmark_action, - SIGNAL (triggered ()), this, SLOT (request_toggle_bookmark ())); - connect (next_bookmark_action, - SIGNAL (triggered ()), this, SLOT (request_next_bookmark ())); - connect (previous_bookmark_action, - SIGNAL (triggered ()), this, SLOT (request_previous_bookmark ())); - connect (remove_bookmark_action, - SIGNAL (triggered ()), this, SLOT (request_remove_bookmark ())); - connect (toggle_breakpoint_action, - SIGNAL (triggered ()), this, SLOT (request_toggle_breakpoint ())); - connect (next_breakpoint_action, - SIGNAL (triggered ()), this, SLOT (request_next_breakpoint ())); - connect (previous_breakpoint_action, - SIGNAL (triggered ()), this, SLOT (request_previous_breakpoint ())); - connect (remove_all_breakpoints_action, - SIGNAL (triggered ()), this, SLOT (request_remove_breakpoint ())); - connect (comment_selection_action, - SIGNAL (triggered ()), this, SLOT (request_comment_selected_text ())); - connect (uncomment_selection_action, - SIGNAL (triggered ()), this, SLOT (request_uncomment_selected_text ())); - connect (find_action, - SIGNAL (triggered ()), this, SLOT (request_find ())); + connect (new_action, SIGNAL (triggered ()), + this, SLOT (request_new_file ())); + + connect (open_action, SIGNAL (triggered ()), + this, SLOT (request_open_file ())); + + connect (undo_action, SIGNAL (triggered ()), + this, SLOT (request_undo ())); + + connect (redo_action, SIGNAL (triggered ()), + this, SLOT (request_redo ())); + + connect (_copy_action, SIGNAL (triggered ()), + this, SLOT (request_copy ())); + + connect (_cut_action, SIGNAL (triggered ()), + this, SLOT (request_cut ())); + + connect (paste_action, SIGNAL (triggered ()), + this, SLOT (request_paste ())); + + connect (save_action, SIGNAL (triggered ()), + this, SLOT (request_save_file ())); + + connect (save_as_action, SIGNAL (triggered ()), + this, SLOT (request_save_file_as ())); + + connect (print_action, SIGNAL (triggered ()), + this, SLOT (request_print_file ())); + + connect (_run_action, SIGNAL (triggered ()), + this, SLOT (request_run_file ())); - connect (goto_line_action, - SIGNAL (triggered ()), this, SLOT (request_goto_line ())); - + connect (toggle_bookmark_action, SIGNAL (triggered ()), + this, SLOT (request_toggle_bookmark ())); + + connect (next_bookmark_action, SIGNAL (triggered ()), + this, SLOT (request_next_bookmark ())); + + connect (previous_bookmark_action, SIGNAL (triggered ()), + this, SLOT (request_previous_bookmark ())); + + connect (remove_bookmark_action, SIGNAL (triggered ()), + this, SLOT (request_remove_bookmark ())); + + connect (toggle_breakpoint_action, SIGNAL (triggered ()), + this, SLOT (request_toggle_breakpoint ())); + + connect (next_breakpoint_action, SIGNAL (triggered ()), + this, SLOT (request_next_breakpoint ())); + + connect (previous_breakpoint_action, SIGNAL (triggered ()), + this, SLOT (request_previous_breakpoint ())); + + connect (remove_all_breakpoints_action, SIGNAL (triggered ()), + this, SLOT (request_remove_breakpoint ())); + + connect (comment_selection_action, SIGNAL (triggered ()), + this, SLOT (request_comment_selected_text ())); + + connect (uncomment_selection_action, SIGNAL (triggered ()), + this, SLOT (request_uncomment_selected_text ())); + + connect (find_action, SIGNAL (triggered ()), + this, SLOT (request_find ())); + + connect (goto_line_action, SIGNAL (triggered ()), + this, SLOT (request_goto_line ())); + // The actions of the mru file menu for (int i = 0; i < MaxMRUFiles; ++i) { - connect(_mru_file_actions[i], SIGNAL (triggered ()), this, SLOT (request_mru_open_file ())); + connect (_mru_file_actions[i], SIGNAL (triggered ()), + this, SLOT (request_mru_open_file ())); } + mru_menu_update (); - connect (_tab_widget, - SIGNAL (tabCloseRequested (int)), this, SLOT (handle_tab_close_request (int))); - connect (_tab_widget, - SIGNAL (currentChanged(int)), this, SLOT (active_tab_changed (int))); + + connect (_tab_widget, SIGNAL (tabCloseRequested (int)), + this, SLOT (handle_tab_close_request (int))); + + connect (_tab_widget, SIGNAL (currentChanged (int)), + this, SLOT (active_tab_changed (int))); resize (500, 400); - setWindowIcon (QIcon(":/actions/icons/logo.png")); + setWindowIcon (QIcon (":/actions/icons/logo.png")); setWindowTitle ("Editor"); //restore previous session - if (settings->value ("editor/restoreSession",true).toBool ()) + if (settings->value ("editor/restoreSession", true).toBool ()) { - QStringList sessionFileNames = settings->value("editor/savedSessionTabs", QStringList()).toStringList (); + QStringList sessionFileNames + = settings->value ("editor/savedSessionTabs", QStringList ()).toStringList (); - for (int n=0; n < sessionFileNames.count (); ++n) + for (int n = 0; n < sessionFileNames.count (); ++n) request_open_file (sessionFileNames.at (n)); } } void -file_editor::add_file_editor_tab (file_editor_tab *f, const QString &fn) +file_editor::add_file_editor_tab (file_editor_tab *f, const QString& fn) { _tab_widget->addTab (f, fn); // Signals from the file editor_tab connect (f, SIGNAL (file_name_changed (const QString&, const QString&)), - this, SLOT (handle_file_name_changed (const QString&, const QString&))); + this, SLOT (handle_file_name_changed (const QString&, + 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&, QWidget *)), - this, SLOT (handle_add_filename_to_list (const QString&, QWidget *))); + + connect (f, SIGNAL (add_filename_to_list (const QString&, QWidget*)), + this, SLOT (handle_add_filename_to_list (const QString&, QWidget*))); + connect (f, SIGNAL (editor_check_conflict_save (const QString&, bool)), this, SLOT (check_conflict_save (const QString&, bool))); + connect (f, SIGNAL (mru_add_file (const QString&)), this, SLOT (handle_mru_add_file (const QString&))); + connect (f, SIGNAL (process_octave_code (const QString&)), - parent (), SLOT (handle_command_double_clicked (const QString&))); + parent (), SLOT (execute_command_in_terminal (const QString&))); // Signals from the file_editor non-trivial operations connect (this, SIGNAL (fetab_settings_changed (const QSettings *)), f, SLOT (notice_settings (const QSettings *))); + 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)), + + 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_print_file (const QWidget*)), f, SLOT (print_file (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*))); - connect (this, SIGNAL (fetab_goto_line (const QWidget *, int)), - f, SLOT (goto_line (const QWidget *, int))); + + connect (this, SIGNAL (fetab_goto_line (const QWidget*, int)), + f, SLOT (goto_line (const QWidget*, int))); + connect (this, SIGNAL (fetab_set_focus (const QWidget*)), f, SLOT (set_focus (const QWidget*))); - connect (this, SIGNAL (fetab_insert_debugger_pointer (const QWidget *, int)), - f, SLOT (insert_debugger_pointer (const QWidget *, int))); - connect (this, SIGNAL (fetab_delete_debugger_pointer (const QWidget *, int)), - f, SLOT (delete_debugger_pointer (const QWidget *, int))); - connect (this, SIGNAL (fetab_do_breakpoint_marker (bool, const QWidget *, int)), - f, SLOT (do_breakpoint_marker (bool, const QWidget *, int))); + + connect (this, SIGNAL (fetab_insert_debugger_pointer (const QWidget*, int)), + f, SLOT (insert_debugger_pointer (const QWidget*, int))); + + connect (this, SIGNAL (fetab_delete_debugger_pointer (const QWidget*, int)), + f, SLOT (delete_debugger_pointer (const QWidget*, int))); + + connect (this, SIGNAL (fetab_do_breakpoint_marker (bool, const QWidget*, + int)), + f, SLOT (do_breakpoint_marker (bool, const QWidget*, int))); _tab_widget->setCurrentWidget (f); } diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/m-editor/file-editor.h --- a/libgui/src/m-editor/file-editor.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/m-editor/file-editor.h Mon Apr 29 19:13:40 2013 -0400 @@ -36,13 +36,6 @@ #include "file-editor-interface.h" #include "file-editor-tab.h" -enum editor_markers - { - bookmark, - breakpoint, - debugger_position - }; - class file_editor : public file_editor_interface { Q_OBJECT @@ -53,27 +46,29 @@ typedef std::map::const_iterator editor_tab_map_const_iterator; file_editor (QWidget *p); - ~file_editor (); + ~file_editor (void); void connect_visibility_changed (void); void loadFile (const QString& fileName); - QMenu * get_mru_menu ( ) { return _mru_file_menu; } - QMenu * debug_menu (); - QToolBar * toolbar (); + QMenu *get_mru_menu (void) { return _mru_file_menu; } + QMenu *debug_menu (void); + QToolBar *toolbar (void); - void set_focus (); + void set_focus (void); void handle_enter_debug_mode (void); void handle_exit_debug_mode (void); signals: + void fetab_settings_changed (const QSettings *settings); 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); + 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); @@ -99,7 +94,8 @@ void fetab_goto_line (const QWidget* ID, int line = -1); void fetab_insert_debugger_pointer (const QWidget* ID, int line = -1); void fetab_delete_debugger_pointer (const QWidget* ID, int line = -1); - void fetab_do_breakpoint_marker (bool insert, const QWidget* ID, int line = -1); + void fetab_do_breakpoint_marker (bool insert, const QWidget* ID, + int line = -1); void fetab_set_focus (const QWidget* ID); public slots: @@ -107,37 +103,40 @@ void handle_visibility (bool visible); void request_new_file (const QString& commands); - void request_open_file (); - void request_mru_open_file (); - void request_print_file (); + void request_new_script (const QString& commands); + void request_new_function (const QString& commands); + void request_open_file (void); + void request_mru_open_file (void); + void request_print_file (void); - void request_undo (); - void request_redo (); - void request_copy (); - void request_cut (); - void request_paste (); - void request_save_file (); - void request_save_file_as (); - void request_run_file (); - void request_toggle_bookmark (); - void request_next_bookmark (); - void request_previous_bookmark (); - void request_remove_bookmark (); + void request_undo (void); + void request_redo (void); + void request_copy (void); + void request_cut (void); + void request_paste (void); + void request_save_file (void); + void request_save_file_as (void); + void request_run_file (void); + void request_toggle_bookmark (void); + void request_next_bookmark (void); + void request_previous_bookmark (void); + void request_remove_bookmark (void); - void request_toggle_breakpoint (); - void request_next_breakpoint (); - void request_previous_breakpoint (); - void request_remove_breakpoint (); + void request_toggle_breakpoint (void); + void request_next_breakpoint (void); + void request_previous_breakpoint (void); + void request_remove_breakpoint (void); - void request_comment_selected_text (); - void request_uncomment_selected_text (); - void request_find (); + void request_comment_selected_text (void); + void request_uncomment_selected_text (void); + void request_find (void); - void request_goto_line (); + void request_goto_line (void); - void handle_file_name_changed (const QString& fileName, const QString& toolTip); + void handle_file_name_changed (const QString& fileName, + const QString& toolTip); void handle_tab_close_request (int index); - void handle_tab_remove_request (); + void handle_tab_remove_request (void); void handle_add_filename_to_list (const QString& fileName, QWidget *ID); void active_tab_changed (int index); void handle_editor_state_changed (bool enableCopy, const QString& fileName); @@ -146,23 +145,26 @@ void handle_insert_debugger_pointer_request (const QString& file, int line); void handle_delete_debugger_pointer_request (const QString& file, int line); - void handle_update_breakpoint_marker_request (bool insert, const QString& file, - int line); + void handle_update_breakpoint_marker_request (bool insert, + const QString& file, int line); + void handle_edit_file_request (const QString& file); - /** Tells the editor to react on changed settings. */ + // Tells the editor to react on changed settings. void notice_settings (const QSettings *settings); private slots: + void request_open_file (const QString& fileName, int line = -1, bool debug_pointer = false, bool breakpoint_marker = false, bool insert = true); private: - void construct (); - void add_file_editor_tab(file_editor_tab *f, const QString &fn); + + void construct (void); + void add_file_editor_tab (file_editor_tab *f, const QString& fn); void save_file_as (QWidget *fetabID = 0); - void mru_menu_update (); + void mru_menu_update (void); QWidget *find_tab_widget (const QString& openFileName) const; @@ -170,14 +172,14 @@ QString ced; - QMenuBar * _menu_bar; - QToolBar * _tool_bar; - QMenu * _debug_menu; - QAction * _copy_action; - QAction * _cut_action; - QAction * _run_action; - QTabWidget * _tab_widget; - int _marker_breakpoint; + QMenuBar *_menu_bar; + QToolBar *_tool_bar; + QMenu *_debug_menu; + QAction *_copy_action; + QAction *_cut_action; + QAction *_run_action; + QTabWidget *_tab_widget; + int _marker_breakpoint; enum { MaxMRUFiles = 10 }; QMenu *_mru_file_menu; diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/m-editor/lexer-octave-gui.cc --- a/libgui/src/m-editor/lexer-octave-gui.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/m-editor/lexer-octave-gui.cc Mon Apr 29 19:13:40 2013 -0400 @@ -67,17 +67,20 @@ // functions of the class QsciLexer () and the enum of available styles (see // lexer-octave-gui.h provides the functionality of the octave lexer. // ----------------------------------------------------------------------------- -const char *lexer_octave_gui::language() const +const char * +lexer_octave_gui::language() const { return "Octave"; // return the name of the language } -const char *lexer_octave_gui::lexer() const +const char * +lexer_octave_gui::lexer() const { return "octave"; // return the name of the lexer } -QString lexer_octave_gui::description(int style) const +QString +lexer_octave_gui::description(int style) const { switch (style) { @@ -103,10 +106,66 @@ return QString(); // no valid style, return empty string } + +// ----------------------------------------------------- +// The set of default colors +// ----------------------------------------------------- +QColor +lexer_octave_gui::defaultColor (int style) const +{ + switch (style) + { + case Default: + case Operator: + return QColor (0x00,0x00,0x00); + + case Comment: + return QColor (0x00,0x7f,0x00); + + case Command: + return QColor (0x7f,0x7f,0x00); + + case Number: + return QColor (0x00,0x7f,0x7f); + + case Keyword: + return QColor (0x00,0x00,0x7f); + + case SingleQuotedString: + case DoubleQuotedString: + return QColor (0x7f,0x00,0x7f); + } + + return QsciLexer::defaultColor (style); +} + +// ----------------------------------------------------- +// The defaulot fonts +// ----------------------------------------------------- +QFont +lexer_octave_gui::defaultFont (int style) const +{ + QFont font; + + switch (style) + { + case Keyword: + font = QsciLexer::defaultFont (style); + font.setBold(true); + break; + + default: + font = QsciLexer::defaultFont (style); + } + + return font; +} + // ----------------------------------------------------- // The set of keywords for highlighting // ----------------------------------------------------- -const char *lexer_octave_gui::keywords(int set) const +const char * +lexer_octave_gui::keywords(int set) const { if (set == 1) return resource_manager::octave_keywords (); diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/m-editor/lexer-octave-gui.h --- a/libgui/src/m-editor/lexer-octave-gui.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/m-editor/lexer-octave-gui.h Mon Apr 29 19:13:40 2013 -0400 @@ -53,7 +53,9 @@ virtual const char *keywords (int set) const; virtual const char *lexer () const; virtual const char *language () const; - QString description(int style) const; + QString description (int style) const; + QColor defaultColor (int style) const; + QFont defaultFont (int style) const; private: lexer_octave_gui (const lexer_octave_gui &); diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/main-window.cc --- a/libgui/src/main-window.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/main-window.cc Mon Apr 29 19:13:40 2013 -0400 @@ -104,6 +104,12 @@ delete _octave_qt_link; } +bool +main_window::command_window_has_focus (void) const +{ + return command_window->has_focus (); +} + void main_window::focus_command_window (void) { @@ -188,11 +194,25 @@ } void -main_window::handle_command_double_clicked (const QString& command) +main_window::execute_command_in_terminal (const QString& command) { - emit relay_command_signal (command); + octave_link::post_event (this, &main_window::execute_command_callback, + command.toStdString ()); + + focus_command_window (); +} - command_window->focus (); +void +main_window::handle_new_figure_request (void) +{ + octave_link::post_event (this, &main_window::new_figure_callback); +} + +void +main_window::handle_new_variable_request (void) +{ + QMessageBox::about (this, tr ("New Variable"), + tr ("The new variable action is not implemented.")); } void @@ -306,9 +326,11 @@ } void -main_window::reset_windows () +main_window::reset_windows (void) { - // TODO: Implement. + QSettings *settings = resource_manager::get_default_settings (); + + set_window_layout (settings); } void @@ -332,13 +354,15 @@ void main_window::browse_for_directory (void) { - QString dir = - QFileDialog::getExistingDirectory (this, tr ("Set working directory")); + QString dir + = QFileDialog::getExistingDirectory (this, tr ("Set working directory")); + + set_current_working_directory (dir); - if (! dir.isEmpty ()) - octave_link::post_event (this, - &main_window::change_directory_callback, - dir.toStdString ()); + // FIXME -- on Windows systems, the command window freezes after the + // previous actions. Forcing the focus appears to unstick it. + + focus_command_window (); } void @@ -443,6 +467,43 @@ } void +main_window::handle_insert_debugger_pointer_request (const QString& file, + int line) +{ + bool cmd_focus = command_window_has_focus (); + + emit insert_debugger_pointer_signal (file, line); + + if (cmd_focus) + focus_command_window (); +} + +void +main_window::handle_delete_debugger_pointer_request (const QString& file, + int line) +{ + bool cmd_focus = command_window_has_focus (); + + emit delete_debugger_pointer_signal (file, line); + + if (cmd_focus) + focus_command_window (); +} + +void +main_window::handle_update_breakpoint_marker_request (bool insert, + const QString& file, + int line) +{ + bool cmd_focus = command_window_has_focus (); + + emit update_breakpoint_marker_signal (insert, file, line); + + if (cmd_focus) + focus_command_window (); +} + +void main_window::show_about_octave (void) { QString message = OCTAVE_STARTUP_MESSAGE; @@ -461,32 +522,15 @@ main_window::read_settings (void) { QSettings *settings = resource_manager::get_settings (); + if (!settings) { qDebug("Error: QSettings pointer from resource manager is NULL."); return; } - restoreState (settings->value ("MainWindow/windowState").toByteArray ()); - settings->beginGroup ("DockWidgets"); - // restoring the geometry of all dock-widgets - foreach (QObject *obj, children ()) - { - QString name = obj->objectName (); - if (obj->inherits ("QDockWidget") && ! name.isEmpty ()) - { - QDockWidget *widget = qobject_cast (obj); - QVariant val = settings->value (name); - widget->restoreGeometry (val.toByteArray ()); - bool floating = settings->value (name+"Floating", false).toBool (); - bool visible = settings->value (name+"Visible", true).toBool (); - if (floating) - widget->setWindowFlags (Qt::Window); // if floating, make window from widget - widget->setVisible (visible); // make widget visible if desired (setWindowFlags hides widget) - } - } - settings->endGroup(); - restoreGeometry (settings->value ("MainWindow/geometry").toByteArray ()); + set_window_layout (settings); + // restore the list of the last directories QStringList curr_dirs = settings->value ("MainWindow/current_directory_list").toStringList (); for (int i=0; i < curr_dirs.size (); i++) @@ -497,6 +541,41 @@ } void +main_window::set_window_layout (QSettings *settings) +{ + restoreState (settings->value ("MainWindow/windowState").toByteArray ()); + + settings->beginGroup ("DockWidgets"); + + // Restore the geometry of all dock-widgets + foreach (QObject *obj, children ()) + { + QString name = obj->objectName (); + + if (obj->inherits ("QDockWidget") && ! name.isEmpty ()) + { + QDockWidget *widget = qobject_cast (obj); + QVariant val = settings->value (name); + + widget->restoreGeometry (val.toByteArray ()); + + // If floating, make window from widget. + bool floating = settings->value (name+"Floating", false).toBool (); + if (floating) + widget->setWindowFlags (Qt::Window); + + // make widget visible if desired (setWindowFlags hides widget). + bool visible = settings->value (name+"Visible", true).toBool (); + widget->setVisible (visible); + } + } + + settings->endGroup (); + + restoreGeometry (settings->value ("MainWindow/geometry").toByteArray ()); +} + +void main_window::write_settings (void) { QSettings *settings = resource_manager::get_settings (); @@ -594,12 +673,12 @@ const QStringList&))); connect (&uiwidget_creator, - SIGNAL (create_debug_cd_or_addpath_dialog (const QString&, - const QString&, bool)), + SIGNAL (create_filedialog (const QStringList &,const QString&, + const QString&, const QString&, const QString&)), this, - SLOT (handle_create_debug_cd_or_addpath_dialog (const QString&, - const QString&, - bool))); + SLOT (handle_create_filedialog (const QStringList &, const QString&, + const QString&, const QString&, + const QString&))); } // Create a message dialog with specified string, buttons and decorative @@ -657,16 +736,17 @@ } void -main_window::handle_create_debug_cd_or_addpath_dialog (const QString& file, - const QString& dir, - bool addpath_option) - +main_window::handle_create_filedialog (const QStringList& filters, + const QString& title, + const QString& filename, + const QString& dirname, + const QString& multimode) { - cd_or_addpath_dialog *dialog - = new cd_or_addpath_dialog (file, dir, addpath_option); + FileDialog *file_dialog = new FileDialog (filters, title, filename, + dirname, multimode); - dialog->setAttribute (Qt::WA_DeleteOnClose); - dialog->show (); + file_dialog->setAttribute (Qt::WA_DeleteOnClose); + file_dialog->show (); } // Main subroutine of the constructor @@ -677,6 +757,8 @@ setWindowIcon (QIcon (":/actions/icons/logo.png")); workspace_window->setModel (_workspace_model); + connect (_workspace_model, SIGNAL (model_changed (void)), + workspace_window, SLOT (handle_model_changed (void))); // Create and set the central widget. QMainWindow takes ownership of // the widget (pointer) so there is no need to delete the object upon @@ -738,6 +820,21 @@ construct_octave_qt_link (); + connect (this, + SIGNAL (insert_debugger_pointer_signal (const QString&, int)), + editor_window, + SLOT (handle_insert_debugger_pointer_request (const QString&, int))); + + connect (this, + SIGNAL (delete_debugger_pointer_signal (const QString&, int)), + editor_window, + SLOT (handle_delete_debugger_pointer_request (const QString&, int))); + + connect (this, + SIGNAL (update_breakpoint_marker_signal (bool, const QString&, int)), + editor_window, + SLOT (handle_update_breakpoint_marker_request (bool, const QString&, int))); + QDir curr_dir; set_current_working_directory (curr_dir.absolutePath ()); @@ -772,6 +869,10 @@ this, SLOT (change_directory (QString))); connect (_octave_qt_link, + SIGNAL (execute_command_in_terminal_signal (QString)), + this, SLOT (execute_command_in_terminal (QString))); + + connect (_octave_qt_link, SIGNAL (set_history_signal (const QStringList&)), history_window, SLOT (set_history (const QStringList&))); @@ -790,25 +891,25 @@ this, SLOT (handle_exit_debugger ())); connect (_octave_qt_link, - SIGNAL (update_breakpoint_marker_signal (bool, const QString&, int)), - editor_window, - SLOT (handle_update_breakpoint_marker_request (bool, const QString&, int))); - - connect (_octave_qt_link, SIGNAL (edit_file_signal (const QString&)), editor_window, SLOT (handle_edit_file_request (const QString&))); connect (_octave_qt_link, SIGNAL (insert_debugger_pointer_signal (const QString&, int)), - editor_window, + this, SLOT (handle_insert_debugger_pointer_request (const QString&, int))); connect (_octave_qt_link, SIGNAL (delete_debugger_pointer_signal (const QString&, int)), - editor_window, + this, SLOT (handle_delete_debugger_pointer_request (const QString&, int))); + connect (_octave_qt_link, + SIGNAL (update_breakpoint_marker_signal (bool, const QString&, int)), + this, + SLOT (handle_update_breakpoint_marker_request (bool, const QString&, int))); + connect (_workspace_model, SIGNAL (rename_variable (const QString&, const QString&)), this, @@ -831,8 +932,6 @@ construct_debug_menu (menu_bar); - construct_desktop_menu (menu_bar); - construct_window_menu (menu_bar); construct_help_menu (menu_bar); @@ -855,16 +954,10 @@ file_menu->addMenu (editor_window->get_mru_menu ()); #endif - QAction *close_command_window_action - = file_menu->addAction (tr ("Close Command Window")); - close_command_window_action->setShortcut (QKeySequence::Close); - close_command_window_action->setEnabled (false); // TODO: Make this work. - file_menu->addSeparator (); - QAction *import_data_action - = file_menu->addAction (tr ("Import Data")); - import_data_action->setEnabled (false); // TODO: Make this work. + QAction *load_workspace_action + = file_menu->addAction (tr ("Load workspace")); QAction *save_workspace_action = file_menu->addAction (tr ("Save Workspace As")); @@ -877,21 +970,6 @@ file_menu->addSeparator (); - QAction *page_setup_action - = file_menu->addAction (tr ("Page Setup...")); - page_setup_action->setEnabled (false); // TODO: Make this work. - - QAction *print_action - = file_menu->addAction (tr ("Print")); - print_action->setShortcut (QKeySequence::Print); - print_action->setEnabled (false); // TODO: Make this work. - - QAction *print_selection_action - = file_menu->addAction (tr ("Print Selection...")); - print_selection_action->setEnabled (false); // TODO: Make this work. - - file_menu->addSeparator (); - QAction *exit_action = file_menu->addAction (tr ("Exit")); exit_action->setShortcut (QKeySequence::Quit); @@ -901,6 +979,9 @@ connect (_open_action, SIGNAL (triggered ()), editor_window, SLOT (request_open_file ())); + connect (load_workspace_action, SIGNAL (triggered ()), + this, SLOT (handle_load_workspace_request ())); + connect (save_workspace_action, SIGNAL (triggered ()), this, SLOT (handle_save_workspace_request ())); @@ -914,33 +995,29 @@ QMenu *new_menu = p->addMenu (tr ("New")); _new_script_action - = new_menu->addAction (QIcon (":/actions/icons/filenew.png"), tr ("Script")); - _new_script_action->setShortcut (QKeySequence::New); - _new_script_action->setShortcutContext (Qt::ApplicationShortcut); + = new_menu->addAction (QIcon (":/actions/icons/filenew.png"), + tr ("Script")); QAction *new_function_action = new_menu->addAction (tr ("Function")); - new_function_action->setEnabled (false); // TODO: Make this work. - - QAction *new_class_action = new_menu->addAction (tr ("Class")); - new_class_action->setEnabled (false); // TODO: Make this work. - - QAction *new_enumeration_action = new_menu->addAction (tr ("Enumeration")); - new_enumeration_action->setEnabled (false); // TODO: Make this work. + new_function_action->setEnabled (true); QAction *new_figure_action = new_menu->addAction (tr ("Figure")); - new_figure_action->setEnabled (false); // TODO: Make this work. + new_figure_action->setEnabled (true); QAction *new_variable_action = new_menu->addAction (tr ("Variable")); - new_variable_action->setEnabled (false); // TODO: Make this work. - - QAction *new_model_action = new_menu->addAction (tr ("Model")); - new_model_action->setEnabled (false); // TODO: Make this work. - - QAction *new_gui_action = new_menu->addAction (tr ("GUI")); - new_gui_action->setEnabled (false); // TODO: Make this work. + new_variable_action->setEnabled (true); connect (_new_script_action, SIGNAL (triggered ()), - editor_window, SLOT (request_new_file ())); + editor_window, SLOT (request_new_script ())); + + connect (new_function_action, SIGNAL (triggered ()), + editor_window, SLOT (request_new_function ())); + + connect (new_figure_action, SIGNAL (triggered ()), + this, SLOT (handle_new_figure_request ())); + + connect (new_variable_action, SIGNAL (triggered ()), + this, SLOT (handle_new_variable_request ())); } void @@ -968,12 +1045,6 @@ = edit_menu->addAction (QIcon (":/actions/icons/editpaste.png"), tr ("Paste")); _paste_action->setShortcut (ctrl_shift + Qt::Key_V); - QAction *paste_to_workspace_action - = edit_menu->addAction (tr ("Paste To Workspace...")); - paste_to_workspace_action->setEnabled (false); // TODO: Make this work. - - edit_menu->addSeparator (); - QAction *select_all_action = edit_menu->addAction (tr ("Select All")); select_all_action->setEnabled (false); // TODO: Make this work. @@ -985,10 +1056,6 @@ edit_menu->addSeparator (); - QAction *find_action - = edit_menu->addAction (tr ("Find...")); - find_action->setEnabled (false); // TODO: Make this work. - QAction *find_files_action = edit_menu->addAction (tr ("Find Files...")); find_files_action->setShortcut (ctrl_shift + Qt::Key_F); @@ -1084,17 +1151,6 @@ this, SLOT (debug_quit ())); } -void -main_window::construct_desktop_menu (QMenuBar *p) -{ - QMenu *desktop_menu = p->addMenu (tr ("&Desktop")); - - QAction *load_workspace_action = desktop_menu->addAction (tr ("Load workspace")); - - connect (load_workspace_action, SIGNAL (triggered ()), - this, SLOT (handle_load_workspace_request ())); -} - QAction * main_window::construct_window_menu_item (QMenu *p, const QString& item, bool checkable, @@ -1158,9 +1214,7 @@ window_menu->addSeparator (); QAction *reset_windows_action - = window_menu->addAction (tr ("Reset Windows")); - - reset_windows_action->setEnabled (false); // TODO: Make this work. + = window_menu->addAction (tr ("Reset Default Window Layout")); connect (show_command_window_action, SIGNAL (toggled (bool)), command_window, SLOT (setVisible (bool))); @@ -1390,6 +1444,28 @@ } void +main_window::execute_command_callback (const std::string& command) +{ + std::string pending_input = command_editor::get_current_line (); + + command_editor::set_initial_input (pending_input); + + command_editor::replace_line (command); + command_editor::redisplay (); + + // We are executing inside the command editor event loop. Force + // the current line to be returned for processing. + command_editor::interrupt (); +} + +void +main_window::new_figure_callback (void) +{ + Fbuiltin (ovl ("figure")); + Fdrawnow (); +} + +void main_window::change_directory_callback (const std::string& directory) { Fcd (ovl (directory)); diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/main-window.h --- a/libgui/src/main-window.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/main-window.h Mon Apr 29 19:13:40 2013 -0400 @@ -72,14 +72,20 @@ ~main_window (void); + bool command_window_has_focus (void) const; + void focus_command_window (void); signals: void settings_changed (const QSettings *); - void relay_command_signal (const QString&); void new_file_signal (const QString&); void open_file_signal (const QString&); + void insert_debugger_pointer_signal (const QString& file, int line); + void delete_debugger_pointer_signal (const QString& file, int line); + void update_breakpoint_marker_signal (bool insert, const QString& file, + int line); + public slots: void report_status_message (const QString& statusMessage); void handle_save_workspace_request (void); @@ -109,7 +115,11 @@ void change_directory_up (void); void accept_directory_line_edit (void); - void handle_command_double_clicked (const QString& command); + void execute_command_in_terminal(const QString& dir); + + void handle_new_figure_request (void); + + void handle_new_variable_request (void); void handle_enter_debugger (void); void handle_exit_debugger (void); @@ -119,7 +129,13 @@ void debug_step_out (void); void debug_quit (void); + void handle_insert_debugger_pointer_request (const QString& file, int line); + void handle_delete_debugger_pointer_request (const QString& file, int line); + void handle_update_breakpoint_marker_request (bool insert, + const QString& file, int line); + void read_settings (void); + void set_window_layout (QSettings *settings); void write_settings (void); void connect_visibility_changed (void); @@ -142,9 +158,11 @@ const QFloatList&, const QFloatList&, const QStringList&); - void handle_create_debug_cd_or_addpath_dialog (const QString& file, - const QString& dir, - bool addpath_option); + void handle_create_filedialog (const QStringList &filters, + const QString& title, const QString& filename, + const QString &dirname, + const QString& multimode); + // find files dialog void find_files(const QString &startdir=QDir::currentPath()); void find_files_finished(int); @@ -167,7 +185,6 @@ const QString& item, const QKeySequence& key); void construct_debug_menu (QMenuBar *p); - void construct_desktop_menu (QMenuBar *p); QAction *construct_window_menu_item (QMenu *p, const QString& item, bool checkable, const QKeySequence& key); @@ -195,6 +212,10 @@ void clear_history_callback (void); + void execute_command_callback (const std::string& command); + + void new_figure_callback (void); + void change_directory_callback (const std::string& directory); void debug_continue_callback (void); diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/octave-qt-link.cc --- a/libgui/src/octave-qt-link.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/octave-qt-link.cc Mon Apr 29 19:13:40 2013 -0400 @@ -111,7 +111,7 @@ uiwidget_creator.wait (); // The GUI has sent a signal and the process has been awakened. - return uiwidget_creator.get_dialog_button ()->toStdString (); + return uiwidget_creator.get_dialog_button().toStdString (); } static QStringList @@ -128,6 +128,39 @@ return retval; } +static QStringList +make_filter_list (const octave_link::filter_list& lst) +{ + QStringList retval; + + // We have pairs of data, first being the list of extensions + // exta;exb;extc etc second the name to use as filter name + // (optional). Qt wants a a list of filters in the format of + // 'FilterName (space separated exts)'. + + for (octave_link::filter_list::const_iterator it = lst.begin (); + it != lst.end (); it++) + { + QString ext = QString::fromStdString (it->first); + QString name = QString::fromStdString (it->second); + + // Strip out extensions from name and replace ';' with spaces in + // list. + + name.replace (QRegExp ("\\(.*\\)"), ""); + ext.replace (";", " "); + + if (name.length() == 0) + { + // No name field. Build one from the extensions. + name = ext.toUpper() + " Files"; + } + + retval.append (name + " (" + ext + ")"); + } + + return retval; +} std::pair, int> octave_qt_link::do_list_dialog (const std::list& list, @@ -188,18 +221,83 @@ return retval; } +std::list +octave_qt_link::do_file_dialog (const filter_list& filter, + const std::string& title, + const std::string& filename, + const std::string& dirname, + const std::string& multimode) +{ + std::list retval; + + uiwidget_creator.signal_filedialog (make_filter_list (filter), + QString::fromStdString (title), + QString::fromStdString (filename), + QString::fromStdString (dirname), + QString::fromStdString (multimode)); + + // Wait while the user is responding to dialog. + uiwidget_creator.wait (); + + // Add all the file dialog results to a string list. + const QStringList *inputLine = uiwidget_creator.get_string_list (); + + for (QStringList::const_iterator it = inputLine->begin (); + it != inputLine->end (); it++) + retval.push_back (it->toStdString ()); + + retval.push_back (uiwidget_creator.get_dialog_path ()->toStdString ()); + retval.push_back ((QString ("%1").arg (uiwidget_creator.get_dialog_result ())).toStdString ()); + + return retval; +} + int octave_qt_link::do_debug_cd_or_addpath_error (const std::string& file, const std::string& dir, bool addpath_option) { - uiwidget_creator.signal_debug_cd_or_addpath (QString::fromStdString (file), - QString::fromStdString (dir), - addpath_option); + int retval = -1; + + QString qdir = QString::fromStdString (dir); + QString qfile = QString::fromStdString (file); + + QString msg + = (addpath_option + ? tr ("The file %1 does not exist in the load path. To debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.").arg(qfile).arg(qdir) + : tr ("The file %1 is shadowed by a file with the same name in the load path. To debug the function you are editing, change to the directory %2.").arg(qfile).arg(qdir)); + + QString title = tr ("Change Directory or Add Directory to Load Path"); + + QString cd_txt = tr ("Change Directory"); + QString addpath_txt = tr ("Add Directory to Load Path"); + QString cancel_txt = tr ("Cancel"); + QStringList btn; + QStringList role; + btn << cd_txt; + role << "AcceptRole"; + if (addpath_option) + { + btn << addpath_txt; + role << "AcceptRole"; + } + btn << cancel_txt; + role << "AcceptRole"; + + uiwidget_creator.signal_dialog (msg, title, "quest", btn, cancel_txt, role); + + // Wait while the user is responding to message box. uiwidget_creator.wait (); - return uiwidget_creator.get_dialog_result (); + QString result = uiwidget_creator.get_dialog_button (); + + if (result == cd_txt) + retval = 1; + else if (result == addpath_txt) + retval = 2; + + return retval; } void @@ -209,6 +307,12 @@ } void +octave_qt_link::do_execute_command_in_terminal (const std::string& command) +{ + emit execute_command_in_terminal_signal (QString::fromStdString (command)); +} + +void octave_qt_link::do_set_workspace (bool top_level, const std::list& ws) { diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/octave-qt-link.h --- a/libgui/src/octave-qt-link.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/octave-qt-link.h Mon Apr 29 19:13:40 2013 -0400 @@ -84,6 +84,11 @@ const std::list& nc, const std::list& defaults); + std::list + do_file_dialog (const filter_list& filter, const std::string& title, + const std::string &filename, const std::string &pathname, + const std::string& multimode); + int do_debug_cd_or_addpath_error (const std::string& file, const std::string& dir, @@ -91,6 +96,8 @@ void do_change_directory (const std::string& dir); + void do_execute_command_in_terminal (const std::string& command); + void do_set_workspace (bool top_level, const std::list& ws); @@ -112,6 +119,7 @@ void do_set_default_prompts (std::string& ps1, std::string& ps2, std::string& ps4); + private: // No copying! @@ -134,6 +142,8 @@ void change_directory_signal (const QString& dir); + void execute_command_in_terminal_signal (const QString& command); + void set_workspace_signal (bool top_level, const QString& scopes, const QStringList& symbols, diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/resource-manager.cc --- a/libgui/src/resource-manager.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/resource-manager.cc Mon Apr 29 19:13:40 2013 -0400 @@ -42,15 +42,30 @@ resource_manager *resource_manager::instance = 0; +static QString +default_qt_settings_file (void) +{ + std::string dsf = octave_env::getenv ("OCTAVE_DEFAULT_QT_SETTINGS"); + + if (dsf.empty ()) + dsf = Voct_etc_dir + file_ops::dir_sep_str () + "default-qt-settings"; + + return QString::fromStdString (dsf); +} + resource_manager::resource_manager (void) : settings (0), home_path (), first_run (false) { do_reload_settings (); + + default_settings = new QSettings (default_qt_settings_file (), + QSettings::IniFormat); } resource_manager::~resource_manager (void) { delete settings; + delete default_settings; } @@ -104,26 +119,21 @@ } QSettings * -resource_manager::do_get_settings (void) +resource_manager::do_get_settings (void) const { return settings; } -QString -resource_manager::do_get_home_path (void) +QSettings * +resource_manager::do_get_default_settings (void) const { - return home_path; + return default_settings; } -static std::string -default_qt_settings_file (void) +QString +resource_manager::do_get_home_path (void) const { - std::string dsf = octave_env::getenv ("OCTAVE_DEFAULT_QT_SETTINGS"); - - if (dsf.empty ()) - dsf = Voct_etc_dir + file_ops::dir_sep_str () + "default-qt-settings"; - - return dsf; + return home_path; } void @@ -137,8 +147,7 @@ if (!QFile::exists (settings_file)) { QDir("/").mkpath (settings_path); - QFile::copy (QString::fromStdString (default_qt_settings_file ()), - settings_file); + QFile::copy (default_qt_settings_file (), settings_file); first_run = true; } else @@ -155,7 +164,7 @@ } bool -resource_manager::do_is_first_run (void) +resource_manager::do_is_first_run (void) const { return first_run; } diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/resource-manager.h --- a/libgui/src/resource-manager.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/resource-manager.h Mon Apr 29 19:13:40 2013 -0400 @@ -44,6 +44,11 @@ return instance_ok () ? instance->do_get_settings () : 0; } + static QSettings *get_default_settings (void) + { + return instance_ok () ? instance->do_get_default_settings () : 0; + } + static QString get_home_path (void) { return instance_ok () ? instance->do_get_home_path () : QString (); @@ -94,13 +99,17 @@ QSettings *settings; + QSettings *default_settings; + QString home_path; bool first_run; - QSettings *do_get_settings (void); + QSettings *do_get_settings (void) const; - QString do_get_home_path (void); + QSettings *do_get_default_settings (void) const; + + QString do_get_home_path (void) const; void do_reload_settings (void); @@ -108,7 +117,7 @@ void do_update_network_settings (void); - bool do_is_first_run (void); + bool do_is_first_run (void) const; }; diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/terminal-dock-widget.cc --- a/libgui/src/terminal-dock-widget.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/terminal-dock-widget.cc Mon Apr 29 19:13:40 2013 -0400 @@ -44,17 +44,11 @@ connect (this, SIGNAL (visibilityChanged (bool)), this, SLOT (handle_visibility (bool))); - connect (parent (), SIGNAL (relay_command_signal (const QString&)), - this, SLOT (relay_command (const QString&))); - // Forward signals to QTerminal widget. connect (this, SIGNAL (notice_settings_signal (const QSettings *)), terminal, SLOT (notice_settings (const QSettings *))); - connect (this, SIGNAL (relay_command_signal (const QString&)), - terminal, SLOT (relay_command (const QString&))); - connect (this, SIGNAL (copyClipboard_signal (void)), terminal, SLOT (copyClipboard (void))); @@ -62,6 +56,14 @@ terminal, SLOT (pasteClipboard (void))); } +bool +terminal_dock_widget::has_focus (void) const +{ + QWidget *w = widget (); + + return w->hasFocus (); +} + void terminal_dock_widget::notice_settings (const QSettings *settings) { @@ -69,12 +71,6 @@ } void -terminal_dock_widget::relay_command (const QString& command) -{ - emit relay_command_signal (command); -} - -void terminal_dock_widget::copyClipboard (void) { emit copyClipboard_signal (); diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/terminal-dock-widget.h --- a/libgui/src/terminal-dock-widget.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/terminal-dock-widget.h Mon Apr 29 19:13:40 2013 -0400 @@ -37,14 +37,14 @@ terminal_dock_widget (QWidget *parent = 0); + bool has_focus (void) const; + signals: public slots: void notice_settings (const QSettings *settings); - void relay_command (const QString& command); - void copyClipboard (void); void pasteClipboard (void); @@ -55,8 +55,6 @@ void notice_settings_signal (const QSettings *settings); - void relay_command_signal (const QString& command); - void copyClipboard_signal (void); void pasteClipboard_signal (void); diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/workspace-view.cc --- a/libgui/src/workspace-view.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/workspace-view.cc Mon Apr 29 19:13:40 2013 -0400 @@ -49,6 +49,7 @@ view->setWordWrap (false); view->setContextMenuPolicy (Qt::CustomContextMenu); + view_previous_row_count = 0; // Set an empty widget, so we can assign a layout to it. setWidget (new QWidget (this)); @@ -75,7 +76,7 @@ this, SLOT(contextmenu_requested (const QPoint&))); connect (this, SIGNAL (command_requested (const QString&)), - p, SLOT (handle_command_double_clicked (const QString&))); + p, SLOT (execute_command_in_terminal (const QString&))); } workspace_view::~workspace_view (void) @@ -96,11 +97,11 @@ } void -workspace_view::contextmenu_requested (const QPoint& pos) +workspace_view::contextmenu_requested (const QPoint& qpos) { QMenu menu (this); - QModelIndex index = view->indexAt (pos); + QModelIndex index = view->indexAt (qpos); QAbstractItemModel *m = view->model (); // if it isnt Local, Glocal etc, allow the ctx menu @@ -137,7 +138,7 @@ menu.addAction ("stem(" + var_name + ")", this, SLOT (handle_contextmenu_stem ())); - menu.exec (view->mapToGlobal (pos)); + menu.exec (view->mapToGlobal (qpos)); } } @@ -195,19 +196,19 @@ void workspace_view::handle_contextmenu_disp (void) { - relay_contextmenu_command ("disp"); + relay_contextmenu_command ("disp"); } void workspace_view::handle_contextmenu_plot (void) { - relay_contextmenu_command ("figure;\nplot"); + relay_contextmenu_command ("figure (); plot"); } void workspace_view::handle_contextmenu_stem (void) { - relay_contextmenu_command ("figure;\nstem"); + relay_contextmenu_command ("figure (); stem"); } void @@ -225,6 +226,19 @@ QString var_name = item_data[0].toString (); - emit command_requested (cmdname + "(" + var_name + ")\n"); + emit command_requested (cmdname + " (" + var_name + ");"); } } + +void +workspace_view::handle_model_changed (void) +{ + // Just modify those rows that have been added rather than go through + // the whole list. For-loop test will handle when number of rows reduced. + QFontMetrics fm = view->fontMetrics (); + int row_height = fm.height (); + int new_row_count = view->model ()->rowCount (); + for (int i = view_previous_row_count; i < new_row_count; i++) + view->setRowHeight (i, row_height); + view_previous_row_count = new_row_count; +} diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libgui/src/workspace-view.h --- a/libgui/src/workspace-view.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libgui/src/workspace-view.h Mon Apr 29 19:13:40 2013 -0400 @@ -65,11 +65,14 @@ void handle_contextmenu_plot (void); void handle_contextmenu_stem (void); + void handle_model_changed (void); + private: void relay_contextmenu_command (const QString& cmdname); QTableView *view; + int view_previous_row_count; }; #endif diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/corefcn/ellipj.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/ellipj.cc Mon Apr 29 19:13:40 2013 -0400 @@ -0,0 +1,946 @@ +/* + +Copyright (C) 2001 Leopoldo Cerbaro + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "defun.h" +#include "error.h" +#include "lo-ieee.h" + +static void +gripe_ellipj_arg (const char *arg) +{ + error ("ellipj: expecting scalar or matrix as %s argument", arg); +} + +static void +sncndn (double u, double m, double& sn, double& cn, double& dn, double& err) +{ + static const int Nmax = 16; + double m1, t=0, si_u, co_u, se_u, ta_u, b, c[Nmax], a[Nmax], phi; + int n, Nn, ii; + + if (m < 0 || m > 1) + { + warning ("ellipj: expecting 0 <= m <= 1"); /* -lc- */ + sn = cn = dn = lo_ieee_nan_value (); + return; + } + + double sqrt_eps = sqrt (std::numeric_limits::epsilon ()); + if (m < sqrt_eps) + { + /* # For small m, ( Abramowitz and Stegun, Section 16.13 ) */ + si_u = sin (u); + co_u = cos (u); + t = 0.25*m*(u - si_u*co_u); + sn = si_u - t * co_u; + cn = co_u + t * si_u; + dn = 1 - 0.5*m*si_u*si_u; + } + else if ((1 - m) < sqrt_eps) + { + /* For m1 = (1-m) small ( Abramowitz and Stegun, Section 16.15 ) */ + m1 = 1 - m; + si_u = sinh (u); + co_u = cosh (u); + ta_u = tanh (u); + se_u = 1/co_u; + sn = ta_u + 0.25*m1*(si_u*co_u - u)*se_u*se_u; + cn = se_u - 0.25*m1*(si_u*co_u - u)*ta_u*se_u; + dn = se_u + 0.25*m1*(si_u*co_u + u)*ta_u*se_u; + } + else + { + /* + // Arithmetic-Geometric Mean (AGM) algorithm + // ( Abramowitz and Stegun, Section 16.4 ) + */ + + a[0] = 1; + b = sqrt (1 - m); + c[0] = sqrt (m); + for (n = 1; n < Nmax; ++n) + { + a[n] = (a[n - 1] + b)/2; + c[n] = (a[n - 1] - b)/2; + b = sqrt (a[n - 1]*b); + if (c[n]/a[n] < std::numeric_limits::epsilon ()) break; + } + if (n >= Nmax - 1) + { + err = 1; + return; + } + Nn = n; + for (ii = 1; n > 0; ii = ii*2, --n) ; // ii = pow(2,Nn) + phi = ii*a[Nn]*u; + for (n = Nn; n > 0; --n) + { + t = phi; + phi = (asin ((c[n]/a[n])* sin (phi)) + phi)/2; + } + sn = sin (phi); + cn = cos (phi); + dn = cn/cos (t - phi); + } +} + +static void +sncndn (Complex& u, double m, Complex& sn, Complex& cn, Complex& dn, + double& err) +{ + double m1 = 1 - m, ss1, cc1, dd1; + + sncndn (imag (u), m1, ss1, cc1, dd1, err); + if (real (u) == 0) + { + /* u is pure imag: Jacoby imag. transf. */ + sn = Complex (0, ss1/cc1); + cn = 1/cc1; // cn.imag = 0; + dn = dd1/cc1; // dn.imag = 0; + } + else + { + /* u is generic complex */ + double ss, cc, dd, ddd; + + sncndn (real (u), m, ss, cc, dd, err); + ddd = cc1*cc1 + m*ss*ss*ss1*ss1; + sn = Complex (ss*dd1/ddd, cc*dd*ss1*cc1/ddd); + cn = Complex (cc*cc1/ddd, -ss*dd*ss1*dd1/ddd); + dn = Complex (dd*cc1*dd1/ddd, -m*ss*cc*ss1/ddd); + } +} + +DEFUN (ellipj, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {[@var{sn}, @var{cn}, @var{dn}, @var{err}] =} ellipj (@var{u}, @var{m})\n\ +@deftypefnx {Built-in Function} {[@var{sn}, @var{cn}, @var{dn}, @var{err}] =} ellipj (@var{u}, @var{m}, @var{tol})\n\ +Compute the Jacobi elliptic functions @var{sn}, @var{cn}, and @var{dn}\n\ +of complex argument @var{u} and real parameter @var{m}.\n\ +\n\ +If @var{m} is a scalar, the results are the same size as @var{u}.\n\ +If @var{u} is a scalar, the results are the same size as @var{m}.\n\ +If @var{u} is a column vector and @var{m} is a row vector, the\n\ +results are matrices with @code{length (@var{u})} rows and\n\ +@code{length (@var{m})} columns. Otherwise, @var{u} and\n\ +@var{m} must conform and the results will be the same size.\n\ +\n\ +The value of @var{u} may be complex.\n\ +The value of @var{m} must be 0 <= m <= 1.\n\ +\n\ +@var{tol} is currently ignored (@sc{Matlab} uses this to allow faster,\n\ +less accurate approximation).\n\ +\n\ +If requested, @var{err} contains the following status information\n\ +and is the same size as the result.\n\ +\n\ +@enumerate 0\n\ +@item\n\ +Normal return.\n\ +@item\n\ +Error---no computation, algorithm termination condition not met,\n\ +return @code{NaN}.\n\ +@end enumerate\n\ + Ref: Abramowitz, Milton and Stegun, Irene A\n\ + Handbook of Mathematical Functions, Dover, 1965\n\ + Chapter 16 (Sections 16.4, 16.13 and 16.15)\n\ +@seealso{ellipke}\n\ +@end deftypefn") +{ + octave_value_list retval; + + int nargin = args.length (); + + if (nargin < 2 || nargin > 3) + { + print_usage (); + return retval; + } + + octave_value u_arg = args(0); + octave_value m_arg = args(1); + + if (m_arg.is_scalar_type ()) + { + double m = args(1).double_value (); + + if (error_state) + { + gripe_ellipj_arg ("second"); + return retval; + } + + if (u_arg.is_scalar_type ()) + { + if (u_arg.is_real_type ()) + { // u real + double u = args(0).double_value (); + + if (error_state) + { + gripe_ellipj_arg ("first"); + return retval; + } + double sn, cn, dn; + double err = 0; + + sncndn (u, m, sn, cn, dn, err); + retval (0) = sn; + retval (1) = cn; + retval (2) = dn; + if (nargout > 3) retval(3) = err; + } + else + { // u complex + Complex u = u_arg.complex_value (); + + if (error_state) + { + gripe_ellipj_arg ("second"); + return retval; + } + + Complex sn, cn, dn; + double err; + + sncndn (u, m, sn, cn, dn, err); + + retval (0) = sn; + retval (1) = cn; + retval (2) = dn; + if (nargout > 3) retval(3) = err; + } + } + else + { /* u is matrix ( m is scalar ) */ + ComplexMatrix u = u_arg.complex_matrix_value (); + + if (error_state) + { + gripe_ellipj_arg ("first"); + return retval; + } + + octave_idx_type nr = u.rows (); + octave_idx_type nc = u.cols (); + + ComplexMatrix sn (nr, nc), cn (nr, nc), dn (nr, nc); + Matrix err (nr, nc); + + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + sncndn (u(i,j), m, sn(i,j), cn(i,j), dn(i,j), err(i,j)); + + retval (0) = sn; + retval (1) = cn; + retval (2) = dn; + if (nargout > 3) retval(3) = err; + } + } + else + { + Matrix m = args(1).matrix_value (); + + if (error_state) + { + gripe_ellipj_arg ("second"); + return retval; + } + + octave_idx_type mr = m.rows (); + octave_idx_type mc = m.cols (); + + if (u_arg.is_scalar_type ()) + { /* u is scalar */ + octave_idx_type nr = m.rows (); + octave_idx_type nc = m.cols (); + Matrix err (nr, nc); + + if (u_arg.is_real_type ()) + { + double u = u_arg.double_value (); + + if (error_state) + { + gripe_ellipj_arg ("first"); + return retval; + } + + Matrix sn (nr, nc), cn (nr, nc), dn (nr, nc); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + sncndn (u, m(i,j), sn(i,j), cn(i,j), dn(i,j), err(i,j)); + + retval (0) = sn; + retval (1) = cn; + retval (2) = dn; + if (nargout > 3) retval(3) = err; + } + else + { + Complex u = u_arg.complex_value (); + if (error_state) + { + gripe_ellipj_arg ("first"); + return retval; + } + + ComplexMatrix sn (nr, nc), cn (nr, nc), dn (nr, nc); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + sncndn (u, m(i,j), sn(i,j), cn(i,j), dn(i,j), err(i,j)); + retval (0) = sn; + retval (1) = cn; + retval (2) = dn; + if (nargout > 3) retval(3) = err; + } + } + else + { // u is matrix (m is matrix) + if (u_arg.is_real_type ()) + { // u real matrix + + Matrix u = u_arg.matrix_value (); + if (error_state) + { + gripe_ellipj_arg ("first "); + return retval; + } + + octave_idx_type ur = u.rows (); + octave_idx_type uc = u.cols (); + + if (mr == 1 && uc == 1) + { // u column, m row + RowVector rm = m.row (0); + ColumnVector cu = u.column (0); + + Matrix sn (ur, mc), cn (ur, mc), dn (ur, mc); + Matrix err (ur,mc); + + for (octave_idx_type j = 0; j < mc; j++) + for (octave_idx_type i = 0; i < ur; i++) + sncndn (cu(i), rm(j), sn(i,j), cn(i,j), dn(i,j), err(i,j)); + + retval (0) = sn; + retval (1) = cn; + retval (2) = dn; + if (nargout > 3) retval(3) = err; + } + else if (ur == mr && uc == mc) + { + Matrix sn (ur, mc), cn (ur, mc), dn (ur, mc); + Matrix err (ur,mc); + + for (octave_idx_type j = 0; j < uc; j++) + for (octave_idx_type i = 0; i < ur; i++) + sncndn (u(i,j), m(i,j), sn(i,j), cn(i,j), dn(i,j), err(i,j)); + + retval (0) = sn; + retval (1) = cn; + retval (2) = dn; + if (nargout > 3) retval(3) = err; + } + else + error ("u m invalid"); + } + else + { // u complex matrix + ComplexMatrix u = u_arg.complex_matrix_value (); + if (error_state) + { + gripe_ellipj_arg ("second"); + return retval; + } + + octave_idx_type ur = u.rows (); + octave_idx_type uc = u.cols (); + + if (mr == 1 && uc == 1) + { + RowVector rm = m.row (0); + ComplexColumnVector cu = u.column (0); + + ComplexMatrix sn (ur, mc), cn (ur, mc), dn (ur, mc); + Matrix err (ur,mc); + + for (octave_idx_type j = 0; j < mc; j++) + for (octave_idx_type i = 0; i < ur; i++) + sncndn (cu(i), rm(j), sn(i,j), cn(i,j), dn(i,j), err(i,j)); + + retval (0) = sn; + retval (1) = cn; + retval (2) = dn; + if (nargout > 3) retval(3) = err; + } + else if (ur == mr && uc == mc) + { + ComplexMatrix sn (ur, mc), cn (ur, mc), dn (ur, mc); + Matrix err (ur,mc); + + for (octave_idx_type j = 0; j < uc; j++) + for (octave_idx_type i = 0; i < ur; i++) + sncndn (u(i,j), m(i,j), sn(i,j), cn(i,j), dn(i,j), err(i,j)); + + retval (0) = sn; + retval (1) = cn; + retval (2) = dn; + if (nargout > 3) retval(3) = err; + } + else + error ("u m invalid"); + } + } + } // m matrix + + return retval; +} + +/* +## demos taken from inst/ellipj.m + +%!demo +%! N = 150; +%! % m = [1-logspace(0,log(eps),N-1), 1]; ## m near 1 +%! % m = [0, logspace(log(eps),0,N-1)]; ## m near 0 +%! m = linspace(0,1,N); ## m equally spaced +%! u = linspace(-20,20,N); +%! M = ones(length(u),1) * m; +%! U = u' * ones(1, length(m)); +%! [sn, cn, dn] = ellipj(U,M); +%! +%! %% Plotting +%! c = colormap(hot(64)); +%! data = {sn,cn,dn}; +%! dname = {"sn","cn","dn"}; +%! for i=1:3 +%! subplot(1,3,i); +%! data{i}(data{i} > 1) = 1; +%! data{i}(data{i} < -1) = -1; +%! image(m,u,32*data{i}+32); +%! title(dname{i}); +%! end +%! colormap(c); + +%!demo +%! N = 200; +%! % m = [1-logspace(0,log(eps),N-1), 1]; ## m near 1 +%! % m = [0, logspace(log(eps),0,N-1)]; ## m near 0 +%! m = linspace(0,1,N); ## m equally spaced +%! u = linspace(0,20,5); +%! M = ones(length(u),1) * m; +%! U = u' * ones(1, length(m)); +%! [sn, cn, dn] = ellipj(U,M); +%! +%! %% Plotting +%! data = {sn,cn,dn}; +%! dname = {"sn","cn","dn"}; +%! for i=1:3 +%! subplot(1,3,i); +%! plot(m, data{i}); +%! title(dname{i}); +%! grid on; +%! end +*/ + +/* +## tests taken from inst/test_sncndn.m + +%!test +%! k = (tan(pi/8.))^2; m = k*k; +%! SN = [ +%! -1. + I * 0. , -0.8392965923 + 0. * I +%! -1. + I * 0.2 , -0.8559363407 + 0.108250955 * I +%! -1. + I * 0.4 , -0.906529758 + 0.2204040232 * I +%! -1. + I * 0.6 , -0.9931306727 + 0.3403783409 * I +%! -1. + I * 0.8 , -1.119268095 + 0.4720784944 * I +%! -1. + I * 1. , -1.29010951 + 0.6192468708 * I +%! -1. + I * 1.2 , -1.512691987 + 0.7850890595 * I +%! -1. + I * 1.4 , -1.796200374 + 0.9714821804 * I +%! -1. + I * 1.6 , -2.152201882 + 1.177446413 * I +%! -1. + I * 1.8 , -2.594547417 + 1.396378892 * I +%! -1. + I * 2. , -3.138145339 + 1.611394819 * I +%! -0.8 + I * 0. , -0.7158157937 + 0. * I +%! -0.8 + I * 0.2 , -0.7301746722 + 0.1394690862 * I +%! -0.8 + I * 0.4 , -0.7738940898 + 0.2841710966 * I +%! -0.8 + I * 0.6 , -0.8489542135 + 0.4394411376 * I +%! -0.8 + I * 0.8 , -0.9588386397 + 0.6107824358 * I +%! -0.8 + I * 1. , -1.108848724 + 0.8038415767 * I +%! -0.8 + I * 1.2 , -1.306629972 + 1.024193359 * I +%! -0.8 + I * 1.4 , -1.563010199 + 1.276740951 * I +%! -0.8 + I * 1.6 , -1.893274688 + 1.564345558 * I +%! -0.8 + I * 1.8 , -2.318944084 + 1.88491973 * I +%! -0.8 + I * 2. , -2.869716809 + 2.225506523 * I +%! -0.6 + I * 0. , -0.5638287208 + 0. * I +%! -0.6 + I * 0.2 , -0.5752723012 + 0.1654722474 * I +%! -0.6 + I * 0.4 , -0.610164314 + 0.3374004736 * I +%! -0.6 + I * 0.6 , -0.6702507087 + 0.5224614298 * I +%! -0.6 + I * 0.8 , -0.7586657365 + 0.7277663879 * I +%! -0.6 + I * 1. , -0.8803349115 + 0.9610513652 * I +%! -0.6 + I * 1.2 , -1.042696526 + 1.230800819 * I +%! -0.6 + I * 1.4 , -1.256964505 + 1.546195843 * I +%! -0.6 + I * 1.6 , -1.540333527 + 1.916612621 * I +%! -0.6 + I * 1.8 , -1.919816065 + 2.349972151 * I +%! -0.6 + I * 2. , -2.438761841 + 2.848129496 * I +%! -0.4 + I * 0. , -0.3891382858 + 0. * I +%! -0.4 + I * 0.2 , -0.3971152026 + 0.1850563793 * I +%! -0.4 + I * 0.4 , -0.4214662882 + 0.3775700801 * I +%! -0.4 + I * 0.6 , -0.4635087491 + 0.5853434119 * I +%! -0.4 + I * 0.8 , -0.5256432877 + 0.8168992398 * I +%! -0.4 + I * 1. , -0.611733177 + 1.081923504 * I +%! -0.4 + I * 1.2 , -0.7278102331 + 1.391822501 * I +%! -0.4 + I * 1.4 , -0.8833807998 + 1.760456461 * I +%! -0.4 + I * 1.6 , -1.093891878 + 2.205107766 * I +%! -0.4 + I * 1.8 , -1.385545188 + 2.747638761 * I +%! -0.4 + I * 2. , -1.805081271 + 3.41525351 * I +%! -0.2 + I * 0. , -0.1986311721 + 0. * I +%! -0.2 + I * 0.2 , -0.2027299916 + 0.1972398665 * I +%! -0.2 + I * 0.4 , -0.2152524522 + 0.402598347 * I +%! -0.2 + I * 0.6 , -0.2369100139 + 0.6246336356 * I +%! -0.2 + I * 0.8 , -0.2690115146 + 0.8728455227 * I +%! -0.2 + I * 1. , -0.3136938773 + 1.158323088 * I +%! -0.2 + I * 1.2 , -0.3743615191 + 1.494672508 * I +%! -0.2 + I * 1.4 , -0.4565255082 + 1.899466033 * I +%! -0.2 + I * 1.6 , -0.5694611346 + 2.39667232 * I +%! -0.2 + I * 1.8 , -0.7296612675 + 3.020990664 * I +%! -0.2 + I * 2. , -0.9685726188 + 3.826022536 * I +%! 0. + I * 0. , 0. + 0. * I +%! 0. + I * 0.2 , 0. + 0.201376364 * I +%! 0. + I * 0.4 , 0. + 0.4111029248 * I +%! 0. + I * 0.6 , 0. + 0.6380048435 * I +%! 0. + I * 0.8 , 0. + 0.8919321473 * I +%! 0. + I * 1. , 0. + 1.184486615 * I +%! 0. + I * 1.2 , 0. + 1.530096023 * I +%! 0. + I * 1.4 , 0. + 1.947754612 * I +%! 0. + I * 1.6 , 0. + 2.464074356 * I +%! 0. + I * 1.8 , 0. + 3.119049475 * I +%! 0. + I * 2. , 0. + 3.97786237 * I +%! 0.2 + I * 0. , 0.1986311721 + 0. * I +%! 0.2 + I * 0.2 , 0.2027299916 + 0.1972398665 * I +%! 0.2 + I * 0.4 , 0.2152524522 + 0.402598347 * I +%! 0.2 + I * 0.6 , 0.2369100139 + 0.6246336356 * I +%! 0.2 + I * 0.8 , 0.2690115146 + 0.8728455227 * I +%! 0.2 + I * 1. , 0.3136938773 + 1.158323088 * I +%! 0.2 + I * 1.2 , 0.3743615191 + 1.494672508 * I +%! 0.2 + I * 1.4 , 0.4565255082 + 1.899466033 * I +%! 0.2 + I * 1.6 , 0.5694611346 + 2.39667232 * I +%! 0.2 + I * 1.8 , 0.7296612675 + 3.020990664 * I +%! 0.2 + I * 2. , 0.9685726188 + 3.826022536 * I +%! 0.4 + I * 0. , 0.3891382858 + 0. * I +%! 0.4 + I * 0.2 , 0.3971152026 + 0.1850563793 * I +%! 0.4 + I * 0.4 , 0.4214662882 + 0.3775700801 * I +%! 0.4 + I * 0.6 , 0.4635087491 + 0.5853434119 * I +%! 0.4 + I * 0.8 , 0.5256432877 + 0.8168992398 * I +%! 0.4 + I * 1. , 0.611733177 + 1.081923504 * I +%! 0.4 + I * 1.2 , 0.7278102331 + 1.391822501 * I +%! 0.4 + I * 1.4 , 0.8833807998 + 1.760456461 * I +%! 0.4 + I * 1.6 , 1.093891878 + 2.205107766 * I +%! 0.4 + I * 1.8 , 1.385545188 + 2.747638761 * I +%! 0.4 + I * 2. , 1.805081271 + 3.41525351 * I +%! 0.6 + I * 0. , 0.5638287208 + 0. * I +%! 0.6 + I * 0.2 , 0.5752723012 + 0.1654722474 * I +%! 0.6 + I * 0.4 , 0.610164314 + 0.3374004736 * I +%! 0.6 + I * 0.6 , 0.6702507087 + 0.5224614298 * I +%! 0.6 + I * 0.8 , 0.7586657365 + 0.7277663879 * I +%! 0.6 + I * 1. , 0.8803349115 + 0.9610513652 * I +%! 0.6 + I * 1.2 , 1.042696526 + 1.230800819 * I +%! 0.6 + I * 1.4 , 1.256964505 + 1.546195843 * I +%! 0.6 + I * 1.6 , 1.540333527 + 1.916612621 * I +%! 0.6 + I * 1.8 , 1.919816065 + 2.349972151 * I +%! 0.6 + I * 2. , 2.438761841 + 2.848129496 * I +%! 0.8 + I * 0. , 0.7158157937 + 0. * I +%! 0.8 + I * 0.2 , 0.7301746722 + 0.1394690862 * I +%! 0.8 + I * 0.4 , 0.7738940898 + 0.2841710966 * I +%! 0.8 + I * 0.6 , 0.8489542135 + 0.4394411376 * I +%! 0.8 + I * 0.8 , 0.9588386397 + 0.6107824358 * I +%! 0.8 + I * 1. , 1.108848724 + 0.8038415767 * I +%! 0.8 + I * 1.2 , 1.306629972 + 1.024193359 * I +%! 0.8 + I * 1.4 , 1.563010199 + 1.276740951 * I +%! 0.8 + I * 1.6 , 1.893274688 + 1.564345558 * I +%! 0.8 + I * 1.8 , 2.318944084 + 1.88491973 * I +%! 0.8 + I * 2. , 2.869716809 + 2.225506523 * I +%! 1. + I * 0. , 0.8392965923 + 0. * I +%! 1. + I * 0.2 , 0.8559363407 + 0.108250955 * I +%! 1. + I * 0.4 , 0.906529758 + 0.2204040232 * I +%! 1. + I * 0.6 , 0.9931306727 + 0.3403783409 * I +%! 1. + I * 0.8 , 1.119268095 + 0.4720784944 * I +%! 1. + I * 1. , 1.29010951 + 0.6192468708 * I +%! 1. + I * 1.2 , 1.512691987 + 0.7850890595 * I +%! 1. + I * 1.4 , 1.796200374 + 0.9714821804 * I +%! 1. + I * 1.6 , 2.152201882 + 1.177446413 * I +%! 1. + I * 1.8 , 2.594547417 + 1.396378892 * I +%! 1. + I * 2. , 3.138145339 + 1.611394819 * I +%! ]; +%! CN = [ +%! -1. + I * 0. , 0.5436738271 + 0. * I +%! -1. + I * 0.2 , 0.5541219664 + 0.1672121517 * I +%! -1. + I * 0.4 , 0.5857703552 + 0.3410940893 * I +%! -1. + I * 0.6 , 0.6395034233 + 0.5285979063 * I +%! -1. + I * 0.8 , 0.716688504 + 0.7372552987 * I +%! -1. + I * 1. , 0.8189576795 + 0.9755037374 * I +%! -1. + I * 1.2 , 0.9477661951 + 1.253049471 * I +%! -1. + I * 1.4 , 1.103540657 + 1.581252712 * I +%! -1. + I * 1.6 , 1.284098214 + 1.973449038 * I +%! -1. + I * 1.8 , 1.481835651 + 2.4449211 * I +%! -1. + I * 2. , 1.679032464 + 3.011729224 * I +%! -0.8 + I * 0. , 0.6982891589 + 0. * I +%! -0.8 + I * 0.2 , 0.71187169 + 0.1430549855 * I +%! -0.8 + I * 0.4 , 0.7530744458 + 0.2920273465 * I +%! -0.8 + I * 0.6 , 0.8232501212 + 0.4531616768 * I +%! -0.8 + I * 0.8 , 0.9245978896 + 0.6334016187 * I +%! -0.8 + I * 1. , 1.060030206 + 0.8408616109 * I +%! -0.8 + I * 1.2 , 1.232861756 + 1.085475913 * I +%! -0.8 + I * 1.4 , 1.446126965 + 1.379933558 * I +%! -0.8 + I * 1.6 , 1.701139468 + 1.741030588 * I +%! -0.8 + I * 1.8 , 1.994526268 + 2.191509596 * I +%! -0.8 + I * 2. , 2.312257188 + 2.762051518 * I +%! -0.6 + I * 0. , 0.8258917445 + 0. * I +%! -0.6 + I * 0.2 , 0.842151698 + 0.1130337928 * I +%! -0.6 + I * 0.4 , 0.8915487431 + 0.2309124769 * I +%! -0.6 + I * 0.6 , 0.975948103 + 0.3588102098 * I +%! -0.6 + I * 0.8 , 1.098499209 + 0.5026234141 * I +%! -0.6 + I * 1. , 1.263676101 + 0.6695125973 * I +%! -0.6 + I * 1.2 , 1.477275851 + 0.8687285705 * I +%! -0.6 + I * 1.4 , 1.746262523 + 1.112955966 * I +%! -0.6 + I * 1.6 , 2.078179075 + 1.420581466 * I +%! -0.6 + I * 1.8 , 2.479425208 + 1.819580713 * I +%! -0.6 + I * 2. , 2.950586798 + 2.354077344 * I +%! -0.4 + I * 0. , 0.9211793498 + 0. * I +%! -0.4 + I * 0.2 , 0.9395019377 + 0.07822091534 * I +%! -0.4 + I * 0.4 , 0.9952345231 + 0.1598950363 * I +%! -0.4 + I * 0.6 , 1.090715991 + 0.2487465067 * I +%! -0.4 + I * 0.8 , 1.229998843 + 0.34910407 * I +%! -0.4 + I * 1. , 1.419103868 + 0.4663848201 * I +%! -0.4 + I * 1.2 , 1.666426377 + 0.607877235 * I +%! -0.4 + I * 1.4 , 1.983347336 + 0.7841054404 * I +%! -0.4 + I * 1.6 , 2.385101684 + 1.01134031 * I +%! -0.4 + I * 1.8 , 2.89185416 + 1.316448705 * I +%! -0.4 + I * 2. , 3.529393374 + 1.74670531 * I +%! -0.2 + I * 0. , 0.9800743122 + 0. * I +%! -0.2 + I * 0.2 , 0.9997019476 + 0.03999835809 * I +%! -0.2 + I * 0.4 , 1.059453907 + 0.08179712295 * I +%! -0.2 + I * 0.6 , 1.16200643 + 0.1273503824 * I +%! -0.2 + I * 0.8 , 1.312066413 + 0.1789585449 * I +%! -0.2 + I * 1. , 1.516804331 + 0.2395555269 * I +%! -0.2 + I * 1.2 , 1.786613221 + 0.313189147 * I +%! -0.2 + I * 1.4 , 2.136422971 + 0.405890925 * I +%! -0.2 + I * 1.6 , 2.588021972 + 0.527357091 * I +%! -0.2 + I * 1.8 , 3.174302819 + 0.6944201617 * I +%! -0.2 + I * 2. , 3.947361147 + 0.9387994989 * I +%! 0. + I * 0. , 1. + 0. * I +%! 0. + I * 0.2 , 1.020074723 + 0. * I +%! 0. + I * 0.4 , 1.08120563 + 0. * I +%! 0. + I * 0.6 , 1.18619146 + 0. * I +%! 0. + I * 0.8 , 1.339978715 + 0. * I +%! 0. + I * 1. , 1.550164037 + 0. * I +%! 0. + I * 1.2 , 1.827893279 + 0. * I +%! 0. + I * 1.4 , 2.189462954 + 0. * I +%! 0. + I * 1.6 , 2.659259752 + 0. * I +%! 0. + I * 1.8 , 3.275434266 + 0. * I +%! 0. + I * 2. , 4.101632484 + 0. * I +%! 0.2 + I * 0. , 0.9800743122 + 0. * I +%! 0.2 + I * 0.2 , 0.9997019476 - 0.03999835809 * I +%! 0.2 + I * 0.4 , 1.059453907 - 0.08179712295 * I +%! 0.2 + I * 0.6 , 1.16200643 - 0.1273503824 * I +%! 0.2 + I * 0.8 , 1.312066413 - 0.1789585449 * I +%! 0.2 + I * 1. , 1.516804331 - 0.2395555269 * I +%! 0.2 + I * 1.2 , 1.786613221 - 0.313189147 * I +%! 0.2 + I * 1.4 , 2.136422971 - 0.405890925 * I +%! 0.2 + I * 1.6 , 2.588021972 - 0.527357091 * I +%! 0.2 + I * 1.8 , 3.174302819 - 0.6944201617 * I +%! 0.2 + I * 2. , 3.947361147 - 0.9387994989 * I +%! 0.4 + I * 0. , 0.9211793498 + 0. * I +%! 0.4 + I * 0.2 , 0.9395019377 - 0.07822091534 * I +%! 0.4 + I * 0.4 , 0.9952345231 - 0.1598950363 * I +%! 0.4 + I * 0.6 , 1.090715991 - 0.2487465067 * I +%! 0.4 + I * 0.8 , 1.229998843 - 0.34910407 * I +%! 0.4 + I * 1. , 1.419103868 - 0.4663848201 * I +%! 0.4 + I * 1.2 , 1.666426377 - 0.607877235 * I +%! 0.4 + I * 1.4 , 1.983347336 - 0.7841054404 * I +%! 0.4 + I * 1.6 , 2.385101684 - 1.01134031 * I +%! 0.4 + I * 1.8 , 2.89185416 - 1.316448705 * I +%! 0.4 + I * 2. , 3.529393374 - 1.74670531 * I +%! 0.6 + I * 0. , 0.8258917445 + 0. * I +%! 0.6 + I * 0.2 , 0.842151698 - 0.1130337928 * I +%! 0.6 + I * 0.4 , 0.8915487431 - 0.2309124769 * I +%! 0.6 + I * 0.6 , 0.975948103 - 0.3588102098 * I +%! 0.6 + I * 0.8 , 1.098499209 - 0.5026234141 * I +%! 0.6 + I * 1. , 1.263676101 - 0.6695125973 * I +%! 0.6 + I * 1.2 , 1.477275851 - 0.8687285705 * I +%! 0.6 + I * 1.4 , 1.746262523 - 1.112955966 * I +%! 0.6 + I * 1.6 , 2.078179075 - 1.420581466 * I +%! 0.6 + I * 1.8 , 2.479425208 - 1.819580713 * I +%! 0.6 + I * 2. , 2.950586798 - 2.354077344 * I +%! 0.8 + I * 0. , 0.6982891589 + 0. * I +%! 0.8 + I * 0.2 , 0.71187169 - 0.1430549855 * I +%! 0.8 + I * 0.4 , 0.7530744458 - 0.2920273465 * I +%! 0.8 + I * 0.6 , 0.8232501212 - 0.4531616768 * I +%! 0.8 + I * 0.8 , 0.9245978896 - 0.6334016187 * I +%! 0.8 + I * 1. , 1.060030206 - 0.8408616109 * I +%! 0.8 + I * 1.2 , 1.232861756 - 1.085475913 * I +%! 0.8 + I * 1.4 , 1.446126965 - 1.379933558 * I +%! 0.8 + I * 1.6 , 1.701139468 - 1.741030588 * I +%! 0.8 + I * 1.8 , 1.994526268 - 2.191509596 * I +%! 0.8 + I * 2. , 2.312257188 - 2.762051518 * I +%! 1. + I * 0. , 0.5436738271 + 0. * I +%! 1. + I * 0.2 , 0.5541219664 - 0.1672121517 * I +%! 1. + I * 0.4 , 0.5857703552 - 0.3410940893 * I +%! 1. + I * 0.6 , 0.6395034233 - 0.5285979063 * I +%! 1. + I * 0.8 , 0.716688504 - 0.7372552987 * I +%! 1. + I * 1. , 0.8189576795 - 0.9755037374 * I +%! 1. + I * 1.2 , 0.9477661951 - 1.253049471 * I +%! 1. + I * 1.4 , 1.103540657 - 1.581252712 * I +%! 1. + I * 1.6 , 1.284098214 - 1.973449038 * I +%! 1. + I * 1.8 , 1.481835651 - 2.4449211 * I +%! 1. + I * 2. , 1.679032464 - 3.011729224 * I +%! ]; +%! DN = [ +%! -1. + I * 0. , 0.9895776106 + 0. * I +%! -1. + I * 0.2 , 0.9893361555 + 0.002756935338 * I +%! -1. + I * 0.4 , 0.9885716856 + 0.005949639805 * I +%! -1. + I * 0.6 , 0.9871564855 + 0.01008044183 * I +%! -1. + I * 0.8 , 0.9848512162 + 0.01579337596 * I +%! -1. + I * 1. , 0.9812582484 + 0.02396648455 * I +%! -1. + I * 1.2 , 0.9757399152 + 0.0358288294 * I +%! -1. + I * 1.4 , 0.9672786056 + 0.0531049859 * I +%! -1. + I * 1.6 , 0.954237868 + 0.0781744383 * I +%! -1. + I * 1.8 , 0.933957524 + 0.1141918269 * I +%! -1. + I * 2. , 0.9020917489 + 0.1650142936 * I +%! -0.8 + I * 0. , 0.992429635 + 0. * I +%! -0.8 + I * 0.2 , 0.9924147861 + 0.003020708044 * I +%! -0.8 + I * 0.4 , 0.99236555 + 0.00652359532 * I +%! -0.8 + I * 0.6 , 0.9922655715 + 0.0110676219 * I +%! -0.8 + I * 0.8 , 0.9920785856 + 0.01737733806 * I +%! -0.8 + I * 1. , 0.9917291795 + 0.02645738598 * I +%! -0.8 + I * 1.2 , 0.9910606387 + 0.03974949378 * I +%! -0.8 + I * 1.4 , 0.9897435004 + 0.05935252515 * I +%! -0.8 + I * 1.6 , 0.987077644 + 0.08832675281 * I +%! -0.8 + I * 1.8 , 0.9815667458 + 0.1310872821 * I +%! -0.8 + I * 2. , 0.970020127 + 0.1938136793 * I +%! -0.6 + I * 0. , 0.9953099088 + 0. * I +%! -0.6 + I * 0.2 , 0.995526009 + 0.002814772354 * I +%! -0.6 + I * 0.4 , 0.9962071136 + 0.006083312292 * I +%! -0.6 + I * 0.6 , 0.9974557125 + 0.01033463525 * I +%! -0.6 + I * 0.8 , 0.9994560563 + 0.01626207722 * I +%! -0.6 + I * 1. , 1.00249312 + 0.02484336286 * I +%! -0.6 + I * 1.2 , 1.006973922 + 0.0375167093 * I +%! -0.6 + I * 1.4 , 1.013436509 + 0.05645315628 * I +%! -0.6 + I * 1.6 , 1.022504295 + 0.08499262247 * I +%! -0.6 + I * 1.8 , 1.034670023 + 0.1283564595 * I +%! -0.6 + I * 2. , 1.049599899 + 0.194806122 * I +%! -0.4 + I * 0. , 0.9977686897 + 0. * I +%! -0.4 + I * 0.2 , 0.9981836165 + 0.002167241934 * I +%! -0.4 + I * 0.4 , 0.9994946045 + 0.004686808612 * I +%! -0.4 + I * 0.6 , 1.001910789 + 0.00797144174 * I +%! -0.4 + I * 0.8 , 1.005817375 + 0.01256717724 * I +%! -0.4 + I * 1. , 1.011836374 + 0.01925509038 * I +%! -0.4 + I * 1.2 , 1.020923572 + 0.02920828367 * I +%! -0.4 + I * 1.4 , 1.034513743 + 0.04425213602 * I +%! -0.4 + I * 1.6 , 1.054725746 + 0.06732276244 * I +%! -0.4 + I * 1.8 , 1.08462027 + 0.1033236812 * I +%! -0.4 + I * 2. , 1.128407402 + 0.1608240664 * I +%! -0.2 + I * 0. , 0.9994191176 + 0. * I +%! -0.2 + I * 0.2 , 0.9999683719 + 0.001177128019 * I +%! -0.2 + I * 0.4 , 1.001705496 + 0.00254669712 * I +%! -0.2 + I * 0.6 , 1.004913944 + 0.004334880912 * I +%! -0.2 + I * 0.8 , 1.010120575 + 0.006842775622 * I +%! -0.2 + I * 1. , 1.018189543 + 0.01050520136 * I +%! -0.2 + I * 1.2 , 1.030482479 + 0.01598431001 * I +%! -0.2 + I * 1.4 , 1.049126108 + 0.02433134655 * I +%! -0.2 + I * 1.6 , 1.077466003 + 0.0372877718 * I +%! -0.2 + I * 1.8 , 1.120863308 + 0.05789156398 * I +%! -0.2 + I * 2. , 1.188162088 + 0.09181238708 * I +%! 0. + I * 0. , 1. + 0. * I +%! 0. + I * 0.2 , 1.000596698 + 0. * I +%! 0. + I * 0.4 , 1.002484444 + 0. * I +%! 0. + I * 0.6 , 1.005973379 + 0. * I +%! 0. + I * 0.8 , 1.011641536 + 0. * I +%! 0. + I * 1. , 1.020441432 + 0. * I +%! 0. + I * 1.2 , 1.033885057 + 0. * I +%! 0. + I * 1.4 , 1.054361188 + 0. * I +%! 0. + I * 1.6 , 1.085694733 + 0. * I +%! 0. + I * 1.8 , 1.134186672 + 0. * I +%! 0. + I * 2. , 1.210701071 + 0. * I +%! 0.2 + I * 0. , 0.9994191176 + 0. * I +%! 0.2 + I * 0.2 , 0.9999683719 - 0.001177128019 * I +%! 0.2 + I * 0.4 , 1.001705496 - 0.00254669712 * I +%! 0.2 + I * 0.6 , 1.004913944 - 0.004334880912 * I +%! 0.2 + I * 0.8 , 1.010120575 - 0.006842775622 * I +%! 0.2 + I * 1. , 1.018189543 - 0.01050520136 * I +%! 0.2 + I * 1.2 , 1.030482479 - 0.01598431001 * I +%! 0.2 + I * 1.4 , 1.049126108 - 0.02433134655 * I +%! 0.2 + I * 1.6 , 1.077466003 - 0.0372877718 * I +%! 0.2 + I * 1.8 , 1.120863308 - 0.05789156398 * I +%! 0.2 + I * 2. , 1.188162088 - 0.09181238708 * I +%! 0.4 + I * 0. , 0.9977686897 + 0. * I +%! 0.4 + I * 0.2 , 0.9981836165 - 0.002167241934 * I +%! 0.4 + I * 0.4 , 0.9994946045 - 0.004686808612 * I +%! 0.4 + I * 0.6 , 1.001910789 - 0.00797144174 * I +%! 0.4 + I * 0.8 , 1.005817375 - 0.01256717724 * I +%! 0.4 + I * 1. , 1.011836374 - 0.01925509038 * I +%! 0.4 + I * 1.2 , 1.020923572 - 0.02920828367 * I +%! 0.4 + I * 1.4 , 1.034513743 - 0.04425213602 * I +%! 0.4 + I * 1.6 , 1.054725746 - 0.06732276244 * I +%! 0.4 + I * 1.8 , 1.08462027 - 0.1033236812 * I +%! 0.4 + I * 2. , 1.128407402 - 0.1608240664 * I +%! 0.6 + I * 0. , 0.9953099088 + 0. * I +%! 0.6 + I * 0.2 , 0.995526009 - 0.002814772354 * I +%! 0.6 + I * 0.4 , 0.9962071136 - 0.006083312292 * I +%! 0.6 + I * 0.6 , 0.9974557125 - 0.01033463525 * I +%! 0.6 + I * 0.8 , 0.9994560563 - 0.01626207722 * I +%! 0.6 + I * 1. , 1.00249312 - 0.02484336286 * I +%! 0.6 + I * 1.2 , 1.006973922 - 0.0375167093 * I +%! 0.6 + I * 1.4 , 1.013436509 - 0.05645315628 * I +%! 0.6 + I * 1.6 , 1.022504295 - 0.08499262247 * I +%! 0.6 + I * 1.8 , 1.034670023 - 0.1283564595 * I +%! 0.6 + I * 2. , 1.049599899 - 0.194806122 * I +%! 0.8 + I * 0. , 0.992429635 + 0. * I +%! 0.8 + I * 0.2 , 0.9924147861 - 0.003020708044 * I +%! 0.8 + I * 0.4 , 0.99236555 - 0.00652359532 * I +%! 0.8 + I * 0.6 , 0.9922655715 - 0.0110676219 * I +%! 0.8 + I * 0.8 , 0.9920785856 - 0.01737733806 * I +%! 0.8 + I * 1. , 0.9917291795 - 0.02645738598 * I +%! 0.8 + I * 1.2 , 0.9910606387 - 0.03974949378 * I +%! 0.8 + I * 1.4 , 0.9897435004 - 0.05935252515 * I +%! 0.8 + I * 1.6 , 0.987077644 - 0.08832675281 * I +%! 0.8 + I * 1.8 , 0.9815667458 - 0.1310872821 * I +%! 0.8 + I * 2. , 0.970020127 - 0.1938136793 * I +%! 1. + I * 0. , 0.9895776106 + 0. * I +%! 1. + I * 0.2 , 0.9893361555 - 0.002756935338 * I +%! 1. + I * 0.4 , 0.9885716856 - 0.005949639805 * I +%! 1. + I * 0.6 , 0.9871564855 - 0.01008044183 * I +%! 1. + I * 0.8 , 0.9848512162 - 0.01579337596 * I +%! 1. + I * 1. , 0.9812582484 - 0.02396648455 * I +%! 1. + I * 1.2 , 0.9757399152 - 0.0358288294 * I +%! 1. + I * 1.4 , 0.9672786056 - 0.0531049859 * I +%! 1. + I * 1.6 , 0.954237868 - 0.0781744383 * I +%! 1. + I * 1.8 , 0.933957524 - 0.1141918269 * I +%! 1. + I * 2. , 0.9020917489 - 0.1650142936 * I +%! ]; +%! tol = 1e-9; +%! for x = 0:10 +%! for y = 0:10 +%! ur = -1 + x * 0.2; +%! ui = y * 0.2; +%! ii = 1 + y + x*11; +%! [sn, cn, dn] = ellipj (ur + I * ui, m); +%! assert (SN (ii, 2), sn, tol); +%! assert (CN (ii, 2), cn, tol); +%! assert (DN (ii, 2), dn, tol); +%! endfor +%! endfor + +## tests taken from test_ellipj.m +%!test +%! u1 = pi/3; m1 = 0; +%! res1 = [sin(pi/3), cos(pi/3), 1]; +%! [sn,cn,dn]=ellipj(u1,m1); +%! assert([sn,cn,dn], res1, 10*eps); + +%!test +%! u2 = log(2); m2 = 1; +%! res2 = [ 3/5, 4/5, 4/5 ]; +%! [sn,cn,dn]=ellipj(u2,m2); +%! assert([sn,cn,dn], res2, 10*eps); + +%!test +%! u3 = log(2)*1i; m3 = 0; +%! res3 = [3i/4,5/4,1]; +%! [sn,cn,dn]=ellipj(u3,m3); +%! assert([sn,cn,dn], res3, 10*eps); + +%!test +%! u4 = -1; m4 = tan(pi/8)^4; +%! res4 = [-0.8392965923,0.5436738271,0.9895776106]; +%! [sn,cn,dn]=ellipj(u4, m4); +%! assert([sn,cn,dn], res4, 1e-10); + +%!test +%! u5 = -0.2 + 0.4i; m5 = tan(pi/8)^4; +%! res5 = [ -0.2152524522 + 0.402598347i, ... +%! 1.059453907 + 0.08179712295i, ... +%! 1.001705496 + 0.00254669712i ]; +%! [sn,cn,dn]=ellipj(u5,m5); +%! assert([sn,cn,dn], res5, 1e-9); + +%!test +%! u6 = 0.2 + 0.6i; m6 = tan(pi/8)^4; +%! res6 = [ 0.2369100139 + 0.624633635i, ... +%! 1.16200643 - 0.1273503824i, ... +%! 1.004913944 - 0.004334880912i ]; +%! [sn,cn,dn]=ellipj(u6,m6); +%! assert([sn,cn,dn], res6, 1e-8); + +%!test +%! u7 = 0.8 + 0.8i; m7 = tan(pi/8)^4; +%! res7 = [0.9588386397 + 0.6107824358i, ... +%! 0.9245978896 - 0.6334016187i, ... +%! 0.9920785856 - 0.01737733806i ]; +%! [sn,cn,dn]=ellipj(u7,m7); +%! assert([sn,cn,dn], res7, 1e-10); + +%!test +%! u=[0,pi/6,pi/4,pi/2]; m=0; +%! res = [0,1/2,1/sqrt(2),1;1,cos(pi/6),1/sqrt(2),0;1,1,1,1]; +%! [sn,cn,dn]=ellipj(u,m); +%! assert([sn;cn;dn],res, 100*eps); +%! [sn,cn,dn]=ellipj(u',0); +%! assert([sn,cn,dn],res', 100*eps); + +## XXX FIXME XXX +## need to check [real,complex]x[scalar,rowvec,colvec,matrix]x[u,m] + +%!test +%! ## Test Jacobi elliptic functions +%! ## against "exact" solution from Mathematica 3.0 +%! ## David Billinghurst +%! ## 1 February 2001 +%! u = [ 0.25; 0.25; 0.20; 0.20; 0.672; 0.5]; +%! m = [ 0.0; 1.0; 0.19; 0.81; 0.36; 0.9999999999]; +%! S = [ sin(0.25); tanh(0.25); +%! 0.19842311013970879516; +%! 0.19762082367187648571; +%! 0.6095196917919021945; +%! 0.4621171572617320908 ]; +%! C = [ cos(0.25); sech(0.25); +%! 0.9801164570409401062; +%! 0.9802785369736752032; +%! 0.7927709286533560550; +%! 0.8868188839691764094 ]; +%! D = [ 1.0; sech(0.25); +%! 0.9962526643271134302; +%! 0.9840560289645665155; +%! 0.9307281387786906491; +%! 0.8868188839812167635 ]; +%! [sn,cn,dn] = ellipj(u,m); +%! assert(sn,S,8*eps); +%! assert(cn,C,8*eps); +%! assert(dn,D,8*eps); + +%!error ellipj () +%!error ellipj (1) +%!error ellipj (1,2,3,4) +*/ diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/corefcn/module.mk --- a/libinterp/corefcn/module.mk Mon Apr 22 16:37:53 2013 -0400 +++ b/libinterp/corefcn/module.mk Mon Apr 29 19:13:40 2013 -0400 @@ -45,6 +45,7 @@ corefcn/dlmread.cc \ corefcn/dot.cc \ corefcn/eig.cc \ + corefcn/ellipj.cc \ corefcn/fft.cc \ corefcn/fft2.cc \ corefcn/fftn.cc \ diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/interp-core/ls-mat-ascii.cc --- a/libinterp/interp-core/ls-mat-ascii.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libinterp/interp-core/ls-mat-ascii.cc Mon Apr 29 19:13:40 2013 -0400 @@ -107,7 +107,10 @@ } static void -get_lines_and_columns (std::istream& is, const std::string& filename, octave_idx_type& nr, octave_idx_type& nc) +get_lines_and_columns (std::istream& is, + octave_idx_type& nr, octave_idx_type& nc, + const std::string& filename = std::string (), + bool quiet = false, bool check_numeric = false) { std::streampos pos = is.tellg (); @@ -147,6 +150,25 @@ if (end != std::string::npos) { + if (check_numeric) + { + std::istringstream tmp_stream (buf.substr (beg, end-beg)); + + octave_read_double (tmp_stream); + + if (tmp_stream.fail ()) + { + if (! quiet) + error ("load: %s: non-numeric data found near line %d", + filename.c_str (), file_line_number); + + nr = 0; + nc = 0; + + goto done; + } + } + beg = buf.find_first_not_of (", \t", end); if (beg == std::string::npos || (buf[beg] == '\r' && @@ -172,14 +194,24 @@ else if (nc == tmp_nc) nr++; else - error ("load: %s: inconsistent number of columns near line %d", - filename.c_str (), file_line_number); + { + if (! quiet) + error ("load: %s: inconsistent number of columns near line %d", + filename.c_str (), file_line_number); + + nr = 0; + nc = 0; + + goto done; + } } } - if (nr == 0 || nc == 0) + if (! quiet && (nr == 0 || nc == 0)) error ("load: file '%s' seems to be empty!", filename.c_str ()); + done: + is.clear (); is.seekg (pos); } @@ -233,7 +265,7 @@ int total_count = 0; - get_lines_and_columns (is, filename, nr, nc); + get_lines_and_columns (is, nr, nc, filename); octave_quit (); @@ -376,3 +408,23 @@ return (os && success); } + +bool +looks_like_mat_ascii_file (const std::string& filename) +{ + bool retval = false; + + std::ifstream is (filename.c_str ()); + + if (is) + { + octave_idx_type nr = 0; + octave_idx_type nc = 0; + + get_lines_and_columns (is, nr, nc, filename, true, true); + + retval = (nr != 0 && nc != 0); + } + + return retval; +} diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/interp-core/ls-mat-ascii.h --- a/libinterp/interp-core/ls-mat-ascii.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libinterp/interp-core/ls-mat-ascii.h Mon Apr 29 19:13:40 2013 -0400 @@ -31,4 +31,6 @@ save_mat_ascii_data (std::ostream& os, const octave_value& val_arg, int precision, bool tabs = false); +extern bool looks_like_mat_ascii_file (const std::string& filename); + #endif diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/interpfcn/file-io.cc --- a/libinterp/interpfcn/file-io.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libinterp/interpfcn/file-io.cc Mon Apr 29 19:13:40 2013 -0400 @@ -130,26 +130,25 @@ } } -static std::ios::openmode -fopen_mode_to_ios_mode (const std::string& mode_arg) +static void +normalize_fopen_mode (std::string& mode, bool& use_zlib) { - std::ios::openmode retval = std::ios::in; + use_zlib = false; - if (! mode_arg.empty ()) + if (! mode.empty ()) { // Could probably be faster, but does it really matter? - std::string mode = mode_arg; - - // 'W' and 'R' are accepted as 'w' and 'r', but we warn about - // them because Matlab says they perform "automatic flushing" - // but we don't know precisely what action that implies. + // Accept 'W', 'R', and 'A' as 'w', 'r', and 'a' but we warn about + // them because Matlab says they don't perform "automatic + // flushing" but we don't know precisely what action that implies. size_t pos = mode.find ('W'); if (pos != std::string::npos) { - warning ("fopen: treating mode \"W\" as equivalent to \"w\""); + warning_with_id ("Octave:fopen-mode", + "fopen: treating mode \"W\" as equivalent to \"w\""); mode[pos] = 'w'; } @@ -157,15 +156,26 @@ if (pos != std::string::npos) { - warning ("fopen: treating mode \"R\" as equivalent to \"r\""); + warning_with_id ("Octave:fopen-mode", + "fopen: treating mode \"R\" as equivalent to \"r\""); mode[pos] = 'r'; } + pos = mode.find ('A'); + + if (pos != std::string::npos) + { + warning_with_id ("Octave:fopen-mode", + "fopen: treating mode \"A\" as equivalent to \"a\""); + mode[pos] = 'a'; + } + pos = mode.find ('z'); if (pos != std::string::npos) { #if defined (HAVE_ZLIB) + use_zlib = true; mode.erase (pos, 1); #else error ("this version of Octave does not support gzipped files"); @@ -174,36 +184,54 @@ if (! error_state) { - if (mode == "rt") - retval = std::ios::in; - else if (mode == "wt") - retval = std::ios::out | std::ios::trunc; - else if (mode == "at") - retval = std::ios::out | std::ios::app; - else if (mode == "r+t" || mode == "rt+") - retval = std::ios::in | std::ios::out; - else if (mode == "w+t" || mode == "wt+") - retval = std::ios::in | std::ios::out | std::ios::trunc; - else if (mode == "a+t" || mode == "at+") - retval = std::ios::in | std::ios::out | std::ios::app; - else if (mode == "rb" || mode == "r") - retval = std::ios::in | std::ios::binary; - else if (mode == "wb" || mode == "w") - retval = std::ios::out | std::ios::trunc | std::ios::binary; - else if (mode == "ab" || mode == "a") - retval = std::ios::out | std::ios::app | std::ios::binary; - else if (mode == "r+b" || mode == "rb+" || mode == "r+") - retval = std::ios::in | std::ios::out | std::ios::binary; - else if (mode == "w+b" || mode == "wb+" || mode == "w+") - retval = (std::ios::in | std::ios::out | std::ios::trunc - | std::ios::binary); - else if (mode == "a+b" || mode == "ab+" || mode == "a+") - retval = (std::ios::in | std::ios::out | std::ios::app - | std::ios::binary); - else - ::error ("invalid mode specified"); + // Use binary mode if 't' is not specified, but don't add + // 'b' if it is already present. + + size_t bpos = mode.find ('b'); + size_t tpos = mode.find ('t'); + + if (bpos == std::string::npos && tpos == std::string::npos) + mode += 'b'; } } +} + +static std::ios::openmode +fopen_mode_to_ios_mode (const std::string& mode) +{ + std::ios::openmode retval = std::ios::in; + + if (! error_state) + { + if (mode == "rt") + retval = std::ios::in; + else if (mode == "wt") + retval = std::ios::out | std::ios::trunc; + else if (mode == "at") + retval = std::ios::out | std::ios::app; + else if (mode == "r+t" || mode == "rt+") + retval = std::ios::in | std::ios::out; + else if (mode == "w+t" || mode == "wt+") + retval = std::ios::in | std::ios::out | std::ios::trunc; + else if (mode == "a+t" || mode == "at+") + retval = std::ios::in | std::ios::out | std::ios::app; + else if (mode == "rb" || mode == "r") + retval = std::ios::in | std::ios::binary; + else if (mode == "wb" || mode == "w") + retval = std::ios::out | std::ios::trunc | std::ios::binary; + else if (mode == "ab" || mode == "a") + retval = std::ios::out | std::ios::app | std::ios::binary; + else if (mode == "r+b" || mode == "rb+" || mode == "r+") + retval = std::ios::in | std::ios::out | std::ios::binary; + else if (mode == "w+b" || mode == "wb+" || mode == "w+") + retval = (std::ios::in | std::ios::out | std::ios::trunc + | std::ios::binary); + else if (mode == "a+b" || mode == "ab+" || mode == "a+") + retval = (std::ios::in | std::ios::out | std::ios::app + | std::ios::binary); + else + ::error ("invalid mode specified"); + } return retval; } @@ -448,13 +476,17 @@ static octave_stream -do_stream_open (const std::string& name, const std::string& mode, +do_stream_open (const std::string& name, const std::string& mode_arg, const std::string& arch, int& fid) { octave_stream retval; fid = -1; + std::string mode = mode_arg; + bool use_zlib = false; + normalize_fopen_mode (mode, use_zlib); + std::ios::openmode md = fopen_mode_to_ios_mode (mode); if (! error_state) @@ -488,29 +520,14 @@ if (! fs.is_dir ()) { - std::string tmode = mode; - - // Use binary mode if 't' is not specified, but don't add - // 'b' if it is already present. - - size_t bpos = tmode.find ('b'); - size_t tpos = tmode.find ('t'); - - if (bpos == std::string::npos && tpos == std::string::npos) - tmode += 'b'; - #if defined (HAVE_ZLIB) - size_t pos = tmode.find ('z'); - - if (pos != std::string::npos) + if (use_zlib) { - tmode.erase (pos, 1); - - FILE *fptr = gnulib::fopen (fname.c_str (), tmode.c_str ()); + FILE *fptr = gnulib::fopen (fname.c_str (), mode.c_str ()); int fd = fileno (fptr); - gzFile gzf = ::gzdopen (fd, tmode.c_str ()); + gzFile gzf = ::gzdopen (fd, mode.c_str ()); if (fptr) retval = octave_zstdiostream::create (fname, gzf, fd, @@ -521,7 +538,7 @@ else #endif { - FILE *fptr = gnulib::fopen (fname.c_str (), tmode.c_str ()); + FILE *fptr = gnulib::fopen (fname.c_str (), mode.c_str ()); retval = octave_stdiostream::create (fname, fptr, md, flt_fmt); diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/interpfcn/load-path.cc --- a/libinterp/interpfcn/load-path.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libinterp/interpfcn/load-path.cc Mon Apr 29 19:13:40 2013 -0400 @@ -2165,7 +2165,7 @@ "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} addpath (@var{dir1}, @dots{})\n\ @deftypefnx {Built-in Function} {} addpath (@var{dir1}, @dots{}, @var{option})\n\ -Add @var{dir1}, @dots{} to the current function search path. If\n\ +Add named directories to the function search path. If\n\ @var{option} is \"-begin\" or 0 (the default), prepend the\n\ directory name to the current path. If @var{option} is \"-end\"\n\ or 1, append the directory name to the current path.\n\ diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/interpfcn/load-save.cc --- a/libinterp/interpfcn/load-save.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libinterp/interpfcn/load-save.cc Mon Apr 29 19:13:40 2013 -0400 @@ -242,7 +242,8 @@ int32_t mopt, nr, nc, imag, len; - int err = read_mat_file_header (file, swap, mopt, nr, nc, imag, len, 1); + int err = read_mat_file_header (file, swap, mopt, nr, nc, imag, len, + true); if (! err) retval = LS_MAT_BINARY; @@ -277,7 +278,7 @@ static load_save_format get_file_format (const std::string& fname, const std::string& orig_fname, - bool &use_zlib) + bool &use_zlib, bool quiet = false) { load_save_format retval = LS_UNKNOWN; @@ -309,19 +310,16 @@ } #endif - if (retval == LS_UNKNOWN) - { - // Try reading the file as numbers only, determining the - // number of rows and columns from the data. We don't - // even bother to check to see if the first item in the - // file is a number, so that get_complete_line() can - // skip any comments that might appear at the top of the - // file. + // FIXME -- looks_like_mat_ascii_file does not check to see + // whether the file contains numbers. It just skips comments and + // checks for the same number of words on each line. We may need + // a better check here. The best way to do that might be just + // to try to read the file and see if it works. - retval = LS_MAT_ASCII; - } + if (retval == LS_UNKNOWN && looks_like_mat_ascii_file (fname)) + retval = LS_MAT_ASCII; } - else + else if (! quiet) gripe_file_open ("load", orig_fname); return retval; @@ -537,6 +535,12 @@ return fname; } +bool +is_octave_data_file (const std::string& fname) +{ + bool use_zlib = false; + return get_file_format (fname, fname, use_zlib, true) != LS_UNKNOWN; +} DEFUN (load, args, nargout, "-*- texinfo -*-\n\ diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/interpfcn/load-save.h --- a/libinterp/interpfcn/load-save.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libinterp/interpfcn/load-save.h Mon Apr 29 19:13:40 2013 -0400 @@ -26,6 +26,9 @@ #include #include +#include "mach-info.h" +#include "symtab.h" + class octave_value; // FIXME: maybe MAT5 and MAT7 should be options to MAT_BINARY. @@ -80,6 +83,8 @@ bool list_only, bool swap, bool verbose, const string_vector& argv, int argv_idx, int argc, int nargout); +extern bool is_octave_data_file (const std::string& file); + extern void do_save (std::ostream& os, const symbol_table::symbol_record& sr, load_save_format fmt, bool save_as_floats); diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/interpfcn/octave-link.cc --- a/libinterp/interpfcn/octave-link.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libinterp/interpfcn/octave-link.cc Mon Apr 29 19:13:40 2013 -0400 @@ -193,6 +193,86 @@ return retval; } +DEFUN (__octave_link_file_dialog__, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __octave_link_file_dialog__ (@var{filterlist}, @var{title}, @var{filename}, @var{size} @var{multiselect}, @var{pathname})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + octave_value_list retval; + + if (args.length () == 6) + { + + const Array flist = args(0).cellstr_value (); + std::string title = args(1).string_value (); + std::string filename = args(2).string_value (); + Matrix pos = args(3).matrix_value (); + std::string multi_on = args(4).string_value (); // on, off, create + std::string pathname = args(5).string_value (); + + octave_idx_type nel = flist.numel (); + octave_link::filter_list filter_lst; + + for (octave_idx_type i = 0; i < flist.rows (); i++) + filter_lst.push_back (std::make_pair (flist(i,0), + (flist.columns () > 1 + ? flist(i,1) : ""))); + + if (! error_state) + { + flush_octave_stdout (); + + std::list items_lst + = octave_link::file_dialog (filter_lst, title, filename, pathname, + multi_on); + + nel = items_lst.size (); + + retval.resize (3); + + // If 3, then is filename, directory and selected index. + if (nel <= 3) + { + int idx = 0; + for (std::list::iterator it = items_lst.begin (); + it != items_lst.end (); it++) + { + retval(idx++) = *it; + + if (idx == 1 && retval(0).string_value ().length () == 0) + retval(0) = 0; + + if (idx == 3) + retval(2) = atoi (retval(2).string_value ().c_str ()); + } + } + else + { + // Multiple files. + nel = items_lst.size (); + Cell items (dim_vector (1, nel)); + + std::list::iterator it = items_lst.begin (); + + for (int idx = 0; idx < items_lst.size ()-2; idx++) + { + items.xelem (idx) = *it; + it++; + } + + retval(0) = items; + retval(1) = *it++; + retval(2) = atoi (it->c_str ()); + } + } + else + error ("invalid arguments"); + } + + return retval; +} + DEFUN (__octave_link_list_dialog__, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} __octave_link_list_dialog__ (@var{list}, @var{mode}, @var{size}, @var{intial}, @var{name}, @var{prompt}, @var{ok_string}, @var{cancel_string})\n\ diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/interpfcn/octave-link.h --- a/libinterp/interpfcn/octave-link.h Mon Apr 22 16:37:53 2013 -0400 +++ b/libinterp/interpfcn/octave-link.h Mon Apr 29 19:13:40 2013 -0400 @@ -179,6 +179,19 @@ : std::list (); } + typedef std::list > filter_list; + + static std::list + file_dialog (const filter_list& filter, const std::string& title, + const std::string& filename, const std::string& dirname, + const std::string& multimode) + { + return enabled () + ? instance->do_file_dialog (filter, title, filename, dirname, multimode) + : std::list (); + } + + static int debug_cd_or_addpath_error (const std::string& file, const std::string& dir, bool addpath_option) @@ -193,6 +206,13 @@ instance->do_change_directory (dir); } + // Preserves pending input. + static void execute_command_in_terminal (const std::string& command) + { + if (enabled ()) + instance->do_execute_command_in_terminal (command); + } + static void set_workspace (void); static void set_workspace (bool top_level, @@ -363,6 +383,11 @@ const std::list& nc, const std::list& defaults) = 0; + virtual std::list + do_file_dialog (const filter_list& filter, const std::string& title, + const std::string& filename, const std::string& dirname, + const std::string& multimode) = 0; + virtual int do_debug_cd_or_addpath_error (const std::string& file, const std::string& dir, @@ -370,6 +395,8 @@ virtual void do_change_directory (const std::string& dir) = 0; + virtual void do_execute_command_in_terminal (const std::string& command) = 0; + virtual void do_set_workspace (bool top_level, const std::list& ws) = 0; diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/interpfcn/sysdep.cc --- a/libinterp/interpfcn/sysdep.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/libinterp/interpfcn/sysdep.cc Mon Apr 29 19:13:40 2013 -0400 @@ -196,16 +196,26 @@ bool retval = false; + const char *f1 = file1.c_str (); + const char *f2 = file2.c_str (); + + bool f1_is_dir = GetFileAttributes (f1) & FILE_ATTRIBUTE_DIRECTORY; + bool f2_is_dir = GetFileAttributes (f2) & FILE_ATTRIBUTE_DIRECTORY; + // Windows native code // Reference: http://msdn2.microsoft.com/en-us/library/aa363788.aspx - HANDLE hfile1 = CreateFile (file1.c_str (), 0, FILE_SHARE_READ, 0, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + DWORD share = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; + + HANDLE hfile1 + = CreateFile (f1, 0, share, 0, OPEN_EXISTING, + f1_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0); if (hfile1 != INVALID_HANDLE_VALUE) { - HANDLE hfile2 = CreateFile (file2.c_str (), 0, FILE_SHARE_READ, 0, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + HANDLE hfile2 + = CreateFile (f2, 0, share, 0, OPEN_EXISTING, + f2_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0); if (hfile2 != INVALID_HANDLE_VALUE) { @@ -214,10 +224,11 @@ if (GetFileInformationByHandle (hfile1, &hfi1) && GetFileInformationByHandle (hfile2, &hfi2)) - - retval = (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber - && hfi1.nFileIndexHigh == hfi2.nFileIndexHigh - && hfi1.nFileIndexLow == hfi2.nFileIndexLow); + { + retval = (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber + && hfi1.nFileIndexHigh == hfi2.nFileIndexHigh + && hfi1.nFileIndexLow == hfi2.nFileIndexLow); + } CloseHandle (hfile2); } diff -r 2ed5bc680c71 -r 8abae9ea4cb5 libinterp/parse-tree/oct-parse.in.yy --- a/libinterp/parse-tree/oct-parse.in.yy Mon Apr 22 16:37:53 2013 -0400 +++ b/libinterp/parse-tree/oct-parse.in.yy Mon Apr 29 19:13:40 2013 -0400 @@ -1575,8 +1575,18 @@ void octave_base_parser::reset (void) { + endfunction_found = false; + autoloading = false; + fcn_file_from_relative_lookup = false; + parsing_subfunctions = false; + max_fcn_depth = 0; + curr_fcn_depth = 0; + primary_fcn_scope = -1; + curr_class_name = ""; + function_scopes.clear (); + primary_fcn_ptr = 0; + delete stmt_list; - stmt_list = 0; lexer.reset (); diff -r 2ed5bc680c71 -r 8abae9ea4cb5 liboctave/util/cmd-edit.cc --- a/liboctave/util/cmd-edit.cc Mon Apr 22 16:37:53 2013 -0400 +++ b/liboctave/util/cmd-edit.cc Mon Apr 29 19:13:40 2013 -0400 @@ -48,6 +48,8 @@ std::set command_editor::startup_hook_set; +std::set command_editor::pre_input_hook_set; + std::set command_editor::event_hook_set; static octave_mutex event_hook_lock; @@ -66,6 +68,8 @@ typedef command_editor::startup_hook_fcn startup_hook_fcn; + typedef command_editor::pre_input_hook_fcn pre_input_hook_fcn; + typedef command_editor::event_hook_fcn event_hook_fcn; typedef command_editor::completion_fcn completion_fcn; @@ -139,6 +143,10 @@ std::string do_get_line_buffer (void) const; + std::string do_get_current_line (void) const; + + void do_replace_line (const std::string& text, bool clear_undo); + void do_insert_text (const std::string& text); void do_newline (void); @@ -153,6 +161,10 @@ void restore_startup_hook (void); + void set_pre_input_hook (pre_input_hook_fcn f); + + void restore_pre_input_hook (void); + void set_event_hook (event_hook_fcn f); void restore_event_hook (void); @@ -179,6 +191,8 @@ startup_hook_fcn previous_startup_hook; + pre_input_hook_fcn previous_pre_input_hook; + event_hook_fcn previous_event_hook; completion_fcn completion_function; @@ -205,6 +219,7 @@ gnu_readline::gnu_readline () : command_editor (), previous_startup_hook (0), + previous_pre_input_hook (0), previous_event_hook (0), completion_function (0), quoting_function (0), dequoting_function (0), char_is_quoted_function (0), user_accept_line_function (0) @@ -522,6 +537,22 @@ return ::octave_rl_line_buffer (); } +std::string +gnu_readline::do_get_current_line (void) const +{ + std::string retval; + char *buf = ::octave_rl_copy_line (); + retval = buf; + free (buf); + return retval; +} + +void +gnu_readline::do_replace_line (const std::string& text, bool clear_undo) +{ + ::octave_rl_replace_line (text.c_str (), clear_undo); +} + void gnu_readline::do_insert_text (const std::string& text) { @@ -568,6 +599,21 @@ } void +gnu_readline::set_pre_input_hook (pre_input_hook_fcn f) +{ + previous_pre_input_hook = ::octave_rl_get_pre_input_hook (); + + if (f != previous_pre_input_hook) + ::octave_rl_set_pre_input_hook (f); +} + +void +gnu_readline::restore_pre_input_hook (void) +{ + ::octave_rl_set_pre_input_hook (previous_pre_input_hook); +} + +void gnu_readline::set_event_hook (event_hook_fcn f) { previous_event_hook = octave_rl_get_event_hook (); @@ -767,7 +813,11 @@ std::string do_get_line_buffer (void) const; - void do_insert_text (const std::string&); + std::string do_get_current_line (void) const; + + void do_replace_line (const std::string& text, bool clear_undo); + + void do_insert_text (const std::string& text); void do_newline (void); @@ -832,6 +882,19 @@ return ""; } +std::string +default_command_editor::do_get_current_line (void) const +{ + // FIXME + return std::string (); +} + +void +default_command_editor::do_replace_line (const std::string&, bool) +{ + // FIXME +} + void default_command_editor::do_insert_text (const std::string&) { @@ -891,6 +954,19 @@ instance = new default_command_editor (); } +void +command_editor::set_initial_input (const std::string& text) +{ + if (instance_ok ()) + instance->initial_input = text; +} + +int +command_editor::insert_initial_input (void) +{ + return instance_ok () ? instance->do_insert_initial_input () : 0; +} + int command_editor::startup_handler (void) { @@ -907,6 +983,21 @@ } int +command_editor::pre_input_handler (void) +{ + for (pre_input_hook_set_iterator p = pre_input_hook_set.begin (); + p != pre_input_hook_set.end (); p++) + { + pre_input_hook_fcn f = *p; + + if (f) + f (); + } + + return 0; +} + +int command_editor::event_handler (void) { event_hook_lock.lock (); @@ -945,8 +1036,17 @@ std::string command_editor::readline (const std::string& prompt, bool& eof) { - return (instance_ok ()) - ? instance->do_readline (prompt, eof) : std::string (); + std::string retval; + + if (instance_ok ()) + { + if (! instance->initial_input.empty ()) + add_pre_input_hook (command_editor::insert_initial_input); + + retval = instance->do_readline (prompt, eof); + } + + return retval; } void @@ -1179,6 +1279,19 @@ return (instance_ok ()) ? instance->do_get_line_buffer () : ""; } +std::string +command_editor::get_current_line (void) +{ + return (instance_ok ()) ? instance->do_get_current_line () : ""; +} + +void +command_editor::replace_line (const std::string& text, bool clear_undo) +{ + if (instance_ok ()) + instance->do_replace_line (text, clear_undo); +} + void command_editor::insert_text (const std::string& text) { @@ -1240,6 +1353,32 @@ } void +command_editor::add_pre_input_hook (pre_input_hook_fcn f) +{ + if (instance_ok ()) + { + pre_input_hook_set.insert (f); + + instance->set_pre_input_hook (pre_input_handler); + } +} + +void +command_editor::remove_pre_input_hook (pre_input_hook_fcn f) +{ + if (instance_ok ()) + { + pre_input_hook_set_iterator p = pre_input_hook_set.find (f); + + if (p != pre_input_hook_set.end ()) + pre_input_hook_set.erase (p); + + if (pre_input_hook_set.empty ()) + instance->restore_pre_input_hook (); + } +} + +void command_editor::add_event_hook (event_hook_fcn f) { octave_autolock guard (event_hook_lock); @@ -1586,6 +1725,21 @@ return result; } +int +command_editor::do_insert_initial_input (void) +{ + std::string input = initial_input; + + initial_input = ""; + + do_insert_text (input); + + // Is it really right to redisplay here? + do_redisplay (); + + return 0; +} + // Return the octal number parsed from STRING, or -1 to indicate that // the string contained a bad number. diff -r 2ed5bc680c71 -r 8abae9ea4cb5 liboctave/util/cmd-edit.h --- a/liboctave/util/cmd-edit.h Mon Apr 22 16:37:53 2013 -0400 +++ b/liboctave/util/cmd-edit.h Mon Apr 29 19:13:40 2013 -0400 @@ -37,12 +37,14 @@ protected: command_editor (void) - : command_number (0), interrupted (false) { } + : command_number (0), interrupted (false), initial_input () { } public: typedef int (*startup_hook_fcn) (void); + typedef int (*pre_input_hook_fcn) (void); + typedef int (*event_hook_fcn) (void); typedef std::string (*completion_fcn) (const std::string&, int); @@ -123,6 +125,10 @@ static std::string get_line_buffer (void); + static std::string get_current_line (void); + + static void replace_line (const std::string& text, bool clear_undo = true); + static void insert_text (const std::string& text); static void newline (void); @@ -137,6 +143,10 @@ static void remove_startup_hook (startup_hook_fcn f); + static void add_pre_input_hook (pre_input_hook_fcn f); + + static void remove_pre_input_hook (pre_input_hook_fcn f); + static void add_event_hook (event_hook_fcn f); static void remove_event_hook (event_hook_fcn f); @@ -151,7 +161,7 @@ static bool filename_quoting_desired (bool); - static bool interrupt (bool); + static bool interrupt (bool = true); static int current_command_number (void); @@ -161,6 +171,10 @@ static void force_default_editor (void); + static void set_initial_input (const std::string& text); + + static int insert_initial_input (void); + private: // No copying! @@ -175,15 +189,22 @@ static int startup_handler (void); + static int pre_input_handler (void); + static int event_handler (void); static std::set startup_hook_set; + static std::set pre_input_hook_set; + static std::set event_hook_set; typedef std::set::iterator startup_hook_set_iterator; typedef std::set::const_iterator startup_hook_set_const_iterator; + typedef std::set::iterator pre_input_hook_set_iterator; + typedef std::set::const_iterator pre_input_hook_set_const_iterator; + typedef std::set::iterator event_hook_set_iterator; typedef std::set::const_iterator event_hook_set_const_iterator; @@ -271,7 +292,11 @@ virtual std::string do_get_line_buffer (void) const = 0; - virtual void do_insert_text (const std::string&) = 0; + virtual std::string do_get_current_line (void) const = 0; + + virtual void do_replace_line (const std::string& text, bool clear_undo) = 0; + + virtual void do_insert_text (const std::string& text) = 0; virtual void do_newline (void) = 0; @@ -285,7 +310,11 @@ virtual void restore_startup_hook (void) { } - virtual void set_event_hook (startup_hook_fcn) { } + virtual void set_pre_input_hook (pre_input_hook_fcn) { } + + virtual void restore_pre_input_hook (void) { } + + virtual void set_event_hook (event_hook_fcn) { } virtual void restore_event_hook (void) { } @@ -299,6 +328,8 @@ virtual void do_interrupt (bool) { } + int do_insert_initial_input (void); + int read_octal (const std::string& s); void error (int); @@ -309,6 +340,8 @@ int command_number; bool interrupted; + + std::string initial_input; }; #endif diff -r 2ed5bc680c71 -r 8abae9ea4cb5 liboctave/util/oct-rl-edit.c --- a/liboctave/util/oct-rl-edit.c Mon Apr 22 16:37:53 2013 -0400 +++ b/liboctave/util/oct-rl-edit.c Mon Apr 29 19:13:40 2013 -0400 @@ -123,6 +123,18 @@ rl_deprep_term_function (); } +char * +octave_rl_copy_line (void) +{ + return rl_copy_text (0, rl_end); +} + +void +octave_rl_replace_line (const char *s, int clear_undo) +{ + rl_replace_line (s, clear_undo); +} + void octave_rl_insert_text (const char *s) { @@ -325,6 +337,18 @@ } void +octave_rl_set_pre_input_hook (rl_pre_input_hook_fcn_ptr f) +{ + rl_pre_input_hook = f; +} + +rl_pre_input_hook_fcn_ptr +octave_rl_get_pre_input_hook (void) +{ + return rl_pre_input_hook; +} + +void octave_rl_set_event_hook (rl_event_hook_fcn_ptr f) { rl_event_hook = f; diff -r 2ed5bc680c71 -r 8abae9ea4cb5 liboctave/util/oct-rl-edit.h --- a/liboctave/util/oct-rl-edit.h Mon Apr 22 16:37:53 2013 -0400 +++ b/liboctave/util/oct-rl-edit.h Mon Apr 29 19:13:40 2013 -0400 @@ -25,6 +25,8 @@ typedef int (*rl_startup_hook_fcn_ptr) (void); +typedef int (*rl_pre_input_hook_fcn_ptr) (void); + typedef int (*rl_event_hook_fcn_ptr) (void); typedef int (*rl_fcn_ptr) (int, int); @@ -62,6 +64,10 @@ extern void octave_rl_restore_terminal_state (void); +extern char *octave_rl_copy_line (void); + +extern void octave_rl_replace_line (const char *s, int clear_undo); + extern void octave_rl_insert_text (const char *); extern int octave_rl_newline (int, int); @@ -123,6 +129,10 @@ extern rl_startup_hook_fcn_ptr octave_rl_get_startup_hook (void); +extern void octave_rl_set_pre_input_hook (rl_startup_hook_fcn_ptr); + +extern rl_pre_input_hook_fcn_ptr octave_rl_get_pre_input_hook (void); + extern void octave_rl_set_event_hook (rl_event_hook_fcn_ptr f); extern rl_event_hook_fcn_ptr octave_rl_get_event_hook (void); diff -r 2ed5bc680c71 -r 8abae9ea4cb5 run-octave.in --- a/run-octave.in Mon Apr 22 16:37:53 2013 -0400 +++ b/run-octave.in Mon Apr 29 19:13:40 2013 -0400 @@ -80,7 +80,7 @@ OCTAVE_SITE_INITFILE="$top_srcdir/scripts/startup/main-rcfile" \ OCTAVE_DEFAULT_QT_SETTINGS="$builddir/libgui/default-qt-settings" \ -OCTAVE_LOCALE_DIR="$top_srcdir/libgui/languages" \ +OCTAVE_LOCALE_DIR="$builddir/libgui/languages" \ OCTAVE_JAVA_DIR="$builddir/scripts/java" \ exec $builddir/libtool --mode=execute $driver \ "$octave_executable" --no-init-path --path="$LOADPATH" \ diff -r 2ed5bc680c71 -r 8abae9ea4cb5 scripts/help/__unimplemented__.m --- a/scripts/help/__unimplemented__.m Mon Apr 22 16:37:53 2013 -0400 +++ b/scripts/help/__unimplemented__.m Mon Apr 29 19:13:40 2013 -0400 @@ -191,11 +191,8 @@ "dragrect", "dynamicprops", "echodemo", - "ellipj", - "ellipke", "evalc", "exifread", - "expint", "export2wsdlg", "figurepalette", "filebrowser", @@ -335,7 +332,6 @@ "rbbox", "reducepatch", "reducevolume", - "resample", "root", "rotate", "rotate3d", @@ -402,7 +398,6 @@ "visdiff", "volumebounds", "waitfor", - "waterfall", "wavfinfo", "wavplay", "wavrecord", diff -r 2ed5bc680c71 -r 8abae9ea4cb5 scripts/io/strread.m --- a/scripts/io/strread.m Mon Apr 22 16:37:53 2013 -0400 +++ b/scripts/io/strread.m Mon Apr 29 19:13:40 2013 -0400 @@ -315,6 +315,11 @@ for jj = 1:numel (a) ## From right to left to avoid losing track ii = numel (a) - jj + 1; + ## Check for illegal format specifiers + if (isempty (b{ii})) + error ("strread: unknown format specifier #%d ('%s')\n", + ii, fmt_words{idy2(ii)}); + endif if (! (length (fmt_words{idy2(ii)}) == b{ii}(1))) ## Split fmt_words(ii) into % conv specifier and trailing literal fmt_words(idy2(ii)+1 : end+1) = fmt_words(idy2(ii) : end); @@ -985,3 +990,7 @@ %!error strread ("a", "%*f64 %s") %!error strread ("a", "%u32") %!error strread ("a", "%*u32 %d") + +%% Illegal format specifiers +%!test +%!error strread ("1.0", "%z") diff -r 2ed5bc680c71 -r 8abae9ea4cb5 scripts/plot/module.mk --- a/scripts/plot/module.mk Mon Apr 22 16:37:53 2013 -0400 +++ b/scripts/plot/module.mk Mon Apr 29 19:13:40 2013 -0400 @@ -204,6 +204,7 @@ plot/view.m \ plot/waitbar.m \ plot/waitforbuttonpress.m \ + plot/waterfall.m \ plot/whitebg.m \ plot/xlabel.m \ plot/xlim.m \ diff -r 2ed5bc680c71 -r 8abae9ea4cb5 scripts/plot/stemleaf.m --- a/scripts/plot/stemleaf.m Mon Apr 22 16:37:53 2013 -0400 +++ b/scripts/plot/stemleaf.m Mon Apr 29 19:13:40 2013 -0400 @@ -46,16 +46,17 @@ ## @group ## ## Fenced Letter Display -## #% nx|___________________ nx = numel (x) -## M% mi| md | mi median index, md median -## H% hi|hl hu| hs hi lower hinge index, hl,hu hinges, hs h_spread -## 1 |x(1) x(nx)| x(1), x(nx) first and last data value -## _______ -## ______|step |_______ step 1.5*h_spread -## f|ifl ifh| inner fence, lower and higher -## |nfl nfh| # data points within fences -## F|ofl ofh| outer fence, lower and higher -## |nFl nFh| # data points outside outer fences +## #% nx|___________________ nx = numel (x) +## M% mi| md | mi median index, md median +## H% hi|hl hu| hs hi lower hinge index, hl,hu hinges, +## 1 |x(1) x(nx)| hs h_spreadx(1), x(nx) first +## _______ and last data value. +## ______|step |_______ step 1.5*h_spread +## f|ifl ifh| inner fence, lower and higher +## |nfl nfh| no.\ of data points within fences +## F|ofl ofh| outer fence, lower and higher +## |nFl nFh| no.\ of data points outside outer +## fences ## @end group ## @end example ## diff -r 2ed5bc680c71 -r 8abae9ea4cb5 scripts/plot/uigetfile.m --- a/scripts/plot/uigetfile.m Mon Apr 22 16:37:53 2013 -0400 +++ b/scripts/plot/uigetfile.m Mon Apr 29 19:13:40 2013 -0400 @@ -24,7 +24,7 @@ ## @deftypefnx {Function File} {[@dots{}] =} uigetfile (@dots{}, "Position", [@var{px} @var{py}]) ## @deftypefnx {Function File} {[@dots{}] =} uigetfile (@dots{}, "MultiSelect", @var{mode}) ## -## Open a GUI dialog for selecting a file. It returns the filename @var{fname}, +## Open a GUI dialog for selecting a file and return the filename @var{fname}, ## the path to this file @var{fpath}, and the filter index @var{fltidx}. ## @var{flt} contains a (list of) file filter string(s) in one of the following ## formats: @@ -65,19 +65,21 @@ function [retfile, retpath, retindex] = uigetfile (varargin) - defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__"); - funcname = ["__uigetfile_", defaulttoolkit, "__"]; - functype = exist (funcname); - if (! __is_function__ (funcname)) - funcname = "__uigetfile_fltk__"; + if (! __octave_link_enabled__ ()) + defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__"); + funcname = ["__uigetfile_", defaulttoolkit, "__"]; + functype = exist (funcname); if (! __is_function__ (funcname)) - error ("uigetfile: fltk graphics toolkit required"); - elseif (! strcmp (defaulttoolkit, "gnuplot")) - warning ("uigetfile: no implementation for toolkit '%s', using 'fltk' instead", + funcname = "__uigetfile_fltk__"; + if (! __is_function__ (funcname)) + error ("uigetfile: fltk graphics toolkit required"); + elseif (! strcmp (defaulttoolkit, "gnuplot")) + warning ("uigetfile: no implementation for toolkit '%s', using 'fltk' instead", defaulttoolkit); + endif endif endif - + if (nargin > 7) error ("uigetfile: number of input arguments must be less than eight"); endif @@ -183,7 +185,11 @@ endfor endif - [retfile, retpath, retindex] = feval (funcname, outargs{:}); + if (__octave_link_enabled__ ()) + [retfile, retpath, retindex] = __octave_link_file_dialog__ (outargs{:}); + else + [retfile, retpath, retindex] = feval (funcname, outargs{:}); + endif endfunction diff -r 2ed5bc680c71 -r 8abae9ea4cb5 scripts/plot/uiputfile.m --- a/scripts/plot/uiputfile.m Mon Apr 22 16:37:53 2013 -0400 +++ b/scripts/plot/uiputfile.m Mon Apr 29 19:13:40 2013 -0400 @@ -56,16 +56,18 @@ function [retfile, retpath, retindex] = uiputfile (varargin) - defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__"); - funcname = ["__uiputfile_", defaulttoolkit, "__"]; - functype = exist (funcname); - if (! __is_function__ (funcname)) - funcname = "__uiputfile_fltk__"; + if (! __octave_link_enabled__ ()) + defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__"); + funcname = ["__uiputfile_", defaulttoolkit, "__"]; + functype = exist (funcname); if (! __is_function__ (funcname)) - error ("uiputfile: fltk graphics toolkit required"); - elseif (! strcmp (defaulttoolkit, "gnuplot")) - warning ("uiputfile: no implementation for toolkit '%s', using 'fltk' instead", + funcname = "__uiputfile_fltk__"; + if (! __is_function__ (funcname)) + error ("uiputfile: fltk graphics toolkit required"); + elseif (! strcmp (defaulttoolkit, "gnuplot")) + warning ("uiputfile: no implementation for toolkit '%s', using 'fltk' instead", defaulttoolkit); + endif endif endif @@ -117,7 +119,11 @@ endif endif - [retfile, retpath, retindex] = feval (funcname, outargs{:}); + if (__octave_link_enabled__ ()) + [retfile, retpath, retindex] = __octave_link_file_dialog__ (outargs{:}); + else + [retfile, retpath, retindex] = feval (funcname, outargs{:}); + endif endfunction diff -r 2ed5bc680c71 -r 8abae9ea4cb5 scripts/plot/waterfall.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/plot/waterfall.m Mon Apr 29 19:13:40 2013 -0400 @@ -0,0 +1,61 @@ +## Copyright (C) 2013 Mike Miller +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} waterfall (@var{x}, @var{y}, @var{z}) +## @deftypefnx {Function File} {} waterfall (@var{z}) +## @deftypefnx {Function File} {@var{h} =} waterfall (@dots{}) +## Plot a waterfall plot given matrices @var{x}, and @var{y} from +## @code{meshgrid} and a matrix @var{z} corresponding to the @var{x} and +## @var{y} coordinates of the mesh. If @var{x} and @var{y} are vectors, +## then a typical vertex is (@var{x}(j), @var{y}(i), @var{z}(i,j)). Thus, +## columns of @var{z} correspond to different @var{x} values and rows of +## @var{z} correspond to different @var{y} values. +## +## The optional return value @var{h} is a graphics handle to the created +## surface object. +## @seealso{meshgrid, meshz, surf} +## @end deftypefn + +## Author: Mike Miller + +function h = waterfall (varargin) + + tmp = meshz (varargin{:}); + + set (tmp, "meshstyle", "row"); + + ## The gnuplot toolkit does nothing with the meshstyle property currently. + toolkit = get (ancestor (tmp, "figure"), "__graphics_toolkit__"); + if (strcmp (toolkit, "gnuplot")) + warning ("waterfall: may not render correctly using toolkit '%s'", toolkit); + endif + + if (nargout > 0) + h = tmp; + endif + +endfunction + + +%!demo +%! clf; +%! colormap ('default'); +%! [~,~,Z] = peaks (); +%! waterfall (Z); + diff -r 2ed5bc680c71 -r 8abae9ea4cb5 scripts/specfun/ellipke.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/specfun/ellipke.m Mon Apr 29 19:13:40 2013 -0400 @@ -0,0 +1,153 @@ +## Copyright (C) 2001 David Billinghurst +## Copyright (C) 2001 Paul Kienzle +## Copyright (C) 2003 Jaakko Ruohio +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} ellipke (@var{m}) +## @deftypefnx {Function File} {} ellipke (@var{m}, @var{tol}) +## @deftypefnx {Function File} {[@var{k}, @var{e}] =} ellipke (@dots{}) +## Compute complete elliptic integral of the first K(@var{m}) and second +## E(@var{m}) kind. +## +## @var{m} is either real array or scalar with 0 <= m <= 1. +## +## @var{tol} is currently ignored (@sc{Matlab} uses this to allow faster, +## less accurate approximation). +## +## Ref: Abramowitz, Milton and Stegun, Irene A. Handbook of Mathematical +## Functions, Dover, 1965, Chapter 17. +## @seealso{ellipj} +## @end deftypefn + +function [k, e] = ellipke (m) + + if (nargin < 1 || nargin > 2) + print_usage (); + endif + + k = e = zeros (size (m)); + m = m(:); + if any (!isreal (m)) + error ("ellipke must have real m"); + endif + if any (m > 1) + error ("ellipke must have m <= 1"); + endif + + Nmax = 16; + idx = find (m == 1); + if (!isempty (idx)) + k(idx) = Inf; + e(idx) = 1; + endif + + idx = find (m == -Inf); + if (!isempty (idx)) + k(idx) = 0; + e(idx) = Inf; + endif + + ## Arithmetic-Geometric Mean (AGM) algorithm + ## ( Abramowitz and Stegun, Section 17.6 ) + idx = find (m != 1 & m != -Inf); + if (!isempty (idx)) + idx_neg = find (m < 0 & m != -Inf); + mult_k = 1./sqrt (1 - m(idx_neg)); + mult_e = sqrt (1 - m(idx_neg)); + m(idx_neg) = -m(idx_neg)./(1 - m(idx_neg)); + a = ones (length (idx), 1); + b = sqrt (1 - m(idx)); + c = sqrt (m(idx)); + f = 0.5; + sum = f*c.*c; + for n = 2:Nmax + t = (a + b)/2; + c = (a - b)/2; + b = sqrt (a.*b); + a = t; + f = f * 2; + sum = sum + f*c.*c; + if (all (c./a < eps)) break; endif + endfor + if (n >= Nmax) error ("ellipke: not enough workspace"); endif + k(idx) = 0.5*pi./a; + e(idx) = 0.5*pi.*(1 - sum)./a; + k(idx_neg) = mult_k.*k(idx_neg); + e(idx_neg) = mult_e.*e(idx_neg); + endif + +endfunction + +%% Test complete elliptic functions of first and second kind +%% against "exact" solution from Mathematica 3.0 +%!test +%! m = [0.0; 0.01; 0.1; 0.5; 0.9; 0.99; 1.0 ]; +%! [k,e] = ellipke (m); +%! +%! # K(1.0) is really infinity - see below +%! k_exp = [1.5707963267948966192; +%! 1.5747455615173559527; +%! 1.6124413487202193982; +%! 1.8540746773013719184; +%! 2.5780921133481731882; +%! 3.6956373629898746778; +%! 0.0 ]; +%! e_exp = [1.5707963267948966192; +%! 1.5668619420216682912; +%! 1.5307576368977632025; +%! 1.3506438810476755025; +%! 1.1047747327040733261; +%! 1.0159935450252239356; +%! 1.0 ]; +%! if k(7)==Inf, k(7)=0; endif; +%! assert (k, k_exp, 8*eps); +%! assert (e, e_exp, 8*eps); + +%% Test against A&S Table 17.1 +%!test +%! m = [0:5:50]'/100; +%! k_exp = [1.570796326794897; +%! 1.591003453790792; +%! 1.612441348720219; +%! 1.635256732264580; +%! 1.659623598610528; +%! 1.685750354812596; +%! 1.713889448178791; +%! 1.744350597225613; +%! 1.777519371491253; +%! 1.813883936816983; +%! 1.854074677301372 ]; +%! e_exp = [1.570796327; +%! 1.550973352; +%! 1.530757637; +%! 1.510121831; +%! 1.489035058; +%! 1.467462209; +%! 1.445363064; +%! 1.422691133; +%! 1.399392139; +%! 1.375401972; +%! 1.350643881 ]; +%! [k,e] = ellipke (m); +%! assert (k, k_exp, 1e-15); +%! assert (e, e_exp, 1e-8); + +%% Test input validation +%!error ellipke () +%!error ellipke (1,2,3) diff -r 2ed5bc680c71 -r 8abae9ea4cb5 scripts/specfun/expint.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/specfun/expint.m Mon Apr 29 19:13:40 2013 -0400 @@ -0,0 +1,201 @@ +## Copyright (C) 2006 Sylvain Pelissier +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} expint (@var{x}) +## Compute the exponential integral, +## @tex +## $$ +## E_1 (x) = \int_x^\infty {e^{-t} \over t} dt. +## $$ +## @end tex +## @ifnottex +## +## @example +## @group +## infinity +## / +## expint (x) = | exp (-t)/t dt +## / +## x +## @end group +## @end example +## +## @end ifnottex +## @end deftypefn + +function y = expint (x) + + if (nargin != 1) + print_usage (); + endif + + y = expint_E1 (x); + +endfunction + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} expint_E1 (@var{x}) +## Compute the exponential integral, +## @verbatim +## infinity +## / +## expint(x) = | exp(-t)/t dt +## / +## x +## @end verbatim +## @end deftypefn + +function y = expint_E1 (x) + + if (nargin != 1) + print_usage (); + endif + + y = x; + + idx = (imag (x) > 0 & imag (x) != 0); + y(idx) = -expint_Ei (-y(idx)) - i.*pi; + + idx = (imag (x) < 0 & imag (x) != 0); + y(idx) = -expint_Ei (-y(idx)) + i.*pi; + + idx = (real (x) >= 0 & imag (x) == 0); + y(idx) = -expint_Ei (-y(idx)); + + idx = (real (x) < 0 & imag (x) == 0); + y(idx) = -expint_Ei (-y(idx)) - i.*pi; + +endfunction + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} expint_Ei (@var{x}) +## Compute the exponential integral, +## @verbatim +## infinity +## / +## expint_Ei(x) = - | exp(t)/t dt +## / +## -x +## @end verbatim +## @end deftypefn + +function y = expint_Ei (x) + + if (nargin != 1) + print_usage (); + endif + + y = zeros (size (x)); + F = @(x) exp (-x)./x; + s = prod (size (x)); + + for t = 1:s; + if (x(t) < 0 && imag (x(t)) == 0) + y(t) = -quad (F, -x(t), Inf); + else + if (abs (x(t)) > 2 && imag (x(t)) == 0) + y(t) = expint_Ei (2) - quad (F, -x(t), -2); + else + if (abs (x(t)) >= 10) + if (imag (x(t)) <= 0) + a1 = 4.03640; + a2 = 1.15198; + b1 = 5.03637; + b2 = 4.19160; + y(t) = -(x(t).^2 - a1.*x(t) + a2) ... + ./ ((x(t).^2 - b1.*x(t) + b2) .* (-x(t)) .* exp (-x(t))) ... + - i.*pi; + else + y(t) = conj (expint_Ei (conj (x(t)))); + endif; + ## Serie Expansion + else + for k = 1:100; + y(t) = y(t) + x(t).^k ./ (k.*factorial (k)); + endfor + y(t) = 0.577215664901532860606512090082402431 + log (x(t)) + y(t); + endif + endif + endif + endfor +endfunction + +%% Test against A&S Table 5.1 +%!test +%! x = [5:5:50]'/100; +%! gamma = 0.5772156649; +%! y_exp = [0.9876375971; +%! 0.9755453033; +%! 0.9637156702; +%! 0.9521414833; +%! 0.9408157528; +%! 0.9297317075; +%! 0.9188827858; +%! 0.9082626297; +%! 0.8978650778; +%! 0.8876841584 ]; +%! y = (expint (x) + log(x) + gamma) ./ x; +%! assert (y, y_exp, 1e-9); +%!test +%! x = [50:5:95]'/100; +%! y_exp = [0.559773595; +%! 0.503364081; +%! 0.454379503; +%! 0.411516976; +%! 0.373768843; +%! 0.340340813; +%! 0.310596579; +%! 0.284019269; +%! 0.260183939; +%! 0.238737524 ]; +%! y = expint (x); +%! assert (y, y_exp, 1e-9); +%!test +%! x = [100:5:145]'/100; +%! y_exp = [0.219383934; +%! 0.201872813; +%! 0.185990905; +%! 0.171555354; +%! 0.158408437; +%! 0.146413373; +%! 0.135450958; +%! 0.125416844; +%! 0.116219313; +%! 0.107777440 ]; +%! y = expint (x); +%! assert (y, y_exp, 1e-9); +%!test +%! x = [150:5:200]'/100; +%! y_exp = [0.100019582; +%! 0.092882108; +%! 0.086308334; +%! 0.080247627; +%! 0.074654644; +%! 0.069488685; +%! 0.064713129; +%! 0.060294967; +%! 0.056204378; +%! 0.052414380; +%! 0.048900511 ]; +%! y = expint (x); +%! assert (y, y_exp, 1e-9); + +%% Test input validation +%!error expint () +%!error expint (1,2) diff -r 2ed5bc680c71 -r 8abae9ea4cb5 scripts/specfun/module.mk --- a/scripts/specfun/module.mk Mon Apr 22 16:37:53 2013 -0400 +++ b/scripts/specfun/module.mk Mon Apr 29 19:13:40 2013 -0400 @@ -4,6 +4,8 @@ specfun/bessel.m \ specfun/beta.m \ specfun/betaln.m \ + specfun/ellipke.m \ + specfun/expint.m \ specfun/factor.m \ specfun/factorial.m \ specfun/isprime.m \ diff -r 2ed5bc680c71 -r 8abae9ea4cb5 scripts/strings/strsplit.m --- a/scripts/strings/strsplit.m Mon Apr 22 16:37:53 2013 -0400 +++ b/scripts/strings/strsplit.m Mon Apr 29 19:13:40 2013 -0400 @@ -81,7 +81,13 @@ ## @item @var{delimitertype} may take the value of @code{legacy}, ## @code{simple} or @code{regularexpression}. ## If @var{delimitertype} is equal to @code{legacy}, each individual -## character of @var{del} is used to split the input. +## character of @var{del} is used to split the input. For both @code{simple} +## and @code{regularexpression}, the string is split at the boundaries of the +## delimiter string. If @var{delimiter} is a cell-string, then the string +## is split at the boundaries of each of the cells' strings. @var{simple} +## delimiters may contain escaped characters, but are otherwise treated as +## literal strings. +## ## If the specified delimiters are single characters, the default is ## @var{delimitertype} is @code{legacy}. Otherwise the default ## @var{delimitertype} is @code{simple}. @@ -200,11 +206,11 @@ if (strncmpi (args.delimitertype, "simple", length_deltype)) if (iscellstr (del)) - del = cellfun (@(x) regexp2simple (x, false), del, "uniformoutput", - false); + del = cellfun (@do_string_escapes, del, "uniformoutput", false); else - del = regexp2simple (del, false); + del = do_string_escapes (del); endif + del = regexprep (del, '([^\w])', '\\$1'); endif if (rows (str) > 1) @@ -217,8 +223,7 @@ if (isempty (str)) result = {str}; elseif (strncmpi (args.delimitertype, "legacy", length_deltype)) - ## Conventional splitting is preserved for its speed. Its delimiter type - ## + ## Legacy splitting is fast if (! ischar (del)) if (iscell (del) && all (cellfun (@numel, del) < 2)) del = [del{:}]; @@ -228,7 +233,10 @@ "DEL must be a string, or a cell array scalar character elements.") endif endif - ## Split s according to delimiter + if (strcmp (typeinfo (del), "sq_string")) + del = do_string_escapes (del); + endif + ## Split str at each character contained in del if (isscalar (del)) ## Single separator idx = find (str == del); @@ -246,6 +254,16 @@ if (nargout > 1) ## Grab the separators matches = num2cell (str(idx)(:)).'; + if (args.collapsedelimiters) + ## Collapse the consequtive delimiters + ## TODO - is there a vectorized way? + for m = numel(matches):-1:2 + if (strlens(m) == 0) + matches{m-1} = [matches{m-1:m}]; + matches(m) = []; + endif + end + endif endif ## Remove separators. str(idx) = []; @@ -262,35 +280,16 @@ del = sprintf ('%s|', del{:}); del(end) = []; endif - [result, ~, ~, ~, matches] = regexp (str, del, "split"); if (args.collapsedelimiters) - result(cellfun (@isempty, result)) = []; + del = ["(", del, ")+"]; endif - if (strncmpi (args.delimitertype, "simple", length_deltype)) - matches = cellfun (@(x) regexp2simple (x, true), matches, - "uniformoutput", false); - endif + [result, ~, ~, ~, matches] = regexp (str, del, "split"); else error ("strsplit:invalid_delimitertype", sprintf ("strsplit: Invalid DELIMITERTYPE")) endif endfunction -function str = regexp2simple (str, reverse = false) - rep = {'\', '[', ']', '{', '}', '$', '^', '(', ')', '*', '+', '.', '?', '|'}; - if (reverse) - ## backslash must go last - for r = numel(rep):-1:1 - str = strrep (str, [char(92), rep{r}], rep{r}); - endfor - else - ## backslash must go first - for r = 1:numel(rep) - str = strrep (str, rep{r}, [char(92), rep{r}]); - endfor - endif -endfunction - % Mimic the old strsplit() %!assert (cellfun (@numel, strsplit (["a,b,c";"1,2 "], ",")), [1 1 2 1 4]) @@ -312,7 +311,7 @@ %!test %! [s, m] = strsplit (str, {"\\s", "ain"}, true, "delimitertype", "r"); %! assert (s, {"The", "r", "in", "Sp", "stays", "m", "ly", "in", "the", "pl", "."}) -%! assert (m, {" ", "ain", " ", " ", "ain", " ", " ", "ain", " ", " ", " ", "ain"}) +%! assert (m, {" ", "ain ", " ", "ain ", " ", "ain", " ", " ", " ", "ain"}) % Split on " " and "ain", and treat multiple delimiters separately. %!test %! [s, m] = strsplit (str, {" ", "ain"}, "collapsedelimiters", false); @@ -327,10 +326,6 @@ %!assert (strsplit (["a,bc,,de"], ",", false), {"a", "bc", char(ones(1,0)), "de"}) %!assert (strsplit (["a,bc,de"], ",", true), {"a", "bc", "de"}) %!assert (strsplit (["a,bc,de"], {","," "}, true), {"a", "bc", "de"}) -%!test -%! [s, m] = strsplit ("hello \t world", 1); -%! assert (s, {"hello", "world"}); -%! assert (m, {" ", "\t", " "}); %!assert (strsplit ("road to hell", " ", "delimitertype", "r"), {"road", "to", "hell"}) %!assert (strsplit ("road to^hell", '\^| ', "delimitertype", "r"), {"road", "to", "hell"}) @@ -349,6 +344,37 @@ %!assert (strsplit (["a,bc";",de"], ",", true, "delimitertype", "l"), {"a", "bc", "de "}) %!assert (strsplit (["a,bc";",de"], ", ", true, "delimitertype", "l"), {"a", "bc", "de"}) +%!assert (strsplit ("foo\tbar", '\t', "delimitertype", "l"), {"foo", "bar"}) +%!assert (strsplit ("foo\tbar", '\t', "delimitertype", "r"), {"foo", "bar"}) +%!assert (strsplit ("foo\tbar", '\t', "delimitertype", "s"), {"foo", "bar"}) + +## Test "match" for consecutive delmiters +%!test +%! [a, m] = strsplit ("a\t \nb", '\s', 'delimitertype', 'regularexpression', +%! 'collapsedelimiters', false); +%! assert (a, {"a", "", "", "b"}) +%! assert (m, {"\t", " ", "\n"}) +%!test +%! [a, m] = strsplit ("a\t \nb", '\s', false, 'delimitertype', 'regularexpression'); +%! assert (a, {"a", "", "", "b"}) +%! assert (m, {"\t", " ", "\n"}) +%!test +%! [a, m] = strsplit ("a\t \nb", '\s', "delimitertype", "regularexpression"); +%! assert (a, {"a", "b"}) +%! assert (m, {"\t \n"}) +%!test +%! [a, m] = strsplit ("a\t \nb", {"\t", " ", "\n"}, "delimitertype", "simple"); +%! assert (a, {"a", "b"}) +%! assert (m, {"\t \n"}) +%!test +%! [a, m] = strsplit ("a123b", "123", "delimitertype", "legacy"); +%! assert (a, {"a", "b"}) +%! assert (m, {"123"}) +%!test +%! [s, m] = strsplit ("hello \t world", 1); +%! assert (s, {"hello", "world"}); +%! assert (m, {" \t "}); + %% Test input validation %!error strsplit () %!error strsplit ("abc", "b", true, 4) diff -r 2ed5bc680c71 -r 8abae9ea4cb5 test/io.tst --- a/test/io.tst Mon Apr 22 16:37:53 2013 -0400 +++ b/test/io.tst Mon Apr 29 19:13:40 2013 -0400 @@ -335,21 +335,25 @@ %% test/octave.test/io/fopen-1.m %!test -%! arch_list = ["native"; "ieee-le"; "ieee-be"; "vaxd"; "vaxg"; "cray"]; -%! +%! arch_list = {"native"; "ieee-le"; "ieee-be"; "vaxd"; "vaxg"; "cray"}; +%! warning ("off", "Octave:fopen-mode") %! status = 1; %! %! for i = 1:6 -%! arch = deblank (arch_list (i,:)); -%! for j = 1:6 +%! arch = arch_list{i}; +%! for j = 1:4 %! if (j == 1) -%! mode_list = ["w"; "r"; "a"]; +%! mode_list = {"w"; "r"; "a"}; %! elseif (j == 2) -%! mode_list = ["w+"; "r+"; "a+"]; +%! mode_list = {"w+"; "r+"; "a+"}; +%! elseif (j == 3) +%! mode_list = {"W"; "R"; "A"}; +%! elseif (j == 4) +%! mode_list = {"W+"; "R+"; "A+"}; %! endif %! nm = tmpnam (); %! for k = 1:3 -%! mode = deblank (mode_list (k,:)); +%! mode = mode_list{k}; %! [id, err] = fopen (nm, mode, arch); %! if (id < 0) %! __printf_assert__ ("open failed: %s (%s, %s): %s\n", nm, mode, arch, err);