# HG changeset patch # User Michael Goffioul # Date 1381777212 14400 # Node ID bb2fa6e5b3482787740c0252ecf41f5dd8e616b1 # Parent a98902bda11a4514b7b9b0844479bf95b42905fa# Parent a09511ebf7efea3a3cb783880a26d9889f8f03bf maint: periodic merge of default to classdef diff -r a98902bda11a -r bb2fa6e5b348 .dir-locals.el --- a/.dir-locals.el Mon Oct 14 11:28:29 2013 -0400 +++ b/.dir-locals.el Mon Oct 14 15:00:12 2013 -0400 @@ -2,9 +2,10 @@ ((c-file-style . "gnu") (indent-tabs-mode . nil) (fill-column . 72) - (eval . (when (string-match "\\.h\\'" (buffer-file-name)) - (unless (string-match "/gnulib/" (buffer-file-name)) - (c++-mode) - (c-set-style "gnu")))))) + (eval . (when (and (buffer-file-name) + (string-match-p "\\.h\\'" (buffer-file-name)) + (not (string-match-p "/gnulib/" (buffer-file-name)))) + (c++-mode) + (c-set-style "gnu"))))) (change-log-mode . ((indent-tabs-mode . t))) (makefile-mode . ((indent-tabs-mode . t)))) diff -r a98902bda11a -r bb2fa6e5b348 NEWS --- a/NEWS Mon Oct 14 11:28:29 2013 -0400 +++ b/NEWS Mon Oct 14 15:00:12 2013 -0400 @@ -1,3 +1,4 @@ +
 Summary of important user-visible changes for version 4.0:
 ---------------------------------------------------------
 
@@ -1470,3 +1471,4 @@
       spchol2inv          splu
 
 See NEWS.3 for old news.
+
diff -r a98902bda11a -r bb2fa6e5b348 bootstrap.conf --- a/bootstrap.conf Mon Oct 14 11:28:29 2013 -0400 +++ b/bootstrap.conf Mon Oct 14 15:00:12 2013 -0400 @@ -69,6 +69,7 @@ round roundf select + setenv sigaction signal sigprocmask diff -r a98902bda11a -r bb2fa6e5b348 configure.ac diff -r a98902bda11a -r bb2fa6e5b348 libgui/default-qt-settings.in --- a/libgui/default-qt-settings.in Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/default-qt-settings.in Mon Oct 14 15:00:12 2013 -0400 @@ -28,40 +28,49 @@ cursorType=ibeam [MainWindow] -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 +geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xff\xfa\0\0\0\x13\0\0\x4\xc1\0\0\x3\xb4\0\0\0\x4\0\0\0\x31\0\0\x4\xb7\0\0\x3\xaa\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\xb4\0\0\x3#\xfc\x2\0\0\0\x1\xfc\0\0\0@\0\0\x3#\0\0\x1\x7f\0\xff\xff\xff\xfc\x1\0\0\0\x2\xfc\0\0\0\0\0\0\x2\x1c\0\0\0\xb4\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\x1#\0\0\0\x89\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\x1i\0\0\0\xd4\0\0\0\x63\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\x2\x43\0\0\x1 \0\0\0\x87\0\xff\xff\xff\xfc\0\0\x2\"\0\0\x2\x92\0\0\x1,\0\xff\xff\xff\xfc\x2\0\0\0\x2\xfb\0\0\0\x1c\0N\0\x65\0w\0s\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0@\0\0\0\xdb\0\0\0\x14\0\xff\xff\xff\xfc\0\0\x1!\0\0\x2\x42\0\0\0\xfb\x1\0\0\x1e\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\xdc\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\0\x64\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\xae\0\xff\xff\xff\0\0\0\0\0\0\x3#\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)" [DockWidgets] -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) +NewsDockWidget_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0) +TerminalDockWidget_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xfd\xa8\xff\xff\xfd\xee\xff\xff\xfe\v\xff\xff\xfe\v\xff\xff\xfd\xa8\xff\xff\xfd\xee\xff\xff\xfe\v\xff\xff\xfe\v\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\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) +WorkspaceView=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\x1i\0\0\x2\x1b\0\0\x2<\0\0\0\0\0\0\x1i\0\0\x2\x1b\0\0\x2<\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\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) +HistoryDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\x2\x43\0\0\x2\x1b\0\0\x3\x62\0\0\0\0\0\0\x2\x43\0\0\x2\x1b\0\0\x3\x62\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\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) +FilesDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0@\0\0\x2\x1b\0\0\x1\x62\0\0\0\0\0\0\0@\0\0\x2\x1b\0\0\x1\x62\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) +DocumentationDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xfd\x31\xff\xff\xfd^\xff\xff\xfe\v\xff\xff\xfe\v\xff\xff\xfd\x31\xff\xff\xfd^\xff\xff\xfe\v\xff\xff\xfe\v\0\0\0\0\0\0) DocumentationDockWidgetFloating=false DocumentationDockWidgetVisible=true -FileEditor=@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) +FileEditor=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xfc\x18\xff\xff\xfc|\xff\xff\xfe\v\xff\xff\xfe\v\xff\xff\xfc\x18\xff\xff\xfc|\xff\xff\xfe\v\xff\xff\xfe\v\0\0\0\0\0\0) FileEditorFloating=false FileEditorVisible=true +HistoryDockWidget_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0) +FilesDockWidget_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0) +DocumentationDockWidget_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xfd\xa8\xff\xff\xfd\xee\xff\xff\xfe\v\xff\xff\xfe\v\xff\xff\xfd\xa8\xff\xff\xfd\xee\xff\xff\xfe\v\xff\xff\xfe\v\0\0\0\0\0\0) +FileEditor_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x1\xf3\0\0\x1\x8f\0\0\0\0\0\0\0\0\0\0\x1\xf3\0\0\x1\x8f\0\0\0\0\0\0) +WorkspaceView_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0) +NewsDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\x2\"\0\0\0@\0\0\x4\xb3\0\0\x1\x1a\0\0\x2\"\0\0\0@\0\0\x4\xb3\0\0\x1\x1a\0\0\0\0\0\0) +NewsDockWidgetFloating=false +NewsDockWidgetVisible=true +TerminalDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\x2\"\0\0\x1!\0\0\x4\xb3\0\0\x3\x43\0\0\x2\"\0\0\x1!\0\0\x4\xb3\0\0\x3\x43\0\0\0\0\0\0) [workspaceview] 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\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) +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\x2\x12\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\x2\0\0\x1\x90\0\0\0\x4\0\0\0\0\0\0\0\x82\0\0\0\x1\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\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) +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\x2\v\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\x2\v\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 a98902bda11a -r bb2fa6e5b348 libgui/src/icons/graphic_logo_NewsDockWidget.png Binary file libgui/src/icons/graphic_logo_NewsDockWidget.png has changed diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/icons/graphic_logo_ReleaseWidget.png Binary file libgui/src/icons/graphic_logo_ReleaseWidget.png has changed diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/icons/letter_logo_NewsDockWidget.png Binary file libgui/src/icons/letter_logo_NewsDockWidget.png has changed diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/icons/letter_logo_ReleaseWidget.png Binary file libgui/src/icons/letter_logo_ReleaseWidget.png has changed diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/m-editor/file-editor-tab.cc --- a/libgui/src/m-editor/file-editor-tab.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/m-editor/file-editor-tab.cc Mon Oct 14 15:00:12 2013 -0400 @@ -409,6 +409,24 @@ } void +file_editor_tab::context_help (const QWidget *ID, bool doc) +{ + if (ID != this) + return; + + _edit_area->context_help_doc (doc); +} + +void +file_editor_tab::context_edit (const QWidget *ID) +{ + if (ID != this) + return; + + _edit_area->context_edit (); +} + +void file_editor_tab::save_file (const QWidget *ID) { if (ID != this) @@ -466,6 +484,15 @@ } void +file_editor_tab::context_run (const QWidget *ID) +{ + if (ID != this) + return; + + _edit_area->context_run (); +} + +void file_editor_tab::toggle_bookmark (const QWidget *ID) { if (ID != this) @@ -913,6 +940,7 @@ _edit_area->setText (in.readAll ()); QApplication::restoreOverrideCursor (); + _copy_available = false; // no selection yet available set_file_name (fileName); update_window_title (false); // window title (no modification) _edit_area->setModified (false); // loaded file is not modified yet diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/m-editor/file-editor-tab.h --- a/libgui/src/m-editor/file-editor-tab.h Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/m-editor/file-editor-tab.h Mon Oct 14 15:00:12 2013 -0400 @@ -70,12 +70,15 @@ void copy (const QWidget *ID); void cut (const QWidget *ID); void paste (const QWidget *ID); + void context_help (const QWidget *ID, bool); + void context_edit (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 context_run (const QWidget *ID); void toggle_bookmark (const QWidget *ID); void next_bookmark (const QWidget *ID); void previous_bookmark (const QWidget *ID); diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/m-editor/file-editor.cc --- a/libgui/src/m-editor/file-editor.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/m-editor/file-editor.cc Mon Oct 14 15:00:12 2013 -0400 @@ -467,6 +467,23 @@ } void +file_editor::request_context_help (bool) +{ + emit fetab_context_help (_tab_widget->currentWidget (), false); +} +void +file_editor::request_context_doc (bool) +{ + emit fetab_context_help (_tab_widget->currentWidget (), true); +} + +void +file_editor::request_context_edit (bool) +{ + emit fetab_context_edit (_tab_widget->currentWidget ()); +} + +void file_editor::request_save_file (void) { emit fetab_save_file (_tab_widget->currentWidget ()); @@ -492,6 +509,12 @@ } void +file_editor::request_context_run (bool) +{ + emit fetab_context_run (_tab_widget->currentWidget ()); +} + +void file_editor::request_toggle_bookmark (void) { emit fetab_toggle_bookmark (_tab_widget->currentWidget ()); @@ -701,6 +724,7 @@ { _copy_action->setEnabled (copy_available); _cut_action->setEnabled (copy_available); + _context_run_action->setEnabled (copy_available); if (!file_name.isEmpty ()) { @@ -762,9 +786,11 @@ _copy_action = new QAction (QIcon (":/actions/icons/editcopy.png"), tr ("&Copy"), _tool_bar); + _copy_action->setEnabled (false); _cut_action = new QAction (QIcon (":/actions/icons/editcut.png"), tr ("Cu&t"), _tool_bar); + _cut_action->setEnabled (false); _paste_action = new QAction (QIcon (":/actions/icons/editpaste.png"), @@ -794,7 +820,6 @@ _comment_selection_action = new QAction (tr ("&Comment"), _tool_bar); - _uncomment_selection_action = new QAction (tr ("&Uncomment"), _tool_bar); @@ -866,7 +891,10 @@ fileMenu->addAction (new_action); fileMenu->addAction (open_action); fileMenu->addMenu (_mru_file_menu); - + fileMenu->addSeparator (); + _context_edit_action = + fileMenu->addAction (QIcon (), tr ("&Edit Function"), + this, SLOT (request_context_edit (bool))); fileMenu->addSeparator (); fileMenu->addAction (_save_action); fileMenu->addAction (_save_as_action); @@ -925,8 +953,21 @@ QMenu *_run_menu = new QMenu (tr ("&Run"), _menu_bar); _run_menu->addAction (_run_action); + _context_run_action = + _run_menu->addAction (QIcon (), tr ("Run &Selection"), + this, SLOT (request_context_run (bool))); + _context_run_action->setEnabled (false); _menu_bar->addMenu (_run_menu); + QMenu *_help_menu = new QMenu (tr ("&Help"), _menu_bar); + _context_help_action = + _help_menu->addAction (QIcon (), tr ("&Help on Keyword"), + this, SLOT (request_context_help (bool))); + _context_doc_action = + _help_menu->addAction (QIcon (), tr ("&Documentation on Keyword"), + this, SLOT (request_context_doc (bool))); + _menu_bar->addMenu (_help_menu); + // shortcuts set_shortcuts (true); @@ -1107,6 +1148,12 @@ connect (this, SIGNAL (fetab_paste (const QWidget*)), f, SLOT (paste (const QWidget*))); + connect (this, SIGNAL (fetab_context_help (const QWidget*, bool)), + f, SLOT (context_help (const QWidget*, bool))); + + connect (this, SIGNAL (fetab_context_edit (const QWidget*)), + f, SLOT (context_edit (const QWidget*))); + connect (this, SIGNAL (fetab_save_file (const QWidget*)), f, SLOT (save_file (const QWidget*))); @@ -1119,6 +1166,9 @@ connect (this, SIGNAL (fetab_run_file (const QWidget*)), f, SLOT (run_file (const QWidget*))); + connect (this, SIGNAL (fetab_context_run (const QWidget*)), + f, SLOT (context_run (const QWidget*))); + connect (this, SIGNAL (fetab_toggle_bookmark (const QWidget*)), f, SLOT (toggle_bookmark (const QWidget*))); @@ -1199,12 +1249,14 @@ { if (set) { - _comment_selection_action->setShortcut (Qt::ControlModifier + Qt::Key_7); - _uncomment_selection_action->setShortcut (Qt::ControlModifier + Qt::Key_8); + _comment_selection_action->setShortcut (Qt::ControlModifier + Qt::Key_R); + _uncomment_selection_action->setShortcut (Qt::SHIFT + Qt::ControlModifier + Qt::Key_R); _copy_action->setShortcut (QKeySequence::Copy); _cut_action->setShortcut (QKeySequence::Cut); _paste_action->setShortcut (QKeySequence::Paste); + _context_help_action->setShortcut (QKeySequence::HelpContents); + _context_doc_action->setShortcut (Qt::SHIFT + Qt::Key_F1); _find_action->setShortcut (QKeySequence::Find); _goto_line_action->setShortcut (Qt::ControlModifier+ Qt::Key_G); @@ -1214,8 +1266,10 @@ _toggle_bookmark_action->setShortcut (Qt::Key_F7); _print_action->setShortcut (QKeySequence::Print); - _run_action->setShortcut (Qt::ControlModifier+ Qt::Key_R); + _run_action->setShortcut (Qt::Key_F5); + _context_run_action->setShortcut (Qt::Key_F9); + _context_edit_action->setShortcut (Qt::ControlModifier + Qt::Key_E); _save_action->setShortcut (QKeySequence::Save); _save_as_action->setShortcut (QKeySequence::SaveAs); _close_action->setShortcut (QKeySequence::Close); @@ -1233,6 +1287,7 @@ _copy_action->setShortcut (no_key); _cut_action->setShortcut (no_key); _paste_action->setShortcut (no_key); + _context_help_action->setShortcut (no_key); _find_action->setShortcut (no_key); _goto_line_action->setShortcut (no_key); @@ -1243,7 +1298,9 @@ _print_action->setShortcut (no_key); _run_action->setShortcut (no_key); + _context_run_action->setShortcut (no_key); + _context_edit_action->setShortcut (no_key); _save_action->setShortcut (no_key); _save_as_action->setShortcut (no_key); _close_action->setShortcut (no_key); @@ -1261,9 +1318,9 @@ _comment_selection_action->setEnabled (have_tabs); _uncomment_selection_action->setEnabled (have_tabs); - _copy_action->setEnabled (have_tabs); - _cut_action->setEnabled (have_tabs); _paste_action->setEnabled (have_tabs); + _context_help_action->setEnabled (have_tabs); + _context_doc_action->setEnabled (have_tabs); _find_action->setEnabled (have_tabs); _goto_line_action->setEnabled (have_tabs); @@ -1271,10 +1328,12 @@ _next_bookmark_action->setEnabled (have_tabs); _previous_bookmark_action->setEnabled (have_tabs); _toggle_bookmark_action->setEnabled (have_tabs); + _remove_bookmark_action->setEnabled (have_tabs); _print_action->setEnabled (have_tabs); _run_action->setEnabled (have_tabs); + _context_edit_action->setEnabled (have_tabs); _save_action->setEnabled (have_tabs); _save_as_action->setEnabled (have_tabs); _close_action->setEnabled (have_tabs); diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/m-editor/file-editor.h --- a/libgui/src/m-editor/file-editor.h Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/m-editor/file-editor.h Mon Oct 14 15:00:12 2013 -0400 @@ -74,10 +74,13 @@ void fetab_copy (const QWidget* ID); void fetab_cut (const QWidget* ID); void fetab_paste (const QWidget* ID); + void fetab_context_help (const QWidget* ID, bool); + void fetab_context_edit (const QWidget* ID); void fetab_save_file (const QWidget* ID); void fetab_save_file_as (const QWidget* ID); void fetab_print_file (const QWidget* ID); void fetab_run_file (const QWidget* ID); + void fetab_context_run (const QWidget* ID); void fetab_toggle_bookmark (const QWidget* ID); void fetab_next_bookmark (const QWidget* ID); void fetab_previous_bookmark (const QWidget* ID); @@ -114,9 +117,13 @@ void request_copy (void); void request_cut (void); void request_paste (void); + void request_context_help (bool); + void request_context_doc (bool); + void request_context_edit (bool); void request_save_file (void); void request_save_file_as (void); void request_run_file (void); + void request_context_run (bool); void request_toggle_bookmark (void); void request_next_bookmark (void); void request_previous_bookmark (void); @@ -190,6 +197,8 @@ QAction *_copy_action; QAction *_cut_action; QAction *_paste_action; + QAction *_context_help_action; + QAction *_context_doc_action; QAction *_find_action; QAction *_goto_line_action; @@ -201,7 +210,9 @@ QAction *_print_action; QAction *_run_action; + QAction *_context_run_action; + QAction *_context_edit_action; QAction *_save_action; QAction *_save_as_action; QAction *_close_action; diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/m-editor/octave-qscintilla.cc --- a/libgui/src/m-editor/octave-qscintilla.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/m-editor/octave-qscintilla.cc Mon Oct 14 15:00:12 2013 -0400 @@ -40,6 +40,53 @@ octave_qscintilla::~octave_qscintilla () { } +void +octave_qscintilla::get_global_textcursor_pos (QPoint *global_pos, QPoint *local_pos) +{ + long position = SendScintilla (QsciScintillaBase::SCI_GETCURRENTPOS); + long point_x = SendScintilla + (QsciScintillaBase::SCI_POINTXFROMPOSITION,0,position); + long point_y = SendScintilla + (QsciScintillaBase::SCI_POINTYFROMPOSITION,0,position); + *local_pos = QPoint (point_x,point_y); // local cursor position + *global_pos = mapToGlobal (*local_pos); // global position of cursor +} + +// determine the actual word and whether we are in an octave or matlab script +bool +octave_qscintilla::get_actual_word () +{ + QPoint global_pos, local_pos; + get_global_textcursor_pos (&global_pos, &local_pos); + _word_at_cursor = wordAtPoint (local_pos); + QString lexer_name = lexer ()->lexer (); + return ((lexer_name == "octave" || lexer_name == "matlab") + && !_word_at_cursor.isEmpty ()); +} + +// call documentation or help on the current word +void +octave_qscintilla::context_help_doc (bool documentation) +{ + if (get_actual_word ()) + contextmenu_help_doc (documentation); +} + +// call edit the function related to the current word +void +octave_qscintilla::context_edit () +{ + if (hasSelectedText ()) + contextmenu_edit (true); +} + +// call edit the function related to the current word +void +octave_qscintilla::context_run () +{ + if (hasSelectedText ()) + contextmenu_run (true); +} #ifdef HAVE_QSCI_VERSION_2_6_0 // context menu requested @@ -58,13 +105,7 @@ } else { // context menu by keyboard or other: get point of text cursor - long position = SendScintilla (QsciScintillaBase::SCI_GETCURRENTPOS); - long point_x = SendScintilla - (QsciScintillaBase::SCI_POINTXFROMPOSITION,0,position); - long point_y = SendScintilla - (QsciScintillaBase::SCI_POINTYFROMPOSITION,0,position); - local_pos = QPoint (point_x,point_y); // local cursor position - global_pos = mapToGlobal (local_pos); // global position of cursor + get_global_textcursor_pos (&global_pos, &local_pos); QRect editor_rect = geometry (); // editor rect mapped to global editor_rect.moveTopLeft (parentWidget ()->mapToGlobal (editor_rect.topLeft ())); @@ -82,8 +123,18 @@ { _word_at_cursor = wordAtPoint (local_pos); if (!_word_at_cursor.isEmpty ()) - context_menu->addAction (tr ("help") + " " + _word_at_cursor, - this, SLOT (contextmenu_help (bool))); + { + context_menu->addAction (tr ("Help on") + " " + _word_at_cursor, + this, SLOT (contextmenu_help (bool))); + context_menu->addAction (tr ("Documentation on") + " " + _word_at_cursor, + this, SLOT (contextmenu_doc (bool))); + context_menu->addAction (tr ("Edit") + " " + _word_at_cursor, + this, SLOT (contextmenu_edit (bool))); + } + context_menu->addSeparator (); // separator before custom entries + if (hasSelectedText ()) + context_menu->addAction (tr ("&Run Selection"), + this, SLOT (contextmenu_run (bool))); } // finaly show the menu @@ -92,11 +143,40 @@ #endif -// handle the menu entry for calling help +// handle the menu entry for calling help or doc +void +octave_qscintilla::contextmenu_doc (bool) +{ + contextmenu_help_doc (true); +} void octave_qscintilla::contextmenu_help (bool) { - QString command = "help " + _word_at_cursor; + contextmenu_help_doc (false); +} + +// common function with flag for documentation +void +octave_qscintilla::contextmenu_help_doc (bool documentation) +{ + QString command; + if (documentation) + command = "doc "; + else + command = "help "; + emit execute_command_in_terminal_signal (command + _word_at_cursor); +} + +void +octave_qscintilla::contextmenu_edit (bool) +{ + emit execute_command_in_terminal_signal (QString("edit ") + _word_at_cursor); +} + +void +octave_qscintilla::contextmenu_run (bool) +{ + QString command = selectedText (); emit execute_command_in_terminal_signal (command); } diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/m-editor/octave-qscintilla.h --- a/libgui/src/m-editor/octave-qscintilla.h Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/m-editor/octave-qscintilla.h Mon Oct 14 15:00:12 2013 -0400 @@ -41,6 +41,11 @@ #ifdef HAVE_QSCI_VERSION_2_6_0 virtual void contextMenuEvent (QContextMenuEvent *e); #endif + void context_help_doc (bool); + void context_edit (); + void context_run (); + void get_global_textcursor_pos (QPoint *global_pos, QPoint *local_pos); + bool get_actual_word (); signals: @@ -49,6 +54,10 @@ private slots: void contextmenu_help (bool); + void contextmenu_doc (bool); + void contextmenu_help_doc (bool); + void contextmenu_edit (bool); + void contextmenu_run (bool); private: diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/main-window.cc --- a/libgui/src/main-window.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/main-window.cc Mon Oct 14 15:00:12 2013 -0400 @@ -69,6 +69,7 @@ : QMainWindow (p), _workspace_model (new workspace_model ()), status_bar (new QStatusBar ()), + news_window (new news_dock_widget (this)), command_window (new terminal_dock_widget (this)), history_window (new history_dock_widget (this)), file_browser_window (new files_dock_widget (this)), @@ -93,6 +94,7 @@ // to its original pipe to capture error messages at exit. delete editor_window; // first one for dialogs of modified editor-tabs + delete news_window; delete command_window; delete workspace_window; delete doc_browser_window; @@ -247,6 +249,31 @@ } void +main_window::display_release_notes (void) +{ + display_url_in_window (QUrl ("file://" OCTAVE_OCTETCDIR "/NEWS")); +} + +void +main_window::display_url_in_window (const QUrl& url) +{ + QWidget *w = new QWidget; + + QTextBrowser *browser = new QTextBrowser (w); + browser->setSource (url); + + QVBoxLayout *vlayout = new QVBoxLayout; + vlayout->addWidget (browser); + + w->setLayout (vlayout); + w->setWindowTitle (tr ("Octave Release Notes")); + w->setWindowIcon (QIcon (_release_notes_icon)); + w->show (); + w->raise (); + w->activateWindow (); +} + +void main_window::open_bug_tracker_page (void) { QDesktopServices::openUrl (QUrl ("http://octave.org/bugs.html")); @@ -341,6 +368,11 @@ widget->setWindowIcon (QIcon (icon)); } } + if (widget_icon_data[icon_set_found].name != "NONE") + _release_notes_icon = widget_icon_data[icon_set_found].path + + "ReleaseWidget.png"; + else + _release_notes_icon = ":/actions/icons/logo.png"; int icon_size = settings->value ("toolbar_icon_size",24).toInt (); _main_tool_bar->setIconSize (QSize (icon_size,icon_size)); @@ -653,14 +685,8 @@ void main_window::connect_visibility_changed (void) { - command_window->connect_visibility_changed (); - history_window->connect_visibility_changed (); - file_browser_window->connect_visibility_changed (); - doc_browser_window->connect_visibility_changed (); -#ifdef HAVE_QSCINTILLA - editor_window->connect_visibility_changed (); -#endif - workspace_window->connect_visibility_changed (); + foreach (octave_dock_widget *widget, dock_widget_list ()) + widget->connect_visibility_changed (); } void @@ -863,6 +889,7 @@ | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks); + addDockWidget (Qt::RightDockWidgetArea, news_window); addDockWidget (Qt::RightDockWidgetArea, command_window); addDockWidget (Qt::RightDockWidgetArea, doc_browser_window); tabifyDockWidget (command_window, doc_browser_window); @@ -1021,6 +1048,8 @@ construct_window_menu (menu_bar); construct_help_menu (menu_bar); + + construct_news_menu (menu_bar); } void @@ -1266,6 +1295,9 @@ QAction *show_documentation_action = construct_window_menu_item (window_menu, tr ("Show Documentation"), true, ctrl_shift + Qt::Key_5); + QAction *show_news_action = construct_window_menu_item + (window_menu, tr ("Show News Window"), true, ctrl_shift + Qt::Key_6); + window_menu->addSeparator (); QAction *command_window_action = construct_window_menu_item @@ -1286,6 +1318,9 @@ QAction *documentation_action = construct_window_menu_item (window_menu, tr ("Documentation"), false, ctrl + Qt::Key_5); + QAction *news_action = construct_window_menu_item + (window_menu, tr ("News"), false, ctrl + Qt::Key_6); + window_menu->addSeparator (); QAction *reset_windows_action @@ -1323,6 +1358,12 @@ show_editor_action, SLOT (setChecked (bool))); #endif + connect (show_news_action, SIGNAL (toggled (bool)), + news_window, SLOT (setVisible (bool))); + + connect (news_window, SIGNAL (active_changed (bool)), + show_news_action, SLOT (setChecked (bool))); + connect (show_documentation_action, SIGNAL (toggled (bool)), doc_browser_window, SLOT (setVisible (bool))); @@ -1346,6 +1387,9 @@ editor_window, SLOT (focus ())); #endif + connect (news_action, SIGNAL (triggered ()), + news_window, SLOT (focus ())); + connect (documentation_action, SIGNAL (triggered ()), doc_browser_window, SLOT (focus ())); @@ -1420,6 +1464,24 @@ } void +main_window::construct_news_menu (QMenuBar *p) +{ + QMenu *news_menu = p->addMenu (tr ("&News")); + + QAction *release_notes_action + = news_menu->addAction (tr ("Release Notes")); + + QAction *current_news_action + = news_menu->addAction (tr ("Community News")); + + connect (release_notes_action, SIGNAL (triggered ()), + this, SLOT (display_release_notes ())); + + connect (current_news_action, SIGNAL (triggered ()), + news_window, SLOT (show ())); +} + +void main_window::construct_tool_bar (void) { _main_tool_bar = addToolBar ("Main"); diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/main-window.h --- a/libgui/src/main-window.h Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/main-window.h Mon Oct 14 15:00:12 2013 -0400 @@ -51,6 +51,7 @@ #include "workspace-view.h" #include "history-dock-widget.h" #include "files-dock-widget.h" +#include "news-dock-widget.h" #include "terminal-dock-widget.h" #include "documentation-dock-widget.h" #include "octave-qt-link.h" @@ -108,6 +109,7 @@ void new_file (const QString& commands = QString ()); void open_file (const QString& file_name = QString ()); void open_online_documentation_page (void); + void display_release_notes (void); void open_bug_tracker_page (void); void open_octave_packages_page (void); void open_agora_page (void); @@ -216,8 +218,12 @@ void construct_help_menu (QMenuBar *p); void construct_documentation_menu (QMenu *p); + void construct_news_menu (QMenuBar *p); + void construct_tool_bar (void); + void display_url_in_window (const QUrl& url); + void establish_octave_link (void); void save_workspace_callback (const std::string& file); @@ -263,6 +269,7 @@ QStatusBar *status_bar; // Subwindows. + news_dock_widget *news_window; terminal_dock_widget *command_window; history_dock_widget *history_window; files_dock_widget *file_browser_window; @@ -272,6 +279,7 @@ QList dock_widget_list () { QList list = QList (); + list.append (static_cast (news_window)); list.append (static_cast (command_window)); list.append (static_cast (history_window)); list.append (static_cast (file_browser_window)); @@ -283,7 +291,10 @@ return list; } + QString _release_notes_icon; + QToolBar *_main_tool_bar; + QMenu *_debug_menu; QAction *_debug_continue; diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/module.mk --- a/libgui/src/module.mk Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/module.mk Mon Oct 14 15:00:12 2013 -0400 @@ -36,8 +36,10 @@ src/icons/graphic_logo_FileEditor.png \ src/icons/graphic_logo_FilesDockWidget.png \ src/icons/graphic_logo_HistoryDockWidget.png \ + src/icons/graphic_logo_NewsDockWidget.png \ src/icons/graphic_logo_TerminalDockWidget.png \ src/icons/graphic_logo_WorkspaceView.png \ + src/icons/graphic_logo_ReleaseWidget.png \ src/icons/help_index.png \ src/icons/home.png \ src/icons/icons_license \ @@ -46,8 +48,10 @@ src/icons/letter_logo_FileEditor.png \ src/icons/letter_logo_FilesDockWidget.png \ src/icons/letter_logo_HistoryDockWidget.png \ + src/icons/letter_logo_NewsDockWidget.png \ src/icons/letter_logo_TerminalDockWidget.png \ src/icons/letter_logo_WorkspaceView.png \ + src/icons/letter_logo_ReleaseWidget.png \ src/icons/logo.png \ src/icons/ok.png \ src/icons/question.png \ @@ -85,6 +89,7 @@ src/moc-main-window.cc \ src/moc-octave-qt-link.cc \ src/moc-settings-dialog.cc \ + src/moc-news-dock-widget.cc \ src/moc-terminal-dock-widget.cc \ src/moc-color-picker.cc \ src/moc-welcome-wizard.cc \ @@ -99,8 +104,7 @@ octave_gui_RC = src/qrc-resource.cc octave_gui_UI = \ - src/settings-dialog.ui \ - src/welcome-wizard.ui + src/settings-dialog.ui octave_gui_UI_H = $(patsubst src/%.ui, src/ui-%.h, $(octave_gui_UI)) @@ -125,6 +129,7 @@ src/qtinfo/webinfo.h \ src/resource-manager.h \ src/settings-dialog.h \ + src/news-dock-widget.h \ src/terminal-dock-widget.h \ src/color-picker.h \ src/welcome-wizard.h \ @@ -151,6 +156,7 @@ src/qtinfo/webinfo.cc \ src/resource-manager.cc \ src/settings-dialog.cc \ + src/news-dock-widget.cc \ src/terminal-dock-widget.cc \ src/color-picker.cc \ src/welcome-wizard.cc \ diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/news-dock-widget.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/src/news-dock-widget.cc Mon Oct 14 15:00:12 2013 -0400 @@ -0,0 +1,137 @@ +/* + +Copyright (C) 2013 John W. Eaton + +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 + +#include + +#include "news-dock-widget.h" + +#include "Array.h" +#include "str-vec.h" +#include "url-transfer.h" + +#include "version.h" + +news_dock_widget::news_dock_widget (QWidget *p) + : octave_dock_widget (p), browser (new QTextBrowser (this)) +{ + setObjectName ("NewsDockWidget"); + setWindowIcon (QIcon (":/icons/logo.png")); + set_title (tr ("Community News")); + + browser->setObjectName ("OctaveNews"); + browser->setOpenExternalLinks (true); + + setWidget (browser); + + load_news (); +} + +void +news_dock_widget::load_news (void) +{ + QString base_url = "http://octave.org"; + QString page = "community-news.html"; + + QThread *worker_thread = new QThread; + + news_reader *reader = new news_reader (base_url, page); + + reader->moveToThread (worker_thread); + + connect (reader, SIGNAL (display_news_signal (const QString&)), + this, SLOT (display_news (const QString&))); + + connect (worker_thread, SIGNAL (started (void)), reader, SLOT (process ())); + + connect (reader, SIGNAL (finished (void)), worker_thread, SLOT (quit ())); + + connect (reader, SIGNAL (finished (void)), reader, SLOT (deleteLater ())); + + connect (worker_thread, SIGNAL (finished (void)), + worker_thread, SLOT (deleteLater ())); + + worker_thread->start (); +} + +static const char fixed_news[] = "\n\ +\n\ +

\n\ +This window will be used to inform you about Octave community events.\n\ +Octave may show it to you even if you've chosen hide the window by\n\ +default. We'll try not to bother you too much, but we do want to keep\n\ +you up to date with the latest information about important bug fixes,\n\ +new releases, or any other news that all Octave users should be aware of.\n\ +

\n\ +

\n\ +Currently, Octave's community news source seems to be unavailable.\n\ +For the latest news, please check\n\ +http://octave.org/community-news.html\n\ +when you have a connection to the web.\n\ +

\n\ +

\n\ +— The Octave Developers, " OCTAVE_RELEASE_DATE "\n\ +\n\ +\n"; + +void +news_dock_widget::display_news (const QString& news) +{ + if (news.contains ("this-is-the-gnu-octave-community-news-page")) + { + browser->setHtml (news); + + if (news.contains ("critical-news-event") && ! isVisible ()) + setVisible (true); + } + else + browser->setHtml (fixed_news); +} + +void +news_reader::process (void) +{ + // Run this part in a separate thread so Octave can continue to run + // while we wait for the page to load. Then emit the signal to + // display it when we have the page contents. + + QString url = base_url + "/" + page; + std::ostringstream buf; + url_transfer octave_dot_org (url.toStdString (), buf); + + Array param; + octave_dot_org.http_get (param); + + QString html_text; + + if (octave_dot_org.good ()) + html_text = QString::fromStdString (buf.str ()); + + emit display_news_signal (html_text); + + emit finished (); +} diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/news-dock-widget.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/src/news-dock-widget.h Mon Oct 14 15:00:12 2013 -0400 @@ -0,0 +1,74 @@ +/* + +Copyright (C) 2013 John W. Eaton + +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 +. + +*/ + +#ifndef NEWSDOCKWIDGET_H +#define NEWSDOCKWIDGET_H + +#include + +#include "octave-dock-widget.h" + +class news_dock_widget : public octave_dock_widget +{ + Q_OBJECT + +public: + + news_dock_widget (QWidget *parent = 0); + + void load_news (void); + +protected slots: + + void display_news (const QString& news); + +private: + + QTextBrowser *browser; +}; + +class news_reader : public QObject +{ + Q_OBJECT + +public: + + news_reader (const QString& xbase_url, const QString& xpage) + : QObject (), base_url (xbase_url), page (xpage) { } + +public slots: + + void process (void); + +signals: + + void display_news_signal (const QString& news); + + void finished (void); + +private: + + QString base_url; + QString page; +}; + +#endif // NEWSDOCKWIDGET_H diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/octave-gui.cc --- a/libgui/src/octave-gui.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/octave-gui.cc Mon Oct 14 15:00:12 2013 -0400 @@ -25,6 +25,7 @@ #endif #include +#include #include #include @@ -97,6 +98,9 @@ QApplication application (argc, argv); + // Set the codec for all strings + QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); + // install translators for the gui and qt text QTranslator gui_tr, qt_tr, qsci_tr; resource_manager::config_translators (&qt_tr,&qsci_tr,&gui_tr); diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/resource.qrc --- a/libgui/src/resource.qrc Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/resource.qrc Mon Oct 14 15:00:12 2013 -0400 @@ -46,16 +46,20 @@ icons/db_stop.png icons/letter_logo_FilesDockWidget.png icons/letter_logo_FileEditor.png + icons/letter_logo_NewsDockWidget.png icons/letter_logo_TerminalDockWidget.png icons/letter_logo_HistoryDockWidget.png icons/letter_logo_WorkspaceView.png icons/letter_logo_DocumentationDockWidget.png + icons/letter_logo_ReleaseWidget.png icons/graphic_logo_FilesDockWidget.png icons/graphic_logo_FileEditor.png + icons/graphic_logo_NewsDockWidget.png icons/graphic_logo_TerminalDockWidget.png icons/graphic_logo_HistoryDockWidget.png icons/graphic_logo_WorkspaceView.png icons/graphic_logo_DocumentationDockWidget.png + icons/graphic_logo_ReleaseWidget.png icons/widget-close.png icons/widget-dock.png icons/widget-undock.png diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/welcome-wizard.cc --- a/libgui/src/welcome-wizard.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/welcome-wizard.cc Mon Oct 14 15:00:12 2013 -0400 @@ -1,5 +1,6 @@ /* +Copyright (C) 2013 John W. Eaton Copyright (C) 2011-2012 Jacob Dawid This file is part of Octave. @@ -24,21 +25,100 @@ #include #endif +#include +#include +#include +#include +#include + #include "welcome-wizard.h" #include "resource-manager.h" -#include "ui-welcome-wizard.h" welcome_wizard::welcome_wizard (QWidget *p) - : QDialog (p), _ui (new Ui::welcome_wizard) + : QDialog (p) { - _ui->setupUi (this); - QString label_text = _ui->label_config_file->text (); - label_text.replace (QString ("__%1__"), - resource_manager::get_settings_file ()); - _ui->label_config_file->setText (label_text); + setWindowTitle (tr ("Welcome to GNU Octave")); + + setEnabled (true); + resize (600, 480); + setMinimumSize (QSize (600, 480)); + + + QVBoxLayout *page_layout = new QVBoxLayout (this); + setLayout (page_layout); + + QHBoxLayout *message_and_logo = new QHBoxLayout; + + QVBoxLayout *message = new QVBoxLayout; + + QLabel *title = new QLabel (tr ("Welcome to Octave!")); + QFont ft; + ft.setPointSize (20); + title->setFont (ft); + + QLabel *msg_1 = new QLabel (tr ("You seem to be using the Octave graphical interface for the first time on this computer. Click 'Finish' to write a configuration file and launch Octave GUI.")); + msg_1->setWordWrap (true); + + QString msg_2_text = QString (tr ("The configuration file is stored in %1. " + "If that file exists, you will not see this " + "dialog when Octave starts again."). + arg (resource_manager::get_settings_file ())); + QLabel *msg_2 = new QLabel (msg_2_text); + msg_2->setWordWrap (true); + + message->addWidget (title); + message->addWidget (msg_1); + message->addWidget (msg_2); + + QSpacerItem *logo_filler = new QSpacerItem (40, 20, QSizePolicy::Expanding, + QSizePolicy::Minimum); + + QLabel *logo = new QLabel; + QPixmap logo_pixmap (":/actions/icons/logo.png"); + logo->setPixmap (logo_pixmap.scaledToHeight (150)); + + message_and_logo->addLayout (message); + message_and_logo->addItem (logo_filler); + message_and_logo->addWidget (logo); + + QLabel *links = new QLabel + (tr ("\n" + "\n" + "\n" + "

For more information about Octave:

\n" + "
    \n" + "
  • Visit http://octave.org
  • \n" + "
  • Get the documentation online as html- or pdf-document
  • \n" + "
  • Open the documentation browser of Octave GUI with the help menu
  • \n" + "
\n" + ""), + this); + links->setWordWrap (true); + links->setOpenExternalLinks (true); + + QSpacerItem *hfill = new QSpacerItem (40, 20, QSizePolicy::Expanding, + QSizePolicy::Minimum); + + QPushButton *finish_button = new QPushButton; + finish_button->setText (tr ("Finish")); + + QSpacerItem *vspace = new QSpacerItem (20, 40, QSizePolicy::Minimum); + + QHBoxLayout *button_bar = new QHBoxLayout; + + button_bar->addItem (hfill); + button_bar->addWidget (finish_button); + + QSpacerItem *vfill = new QSpacerItem (20, 40, QSizePolicy::Minimum, + QSizePolicy::Expanding); + + page_layout->addLayout (message_and_logo); + page_layout->addWidget (links); + page_layout->addItem (vspace); + page_layout->addLayout (button_bar); + page_layout->addItem (vfill); + + connect (finish_button, SIGNAL (clicked ()), this, SLOT (accept ())); } - -welcome_wizard::~welcome_wizard() -{ - delete _ui; -} diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/welcome-wizard.h --- a/libgui/src/welcome-wizard.h Mon Oct 14 11:28:29 2013 -0400 +++ b/libgui/src/welcome-wizard.h Mon Oct 14 15:00:12 2013 -0400 @@ -1,5 +1,6 @@ /* +Copyright (C) 2013 John W. Eaton Copyright (C) 2011-2012 Jacob Dawid This file is part of Octave. @@ -25,22 +26,15 @@ #include -namespace Ui { - class welcome_wizard; -} - class welcome_wizard : public QDialog { Q_OBJECT - public: - explicit welcome_wizard (QWidget *parent = 0); - ~welcome_wizard (); +public: -public slots: + welcome_wizard (QWidget *parent = 0); -private: - Ui::welcome_wizard *_ui; + ~welcome_wizard (void) { } }; #endif // WELCOMEWIZARD_H diff -r a98902bda11a -r bb2fa6e5b348 libgui/src/welcome-wizard.ui --- a/libgui/src/welcome-wizard.ui Mon Oct 14 11:28:29 2013 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ - - - welcome_wizard - - - true - - - - 0 - 0 - 480 - 320 - - - - - 480 - 320 - - - - - 480 - 320 - - - - Welcome to GNU Octave - - - - - - - - - 20 - - - - Welcome to Octave! - - - - - - - You seem to be using the Octave graphical interface for the first time on this computer. Click 'Finish' to write a configuration file and launch Octave GUI. - - - true - - - - - - - The configuration file is stored in __%1__. If that file exists, you will not see this dialog when Octave starts again. - - - true - - - - - - - <html><head/><body><p>For more information about Octave,</p> -<ul> -<li>visit <a href="http://octave.org"><span style=" text-decoration: underline; color:#0000ff;">http://octave.org</span></a>,</li> -<li> get the documentation online as <a href="http://www.gnu.org/software/octave/doc/interpreter/index.html"><span style=" text-decoration: underline; color:#0000ff;">html</span></a>- or <a href="http://www.gnu.org/software/octave/octave.pdf"><span style=" text-decoration: underline; color:#0000ff;">pdf</span></a>-document, or</li> -<li>open the documentation browser of Octave GUI with the help menu.</li> -</ul> -</body></html> - - - true - - - true - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Finish - - - - - - - - - - - - - finishButton - clicked() - welcome_wizard - accept() - - - 577 - 372 - - - 323 - 199 - - - - - diff -r a98902bda11a -r bb2fa6e5b348 libinterp/corefcn/data.cc --- a/libinterp/corefcn/data.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libinterp/corefcn/data.cc Mon Oct 14 15:00:12 2013 -0400 @@ -7343,10 +7343,13 @@ reinterpret_cast (in.data ()); \ char* out; \ if (! error_state \ - && octave_base64_encode (inc, inlen, &out)) \ - retval(0) = octave_value (out); \ + && octave_base64_encode (inc, inlen, &out)) \ + { \ + retval(0) = octave_value (out); \ + ::free (out); \ + } \ } - + MAKE_INT_BRANCH(int8) else MAKE_INT_BRANCH(int16) else MAKE_INT_BRANCH(int32) @@ -7370,7 +7373,10 @@ char* out; if (! error_state && octave_base64_encode (inc, inlen, &out)) - retval(0) = octave_value (out); + { + retval(0) = octave_value (out); + ::free (out); + } } else { @@ -7382,7 +7388,10 @@ char* out; if (! error_state && octave_base64_encode (inc, inlen, &out)) - retval(0) = octave_value (out); + { + retval(0) = octave_value (out); + ::free (out); + } } } return retval; diff -r a98902bda11a -r bb2fa6e5b348 libinterp/corefcn/debug.cc --- a/libinterp/corefcn/debug.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libinterp/corefcn/debug.cc Mon Oct 14 15:00:12 2013 -0400 @@ -1121,26 +1121,41 @@ size_t nskip = 0; - if (args.length () == 1) + octave_idx_type len = args.length (); + + // dbstack accepts up to 2 arguments. + + if (len == 1 || len == 2) { int n = 0; - octave_value arg = args(0); - - if (arg.is_string ()) + for (octave_idx_type i = 0; i < len && ! error_state; i++) { - std::string s_arg = arg.string_value (); + octave_value arg = args(i); + + if (arg.is_string ()) + { + std::string s_arg = arg.string_value (); + + // Skip "-completenames", octave returns full names anyway. - n = atoi (s_arg.c_str ()); + if (s_arg == "-completenames") + continue; + + n = atoi (s_arg.c_str ()); + } + else + n = arg.int_value (); + + if (! error_state && n <= 0) + error ("dbstack: N must be a non-negative integer"); } - else - n = args(0).int_value (); if (n > 0) nskip = n; - else - error ("dbstack: N must be a non-negative integer"); } + else if (len) + print_usage (); if (! error_state) { @@ -1214,10 +1229,15 @@ "-*- texinfo -*-\n\ @deftypefn {Command} {} dbstack\n\ @deftypefnx {Command} {} dbstack @var{n}\n\ +@deftypefnx {Command} {} dbstack @var{-completenames}\n\ @deftypefnx {Built-in Function} {[@var{stack}, @var{idx}] =} dbstack (@dots{})\n\ Display or return current debugging function stack information.\n\ With optional argument @var{n}, omit the @var{n} innermost stack frames.\n\ \n\ +Although accepted, the argument @var{-completenames} is silently ignored.\n\ +Octave always returns absolute file names. The arguments @var{n} and\n\ +@var{-completenames} can be both specified in any order.\n\ +\n\ The optional return argument @var{stack} is a struct array with the\n\ following fields:\n\ \n\ diff -r a98902bda11a -r bb2fa6e5b348 libinterp/corefcn/gl-render.cc --- a/libinterp/corefcn/gl-render.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libinterp/corefcn/gl-render.cc Mon Oct 14 15:00:12 2013 -0400 @@ -1616,8 +1616,6 @@ j1 = j; clip(i,j) = is_nan_or_inf (x(i1,j), y(i,j1), z(i,j)); - if (fc_mode == 1 || fc_mode == 2) - clip(i,j) |= (xisnan (c(i,j)) || xisinf (c(i,j))); } } @@ -1676,10 +1674,25 @@ for (int j = 1; j < zr; j++) { - if (clip(j-1, i-1) || clip (j, i-1) - || clip (j-1, i) || clip (j, i)) + + if (clip(j-1, i-1) || clip(j, i-1) + || clip(j-1, i) || clip(j, i)) continue; + if (fc_mode == 1) + { + // "flat" only needs color at lower-left vertex + if (! xfinite (c(j-1,i-1))) + continue; + } + else if (fc_mode == 2) + { + // "interp" needs valid color at all 4 vertices + if (! (xfinite (c(j-1, i-1)) && xfinite (c(j, i-1)) + && xfinite (c(j-1, i)) && xfinite (c(j, i)))) + continue; + } + if (x_mat) { j1 = j-1; @@ -1867,6 +1880,19 @@ if (clip(j-1,i) || clip(j,i)) continue; + if (ec_mode == 1) + { + // "flat" only needs color at lower-left vertex + if (! xfinite (c(j-1,i))) + continue; + } + else if (ec_mode == 2) + { + // "interp" needs valid color at both vertices + if (! (xfinite (c(j-1, i)) && xfinite (c(j, i)))) + continue; + } + if (x_mat) { j1 = j-1; @@ -1951,6 +1977,19 @@ if (clip(j,i-1) || clip(j,i)) continue; + if (ec_mode == 1) + { + // "flat" only needs color at lower-left vertex + if (! xfinite (c(j,i-1))) + continue; + } + else if (ec_mode == 2) + { + // "interp" needs valid color at both vertices + if (! (xfinite (c(j, i-1)) && xfinite (c(j, i)))) + continue; + } + if (y_mat) { i1 = i-1; @@ -2080,12 +2119,17 @@ if ((do_edge && mecolor.numel () == 0) || (do_face && mfcolor.numel () == 0)) { + if (! xfinite (c(j,i))) + continue; // Skip NaNs in color data + for (int k = 0; k < 3; k++) cc(k) = c(j,i,k); } - Matrix lc = (do_edge ? (mecolor.numel () == 0 ? cc : mecolor) : Matrix ()); - Matrix fc = (do_face ? (mfcolor.numel () == 0 ? cc : mfcolor) : Matrix ()); + Matrix lc = (do_edge ? (mecolor.numel () == 0 ? cc : mecolor) + : Matrix ()); + Matrix fc = (do_face ? (mfcolor.numel () == 0 ? cc : mfcolor) + : Matrix ()); draw_marker (x(j1,i), y(j,i1), z(j,i), lc, fc); } diff -r a98902bda11a -r bb2fa6e5b348 libinterp/corefcn/graphics.cc --- a/libinterp/corefcn/graphics.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libinterp/corefcn/graphics.cc Mon Oct 14 15:00:12 2013 -0400 @@ -1199,14 +1199,10 @@ { bool xok = false; - // FIXME -- should we always support []? - if (v.is_empty () && v.is_numeric_type ()) - return true; - // check value type if (type_constraints.size () > 0) { - if(type_constraints.find (v.class_name()) != type_constraints.end()) + if (type_constraints.find (v.class_name ()) != type_constraints.end ()) xok = true; // check if complex is allowed (it's also of class "double", so @@ -1220,29 +1216,36 @@ if (xok) { + if (size_constraints.size () == 0) + return true; + dim_vector vdims = v.dims (); int vlen = vdims.length (); xok = false; - // check value size - if (size_constraints.size () > 0) - for (std::list::const_iterator it = size_constraints.begin (); - ! xok && it != size_constraints.end (); ++it) - { - dim_vector itdims = (*it); - - if (itdims.length () == vlen) - { - xok = true; - - for (int i = 0; xok && i < vlen; i++) - if (itdims(i) >= 0 && itdims(i) != vdims(i)) - xok = false; - } - } - else - return true; + // check dimensional size constraints until a match is found + for (std::list::const_iterator it = size_constraints.begin (); + ! xok && it != size_constraints.end (); ++it) + { + dim_vector itdims = (*it); + + if (itdims.length () == vlen) + { + xok = true; + + for (int i = 0; xok && i < vlen; i++) + { + if (itdims(i) > 0) + { + if (itdims(i) != vdims(i)) + xok = false; + } + else if (v.is_empty ()) + break; + } + } + } } return xok; @@ -2732,26 +2735,41 @@ void base_properties::set_parent (const octave_value& val) { - double tmp = val.double_value (); + double hnp = val.double_value (); graphics_handle new_parent = octave_NaN; if (! error_state) { - new_parent = gh_manager::lookup (tmp); - - if (new_parent.ok ()) - { - graphics_object parent_obj = gh_manager::get_object (get_parent ()); - - parent_obj.remove_child (__myhandle__); - - parent = new_parent.as_octave_value (); - - ::adopt (parent.handle_value (), __myhandle__); - } + if (hnp == __myhandle__) + error ("set: can not set object parent to be object itself"); else - error ("set: invalid graphics handle (= %g) for parent", tmp); + { + new_parent = gh_manager::lookup (hnp); + + if (new_parent.ok ()) + { + // Remove child from current parent + graphics_object old_parent_obj; + old_parent_obj = gh_manager::get_object (get_parent ()); + old_parent_obj.remove_child (__myhandle__); + + // Check new parent's parent is not this child to avoid recursion + graphics_object new_parent_obj; + new_parent_obj = gh_manager::get_object (new_parent); + if (new_parent_obj.get_parent () == __myhandle__) + { + // new parent's parent gets child's original parent + new_parent_obj.get_properties ().set_parent (get_parent ().as_octave_value ()); + } + + // Set parent property to new_parent and do adoption + parent = new_parent.as_octave_value (); + ::adopt (parent.handle_value (), __myhandle__); + } + else + error ("set: invalid graphics handle (= %g) for parent", hnp); + } } else error ("set: expecting parent to be a graphics handle"); @@ -3933,32 +3951,33 @@ axes::properties::init (void) { position.add_constraint (dim_vector (1, 4)); - position.add_constraint (dim_vector (0, 0)); outerposition.add_constraint (dim_vector (1, 4)); + tightinset.add_constraint (dim_vector (1, 4)); + looseinset.add_constraint (dim_vector (1, 4)); colororder.add_constraint (dim_vector (-1, 3)); dataaspectratio.add_constraint (dim_vector (1, 3)); plotboxaspectratio.add_constraint (dim_vector (1, 3)); + alim.add_constraint (2); + clim.add_constraint (2); xlim.add_constraint (2); ylim.add_constraint (2); zlim.add_constraint (2); - clim.add_constraint (2); - alim.add_constraint (2); xtick.add_constraint (dim_vector (1, -1)); ytick.add_constraint (dim_vector (1, -1)); ztick.add_constraint (dim_vector (1, -1)); + ticklength.add_constraint (dim_vector (1, 2)); Matrix vw (1, 2, 0); vw(1) = 90; view = vw; view.add_constraint (dim_vector (1, 2)); cameraposition.add_constraint (dim_vector (1, 3)); + cameratarget.add_constraint (dim_vector (1, 3)); Matrix upv (1, 3, 0.0); upv(2) = 1.0; cameraupvector = upv; cameraupvector.add_constraint (dim_vector (1, 3)); currentpoint.add_constraint (dim_vector (2, 3)); - ticklength.add_constraint (dim_vector (1, 2)); - tightinset.add_constraint (dim_vector (1, 4)); - looseinset.add_constraint (dim_vector (1, 4)); + // No constraints for hidden transform properties update_font (); x_zlim.resize (1, 2); @@ -5569,8 +5588,11 @@ { graphics_object obj = gh_manager::get_object (get_parent ()); - parent_size = - obj.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2); + if (obj.valid_object ()) + parent_size = + obj.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2); + else + parent_size = default_figure_position (); } pos = convert_position (pos, get_units (), "pixels", parent_size); @@ -7666,8 +7688,11 @@ { graphics_object obj = gh_manager::get_object (get_parent ()); - parent_size = - obj.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2); + if (obj.valid_object ()) + parent_size = + obj.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2); + else + parent_size = default_figure_position (); } pos = convert_position (pos, get_units (), "pixels", parent_size); diff -r a98902bda11a -r bb2fa6e5b348 libinterp/corefcn/graphics.in.h --- a/libinterp/corefcn/graphics.in.h Mon Oct 14 11:28:29 2013 -0400 +++ b/libinterp/corefcn/graphics.in.h Mon Oct 14 15:00:12 2013 -0400 @@ -1085,6 +1085,12 @@ current_val (v.default_value ()) { } + color_property (const radio_values& v, const color_values& c) + : base_property ("", graphics_handle ()), + current_type (radio_t), color_val (c), radio_val (v), + current_val (v.default_value ()) + { } + color_property (const std::string& nm, const graphics_handle& h, const color_values& c = color_values (), const radio_values& v = radio_values ()) @@ -1426,6 +1432,7 @@ { add_constraint (dim_vector (-1, 1)); add_constraint (dim_vector (1, -1)); + add_constraint (dim_vector (0, 0)); } row_vector_property (const row_vector_property& p) @@ -1433,6 +1440,7 @@ { add_constraint (dim_vector (-1, 1)); add_constraint (dim_vector (1, -1)); + add_constraint (dim_vector (0, 0)); } void add_constraint (const std::string& type) @@ -2398,7 +2406,7 @@ virtual ~base_properties (void) { } - virtual std::string graphics_object_name (void) const { return "unknonwn"; } + virtual std::string graphics_object_name (void) const { return "unknown"; } void mark_modified (void); @@ -3363,13 +3371,14 @@ protected: void init (void) { + alphamap.add_constraint (dim_vector (-1, 1)); colormap.add_constraint (dim_vector (-1, 3)); - alphamap.add_constraint (dim_vector (-1, 1)); + outerposition.add_constraint (dim_vector (1, 4)); paperposition.add_constraint (dim_vector (1, 4)); + papersize.add_constraint (dim_vector (1, 2)); pointershapecdata.add_constraint (dim_vector (16, 16)); pointershapehotspot.add_constraint (dim_vector (1, 2)); position.add_constraint (dim_vector (1, 4)); - outerposition.add_constraint (dim_vector (1, 4)); } private: @@ -4179,8 +4188,8 @@ radio_property linestyle , "{-}|--|:|-.|none" double_property linewidth , 0.5 radio_property marker , "{none}|+|o|*|.|x|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram" - color_property markeredgecolor , "{auto}|none" - color_property markerfacecolor , "auto|{none}" + color_property markeredgecolor , color_property (radio_values ("{auto}|none"), color_values (0, 0, 0)) + color_property markerfacecolor , color_property (radio_values ("auto|{none}"), color_values (0, 0, 0)) double_property markersize , 6 row_vector_property xdata u , default_data () string_property xdatasource , "" @@ -4271,10 +4280,10 @@ // properties declarations. BEGIN_PROPERTIES (text) - color_property backgroundcolor , "{none}" + color_property backgroundcolor , color_property (radio_values ("{none}"), color_values (1, 1, 1)) color_property color u , color_values (0, 0, 0) string_property displayname , "" - color_property edgecolor , "{none}" + color_property edgecolor , color_property (radio_values ("{none}"), color_values (0, 0, 0)) bool_property editing , "off" radio_property erasemode , "{normal}|none|xor|background" array_property extent rG , Matrix (1, 4, 0.0) @@ -4454,6 +4463,9 @@ cdata.add_constraint ("real"); cdata.add_constraint (dim_vector (-1, -1)); cdata.add_constraint (dim_vector (-1, -1, 3)); + alphadata.add_constraint (dim_vector (-1, -1)); + alphadata.add_constraint ("double"); + alphadata.add_constraint ("uint8"); } private: @@ -4589,9 +4601,8 @@ radio_property linestyle , "{-}|--|:|-.|none" double_property linewidth , 0.5 radio_property marker , "{none}|+|o|*|.|x|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram" - //radio_property marker , "{none}|+|o|*|.|x|s|d|^|v|>|<|p|h" - color_property markeredgecolor , "none|{auto}|flat" - color_property markerfacecolor , "{none}|auto|flat" + color_property markeredgecolor , color_property (radio_values ("none|{auto}|flat"), color_values (0, 0, 0)) + color_property markerfacecolor , color_property (radio_values ("{none}|auto|flat"), color_values (0, 0, 0)) double_property markersize , 6 radio_property normalmode , "{auto}|manual" double_property specularcolorreflectance , 1.0 @@ -4622,6 +4633,7 @@ xdata.add_constraint (dim_vector (-1, -1)); ydata.add_constraint (dim_vector (-1, -1)); zdata.add_constraint (dim_vector (-1, -1)); + faces.add_constraint (dim_vector (-1, -1)); vertices.add_constraint (dim_vector (-1, 2)); vertices.add_constraint (dim_vector (-1, 3)); cdata.add_constraint (dim_vector (-1, -1)); @@ -4629,6 +4641,7 @@ facevertexcdata.add_constraint (dim_vector (-1, 1)); facevertexcdata.add_constraint (dim_vector (-1, 3)); facevertexalphadata.add_constraint (dim_vector (-1, 1)); + vertexnormals.add_constraint (dim_vector (-1, -1)); } private: @@ -4703,7 +4716,7 @@ radio_property edgelighting , "{none}|flat|gouraud|phong" radio_property erasemode , "{normal}|none|xor|background" double_radio_property facealpha , double_radio_property (1.0, radio_values ("flat|interp|texturemap")) - color_property facecolor , "none|{flat}|interp|texturemap" + color_property facecolor , color_property (radio_values ("none|{flat}|interp|texturemap"), color_values (0, 0, 0)) radio_property facelighting , "{none}|flat|gouraud|phong" // FIXME: interpreter is not a Matlab surface property // Octave uses this for legend() with the string displayname. @@ -4711,9 +4724,8 @@ radio_property linestyle , "{-}|--|:|-.|none" double_property linewidth , 0.5 radio_property marker , "{none}|+|o|*|.|x|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram" - //radio_property marker , "{none}|+|o|*|.|x|s|d|^|v|>|<|p|h" - color_property markeredgecolor , "none|{auto}|flat" - color_property markerfacecolor , "{none}|auto|flat" + color_property markeredgecolor , color_property (radio_values ("none|{auto}|flat"), color_values (0, 0, 0)) + color_property markerfacecolor , color_property (radio_values ("{none}|auto|flat"), color_values (0, 0, 0)) double_property markersize , 6 radio_property meshstyle , "{both}|row|column" radio_property normalmode u , "{auto}|manual" @@ -4747,16 +4759,14 @@ xdata.add_constraint (dim_vector (-1, -1)); ydata.add_constraint (dim_vector (-1, -1)); zdata.add_constraint (dim_vector (-1, -1)); - alphadata.add_constraint ("single"); + cdata.add_constraint ("double"); + cdata.add_constraint ("single"); + cdata.add_constraint (dim_vector (-1, -1)); + cdata.add_constraint (dim_vector (-1, -1, 3)); alphadata.add_constraint ("double"); alphadata.add_constraint ("uint8"); alphadata.add_constraint (dim_vector (-1, -1)); vertexnormals.add_constraint (dim_vector (-1, -1, 3)); - cdata.add_constraint ("single"); - cdata.add_constraint ("double"); - cdata.add_constraint ("uint8"); - cdata.add_constraint (dim_vector (-1, -1)); - cdata.add_constraint (dim_vector (-1, -1, 3)); } private: @@ -5062,7 +5072,6 @@ { cdata.add_constraint ("double"); cdata.add_constraint ("single"); - cdata.add_constraint ("uint8"); cdata.add_constraint (dim_vector (-1, -1, 3)); position.add_constraint (dim_vector (1, 4)); sliderstep.add_constraint (dim_vector (1, 2)); @@ -5283,7 +5292,6 @@ { cdata.add_constraint ("double"); cdata.add_constraint ("single"); - cdata.add_constraint ("uint8"); cdata.add_constraint (dim_vector (-1, -1, 3)); } }; @@ -5337,7 +5345,6 @@ { cdata.add_constraint ("double"); cdata.add_constraint ("single"); - cdata.add_constraint ("uint8"); cdata.add_constraint (dim_vector (-1, -1, 3)); } }; diff -r a98902bda11a -r bb2fa6e5b348 libinterp/corefcn/oct-tex-lexer.in.ll --- a/libinterp/corefcn/oct-tex-lexer.in.ll Mon Oct 14 11:28:29 2013 -0400 +++ b/libinterp/corefcn/oct-tex-lexer.in.ll Mon Oct 14 15:00:12 2013 -0400 @@ -30,13 +30,38 @@ #include #endif -#include "txt-eng.h" -#include "oct-tex-parser.h" } %x NUM_MODE %x MAYBE_NUM_MODE +%{ + +// The generated code may include unistd.h. We need that to happen +// before defining isatty to be prefixed with the gnulib namespace +// identifier. + +#include +#include + +#include "txt-eng.h" +#include "oct-tex-parser.h" + +#if defined (GNULIB_NAMESPACE) +// Calls to the following functions appear in the generated output from +// flex without the namespace tag. Redefine them so we will use them +// via the gnulib namespace. +#define fprintf GNULIB_NAMESPACE::fprintf +#define fread GNULIB_NAMESPACE::fread +#define fwrite GNULIB_NAMESPACE::fwrite +#define getc GNULIB_NAMESPACE::getc +#define isatty GNULIB_NAMESPACE::isatty +#define malloc GNULIB_NAMESPACE::malloc +#define realloc GNULIB_NAMESPACE::realloc +#endif + +%} + D [0-9] NUM (({D}+\.?{D}*)|(\.{D}+)) diff -r a98902bda11a -r bb2fa6e5b348 libinterp/corefcn/oct-tex-parser.yy --- a/libinterp/corefcn/oct-tex-parser.yy Mon Oct 14 11:28:29 2013 -0400 +++ b/libinterp/corefcn/oct-tex-parser.yy Mon Oct 14 15:00:12 2013 -0400 @@ -33,6 +33,15 @@ extern int octave_tex_lex (YYSTYPE *, void *); static void yyerror (text_parser_tex& parser, const char *s); +#if defined (GNULIB_NAMESPACE) +// Calls to the following functions appear in the generated output from +// Bison without the namespace tag. Redefine them so we will use them +// via the gnulib namespace. +#define fclose GNULIB_NAMESPACE::fclose +#define fprintf GNULIB_NAMESPACE::fprintf +#define malloc GNULIB_NAMESPACE::malloc +#endif + #define scanner parser.get_scanner () %} diff -r a98902bda11a -r bb2fa6e5b348 libinterp/corefcn/urlwrite.cc --- a/libinterp/corefcn/urlwrite.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libinterp/corefcn/urlwrite.cc Mon Oct 14 15:00:12 2013 -0400 @@ -410,7 +410,9 @@ frame.add_fcn (delete_file, filename); - url_transfer curl = url_transfer (url, method, param, ofile); + url_transfer curl = url_transfer (url, ofile); + + curl.http_action (param, method); ofile.close (); @@ -535,7 +537,9 @@ std::ostringstream buf; - url_transfer curl = url_transfer (url, method, param, buf); + url_transfer curl = url_transfer (url, buf); + + curl.http_action (param, method); if (curl.good ()) { diff -r a98902bda11a -r bb2fa6e5b348 libinterp/octave-value/ov-str-mat.cc --- a/libinterp/octave-value/ov-str-mat.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libinterp/octave-value/ov-str-mat.cc Mon Oct 14 15:00:12 2013 -0400 @@ -676,7 +676,7 @@ { // This is cruft for backward compatiability and easy data // importation - if (rank == 0) + if (rank == 0) //FIXME: Does rank==0 even exist for strings in HDF5? { // a single string: int slen = H5Tget_size (type_hid); @@ -693,7 +693,7 @@ // create datatype for (null-terminated) string // to read into: hid_t st_id = H5Tcopy (H5T_C_S1); - H5Tset_size (st_id, slen); + H5Tset_size (st_id, slen+1); if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, s) < 0) { H5Tclose (st_id); @@ -731,12 +731,12 @@ // same physical length (I think), which is // slightly wasteful, but oh well. - OCTAVE_LOCAL_BUFFER (char, s, elements * slen); + OCTAVE_LOCAL_BUFFER (char, s, elements * (slen+1)); // create datatype for (null-terminated) string // to read into: hid_t st_id = H5Tcopy (H5T_C_S1); - H5Tset_size (st_id, slen); + H5Tset_size (st_id, slen+1); if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, s) < 0) { @@ -747,10 +747,10 @@ return false; } - charMatrix chm (elements, slen - 1); + charMatrix chm (elements, slen, ' '); for (hsize_t i = 0; i < elements; ++i) { - chm.insert (s + i*slen, i, 0); + chm.insert (s + i*(slen+1), i, 0); } matrix = chm; diff -r a98902bda11a -r bb2fa6e5b348 libinterp/octave-value/ov-usr-fcn.cc --- a/libinterp/octave-value/ov-usr-fcn.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/libinterp/octave-value/ov-usr-fcn.cc Mon Oct 14 15:00:12 2013 -0400 @@ -800,11 +800,17 @@ if (val.is_defined ()) { - octave_map m = val.map_value (); + // Don't use the usual approach of attempting to extract a value + // and then checking error_state since this code might be + // executing when error_state is already set. But do fail + // spectacularly if .saved_warning_states. is not an octave_map + // (or octave_scalar_map) object. - if (error_state) + if (! val.is_map ()) panic_impossible (); + octave_map m = val.map_value (); + Cell ids = m.contents ("identifier"); Cell states = m.contents ("state"); diff -r a98902bda11a -r bb2fa6e5b348 libinterp/parse-tree/oct-parse.in.yy --- a/libinterp/parse-tree/oct-parse.in.yy Mon Oct 14 11:28:29 2013 -0400 +++ b/libinterp/parse-tree/oct-parse.in.yy Mon Oct 14 15:00:12 2013 -0400 @@ -260,7 +260,7 @@ %type matrix_rows %type cell_rows %type matrix cell -%type primary_expr oper_expr +%type primary_expr oper_expr power_expr %type simple_expr colon_expr assign_expr expression %type identifier fcn_name magic_tilde %type superclass_identifier meta_identifier @@ -321,6 +321,13 @@ %right PLUS_PLUS MINUS_MINUS %left '(' '.' '{' +// How to clean up if there is a parse error. We handle deleting tokens +// and comments seperately and separators are just characters. The +// remaining items are dynamically allocated parse tree objects that +// must be deleted. +%destructor { } <> +%destructor { delete $$; } <*> + // Where to start. %start input @@ -393,7 +400,10 @@ { $$ = parser.make_index_expression ($1, $2, '('); if (! $$) - ABORT_PARSE; + { + // make_index_expression deleted $1 and $2. + ABORT_PARSE; + } } ; @@ -598,25 +608,37 @@ { $$ = parser.make_index_expression ($1, 0, '('); if (! $$) - ABORT_PARSE; + { + // make_index_expression deleted $1. + ABORT_PARSE; + } } | oper_expr '(' arg_list ')' { $$ = parser.make_index_expression ($1, $3, '('); if (! $$) - ABORT_PARSE; + { + // make_index_expression deleted $1 and $3. + ABORT_PARSE; + } } | oper_expr '{' '}' { $$ = parser.make_index_expression ($1, 0, '{'); if (! $$) - ABORT_PARSE; + { + // make_index_expression deleted $1. + ABORT_PARSE; + } } | oper_expr '{' arg_list '}' { $$ = parser.make_index_expression ($1, $3, '{'); if (! $$) - ABORT_PARSE; + { + // make_index_expression deleted $1 and $3. + ABORT_PARSE; + } } | oper_expr HERMITIAN { $$ = parser.make_postfix_op (HERMITIAN, $1, $2); } @@ -636,9 +658,9 @@ { $$ = parser.make_prefix_op ('+', $2, $1); } | '-' oper_expr %prec UNARY { $$ = parser.make_prefix_op ('-', $2, $1); } - | oper_expr POW oper_expr + | oper_expr POW power_expr { $$ = parser.make_binary_op (POW, $1, $2, $3); } - | oper_expr EPOW oper_expr + | oper_expr EPOW power_expr { $$ = parser.make_binary_op (EPOW, $1, $2, $3); } | oper_expr '+' oper_expr { $$ = parser.make_binary_op ('+', $1, $2, $3); } @@ -662,6 +684,64 @@ { $$ = parser.make_binary_op (ELEFTDIV, $1, $2, $3); } ; +power_expr : primary_expr + { $$ = $1; } + | power_expr PLUS_PLUS + { $$ = parser.make_postfix_op (PLUS_PLUS, $1, $2); } + | power_expr MINUS_MINUS + { $$ = parser.make_postfix_op (MINUS_MINUS, $1, $2); } + | power_expr '(' ')' + { + $$ = parser.make_index_expression ($1, 0, '('); + if (! $$) + { + // make_index_expression deleted $1. + ABORT_PARSE; + } + } + | power_expr '(' arg_list ')' + { + $$ = parser.make_index_expression ($1, $3, '('); + if (! $$) + { + // make_index_expression deleted $1 and $3. + ABORT_PARSE; + } + } + | power_expr '{' '}' + { + $$ = parser.make_index_expression ($1, 0, '{'); + if (! $$) + { + // make_index_expression deleted $1. + ABORT_PARSE; + } + } + | power_expr '{' arg_list '}' + { + $$ = parser.make_index_expression ($1, $3, '{'); + if (! $$) + { + // make_index_expression deleted $1 and $3. + ABORT_PARSE; + } + } + | power_expr indirect_ref_op STRUCT_ELT + { $$ = parser.make_indirect_ref ($1, $3->text ()); } + | power_expr indirect_ref_op '(' expression ')' + { $$ = parser.make_indirect_ref ($1, $4); } + | PLUS_PLUS power_expr %prec POW + { $$ = parser.make_prefix_op (PLUS_PLUS, $2, $1); } + | MINUS_MINUS power_expr %prec POW + { $$ = parser.make_prefix_op (MINUS_MINUS, $2, $1); } + | EXPR_NOT power_expr %prec POW + { $$ = parser.make_prefix_op (EXPR_NOT, $2, $1); } + | '+' power_expr %prec POW + { $$ = parser.make_prefix_op ('+', $2, $1); } + | '-' power_expr %prec POW + { $$ = parser.make_prefix_op ('-', $2, $1); } + ; + colon_expr : colon_expr1 { $$ = parser.finish_colon_expression ($1); } ; @@ -671,7 +751,11 @@ | colon_expr1 ':' oper_expr { if (! ($$ = $1->append ($3))) - ABORT_PARSE; + { + delete $1; + delete $3; + ABORT_PARSE; + } } ; @@ -844,7 +928,10 @@ if_command : IF stash_comment if_cmd_list END { if (! ($$ = parser.finish_if_command ($1, $3, $4, $2))) - ABORT_PARSE; + { + // finish_if_command deleted $3. + ABORT_PARSE; + } } ; @@ -889,7 +976,10 @@ switch_command : SWITCH stash_comment expression opt_sep case_list END { if (! ($$ = parser.finish_switch_command ($1, $3, $5, $6, $2))) - ABORT_PARSE; + { + // finish_switch_command deleted $3 adn $5. + ABORT_PARSE; + } } ; @@ -934,36 +1024,50 @@ $3->mark_braindead_shortcircuit (lexer.fcn_file_full_name); if (! ($$ = parser.make_while_command ($1, $3, $6, $7, $2))) - ABORT_PARSE; + { + // make_while_command deleted $3 and $6. + ABORT_PARSE; + } } | DO stash_comment opt_sep opt_list UNTIL expression { - if (! ($$ = parser.make_do_until_command ($5, $4, $6, $2))) - ABORT_PARSE; + $$ = parser.make_do_until_command ($5, $4, $6, $2); } | FOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END { if (! ($$ = parser.make_for_command (FOR, $1, $3, $5, 0, - $8, $9, $2))) - ABORT_PARSE; + $8, $9, $2))) + { + // make_for_command deleted $3, $5, and $8. + ABORT_PARSE; + } } | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END { if (! ($$ = parser.make_for_command (FOR, $1, $4, $6, 0, - $9, $10, $2))) - ABORT_PARSE; + $9, $10, $2))) + { + // make_for_command deleted $4, $6, and $9. + ABORT_PARSE; + } } | PARFOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END { if (! ($$ = parser.make_for_command (PARFOR, $1, $3, $5, - 0, $8, $9, $2))) - ABORT_PARSE; + 0, $8, $9, $2))) + { + // make_for_command deleted $3, $5, and $8. + ABORT_PARSE; + } } | PARFOR stash_comment '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END { if (! ($$ = parser.make_for_command (PARFOR, $1, $4, $6, - $8, $11, $12, $2))) - ABORT_PARSE; + $8, $11, $12, $2))) + { + // make_for_command deleted $4, $6, $8, and $11. + ABORT_PARSE; + } } ; @@ -972,20 +1076,11 @@ // ======= jump_command : BREAK - { - if (! ($$ = parser.make_break_command ($1))) - ABORT_PARSE; - } + { $$ = parser.make_break_command ($1); } | CONTINUE - { - if (! ($$ = parser.make_continue_command ($1))) - ABORT_PARSE; - } + { $$ = parser.make_continue_command ($1); } | FUNC_RET - { - if (! ($$ = parser.make_return_command ($1))) - ABORT_PARSE; - } + { $$ = parser.make_return_command ($1); } ; // ========== @@ -996,18 +1091,27 @@ stash_comment opt_sep opt_list END { if (! ($$ = parser.make_unwind_command ($1, $4, $8, $9, $2, $6))) - ABORT_PARSE; + { + // make_unwind_command deleted $4 and $8. + ABORT_PARSE; + } } | TRY stash_comment opt_sep opt_list CATCH stash_comment opt_sep opt_list END { if (! ($$ = parser.make_try_command ($1, $4, $7, $8, $9, $2, $6))) - ABORT_PARSE; + { + // make_try_command deleted $4 and $8. + ABORT_PARSE; + } } | TRY stash_comment opt_sep opt_list END { if (! ($$ = parser.make_try_command ($1, $4, 0, 0, $5, $2, 0))) - ABORT_PARSE; + { + // make_try_command deleted $4. + ABORT_PARSE; + } } ; @@ -1089,7 +1193,10 @@ $$ = $1; } else - ABORT_PARSE; + { + delete $1; + ABORT_PARSE; + } } ; @@ -1131,7 +1238,10 @@ if (tmp->validate (tree_parameter_list::out)) $$ = tmp; else - ABORT_PARSE; + { + delete tmp; + ABORT_PARSE; + } } | '[' return_list1 ']' { @@ -1143,7 +1253,10 @@ if ($2->validate (tree_parameter_list::out)) $$ = $2; else - ABORT_PARSE; + { + delete $2; + ABORT_PARSE; + } } ; @@ -1162,7 +1275,17 @@ file : INPUT_FILE opt_nl opt_list END_OF_INPUT { - if (! lexer.reading_fcn_file) + if (lexer.reading_fcn_file) + { + // Delete the dummy statement_list we created + // after parsing the function. Any function + // definitions found in the file have already + // been stored in the symbol table or in + // octave_base_parser::primary_fcn_ptr. + + delete $3; + } + else { tree_statement *end_of_script = parser.make_end ("endscript", true, @@ -1246,8 +1369,7 @@ else if (lexer.parsing_classdef_set_method) fname.insert (0, "set."); - if (! ($$ = parser.frob_function (fname, $2))) - ABORT_PARSE; + $$ = parser.frob_function (fname, $2); } ; @@ -2281,6 +2403,11 @@ retval = new tree_unwind_protect_command (body, cleanup_stmts, lc, mc, tc, l, c); } + else + { + delete body; + delete cleanup_stmts; + } return retval; } @@ -2327,6 +2454,11 @@ retval = new tree_try_catch_command (body, cleanup_stmts, id, lc, mc, tc, l, c); } + else + { + delete body; + delete cleanup_stmts; + } return retval; } @@ -2355,6 +2487,11 @@ retval = new tree_while_command (expr, body, lc, tc, l, c); } + else + { + delete expr; + delete body; + } return retval; } @@ -2367,8 +2504,6 @@ tree_expression *expr, octave_comment_list *lc) { - tree_command *retval = 0; - maybe_warn_assign_as_truth_value (expr); octave_comment_list *tc = octave_comment_buffer::get_comment (); @@ -2378,9 +2513,7 @@ int l = until_tok->line (); int c = until_tok->column (); - retval = new tree_do_until_command (expr, body, lc, tc, l, c); - - return retval; + return new tree_do_until_command (expr, body, lc, tc, l, c); } // Build a for command. @@ -2425,6 +2558,13 @@ lc, tc, l, c); } } + else + { + delete lhs; + delete expr; + delete maxproc; + delete body; + } return retval; } @@ -2434,14 +2574,10 @@ tree_command * octave_base_parser::make_break_command (token *break_tok) { - tree_command *retval = 0; - int l = break_tok->line (); int c = break_tok->column (); - retval = new tree_break_command (l, c); - - return retval; + return new tree_break_command (l, c); } // Build a continue command. @@ -2449,14 +2585,10 @@ tree_command * octave_base_parser::make_continue_command (token *continue_tok) { - tree_command *retval = 0; - int l = continue_tok->line (); int c = continue_tok->column (); - retval = new tree_continue_command (l, c); - - return retval; + return new tree_continue_command (l, c); } // Build a return command. @@ -2464,14 +2596,10 @@ tree_command * octave_base_parser::make_return_command (token *return_tok) { - tree_command *retval = 0; - int l = return_tok->line (); int c = return_tok->column (); - retval = new tree_return_command (l, c); - - return retval; + return new tree_return_command (l, c); } // Start an if command. @@ -2517,6 +2645,8 @@ retval = new tree_if_command (list, lc, tc, l, c); } + else + delete list; return retval; } @@ -2568,6 +2698,11 @@ retval = new tree_switch_command (expr, list, lc, tc, l, c); } + else + { + delete expr; + delete list; + } return retval; } @@ -3116,6 +3251,10 @@ if (args && args->has_magic_tilde ()) { bison_error ("invalid use of empty argument (~) in index expression"); + + delete expr; + delete args; + return retval; } diff -r a98902bda11a -r bb2fa6e5b348 liboctave/array/Array.cc --- a/liboctave/array/Array.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/liboctave/array/Array.cc Mon Oct 14 15:00:12 2013 -0400 @@ -1460,12 +1460,14 @@ void Array::delete_elements (const Array& ia) { - if (ia.length () == 1) + int ial = ia.length (); + + if (ial == 1) delete_elements (ia(0)); else { - int len = ia.length (), k, dim = -1; - for (k = 0; k < len; k++) + int k, dim = -1; + for (k = 0; k < ial; k++) { if (! ia(k).is_colon ()) { @@ -1481,14 +1483,51 @@ dv(0) = 0; *this = Array (dv); } - else if (k == len) + else if (k == ial) { delete_elements (dim, ia(dim)); } else { - (*current_liboctave_error_handler) - ("a null assignment can only have one non-colon index"); + // Allow the null assignment to succeed if it won't change + // anything because the indices reference an empty slice, + // provided that there is at most one non-colon (or + // equivalent) index. So, we still have the requirement of + // deleting a slice, but it is OK if the slice is empty. + + // For compatibility with Matlab, stop checking once we see + // more than one non-colon index or an empty index. Matlab + // considers "[]" to be an empty index but not "false". We + // accept both. + + bool empty_assignment = false; + + int num_non_colon_indices = 0; + + int nd = ndims (); + + for (int i = 0; i < ial; i++) + { + octave_idx_type dim_len = i >= nd ? 1 : dimensions(i); + + if (ia(i).length (dim_len) == 0) + { + empty_assignment = true; + break; + } + + if (! ia(i).is_colon_equiv (dim_len)) + { + num_non_colon_indices++; + + if (num_non_colon_indices == 2) + break; + } + } + + if (! empty_assignment) + (*current_liboctave_error_handler) + ("a null assignment can only have one non-colon index"); } } diff -r a98902bda11a -r bb2fa6e5b348 liboctave/array/Sparse.cc --- a/liboctave/array/Sparse.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/liboctave/array/Sparse.cc Mon Oct 14 15:00:12 2013 -0400 @@ -1215,11 +1215,16 @@ else *this = index (idx.complement (nc)); } - else + else if (idx.length (nel) != 0) { - *this = index (idx_vector::colon); - delete_elements (idx); - *this = transpose (); // We want a row vector. + if (idx.is_colon_equiv (nel)) + *this = Sparse (); + else + { + *this = index (idx_vector::colon); + delete_elements (idx); + *this = transpose (); // We want a row vector. + } } } @@ -1324,8 +1329,21 @@ } } else - (*current_liboctave_error_handler) - ("a null assignment can only have one non-colon index"); + { + // Empty assignment (no elements to delete) is OK if there is at + // least one zero-length index and at most one other index that is + // non-colon (or equivalent) index. Since we only have two + // indices, we just need to check that we have at least one zero + // length index. Matlab considers "[]" to be an empty index but + // not "false". We accept both. + + bool empty_assignment + = (idx_i.length (nr) == 0 || idx_j.length (nc) == 0); + + if (! empty_assignment) + (*current_liboctave_error_handler) + ("a null assignment can only have one non-colon index"); + } } template diff -r a98902bda11a -r bb2fa6e5b348 liboctave/util/cmd-edit.cc --- a/liboctave/util/cmd-edit.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/liboctave/util/cmd-edit.cc Mon Oct 14 15:00:12 2013 -0400 @@ -1599,7 +1599,14 @@ case 'w': case 'W': { - temp = octave_env::get_current_directory (); + try + { + temp = octave_env::get_current_directory (); + } + catch (octave_execution_exception) + { + temp = ""; + } std::string home_dir = octave_env::get_home_directory (); diff -r a98902bda11a -r bb2fa6e5b348 liboctave/util/data-conv.cc --- a/liboctave/util/data-conv.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/liboctave/util/data-conv.cc Mon Oct 14 15:00:12 2013 -0400 @@ -627,13 +627,6 @@ ("unrecognized floating point format requested"); } -static void -gripe_data_conversion (const char *from, const char *to) -{ - (*current_liboctave_error_handler) - ("unable to convert from %s to %s format", from, to); -} - // But first, some data conversion routines. // Currently, we only handle conversions for the IEEE types. To fix diff -r a98902bda11a -r bb2fa6e5b348 liboctave/util/lo-utils.cc --- a/liboctave/util/lo-utils.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/liboctave/util/lo-utils.cc Mon Oct 14 15:00:12 2013 -0400 @@ -26,6 +26,7 @@ #endif #include +#include #include #include #include @@ -87,26 +88,12 @@ return tmp; } -// This function was adapted from xputenv from Karl Berry's kpathsearch -// library. - -// FIXME -- make this do the right thing if we don't have a -// SMART_PUTENV. - void octave_putenv (const std::string& name, const std::string& value) { - int new_len = name.length () + value.length () + 2; - - char *new_item = static_cast (gnulib::malloc (new_len)); - - sprintf (new_item, "%s=%s", name.c_str (), value.c_str ()); - - // As far as I can see there's no way to distinguish between the - // various errors; putenv doesn't have errno values. - - if (gnulib::putenv (new_item) < 0) - (*current_liboctave_error_handler) ("putenv (%s) failed", new_item); + if (gnulib::setenv (name.c_str (), value.c_str (), true) < 0) + (*current_liboctave_error_handler) ("putenv: %s", + gnulib::strerror (errno)); } std::string diff -r a98902bda11a -r bb2fa6e5b348 liboctave/util/oct-base64.cc --- a/liboctave/util/oct-base64.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/liboctave/util/oct-base64.cc Mon Oct 14 15:00:12 2013 -0400 @@ -82,6 +82,7 @@ retval.resize (dim_vector (1, len)); double *dout = reinterpret_cast (out); std::copy (dout, dout + len, retval.fortran_vec ()); + ::free (out); } } diff -r a98902bda11a -r bb2fa6e5b348 liboctave/util/url-transfer.cc --- a/liboctave/util/url-transfer.cc Mon Oct 14 11:28:29 2013 -0400 +++ b/liboctave/util/url-transfer.cc Mon Oct 14 15:00:12 2013 -0400 @@ -45,7 +45,8 @@ #include #endif -void base_url_transfer::delete_file (const std::string& file) +void +base_url_transfer::delete_file (const std::string& file) { octave_unlink (file); } @@ -209,6 +210,8 @@ + realdir + "'"; } } + + return file_list; } #if defined (HAVE_CURL) @@ -273,7 +276,8 @@ public: curl_transfer (void) - : base_url_transfer (), curl (curl_easy_init ()), errnum () + : base_url_transfer (), curl (curl_easy_init ()), errnum (), url (), + userpwd () { if (curl) valid = true; @@ -281,10 +285,10 @@ errmsg = "can not create curl object"; } - curl_transfer (const std::string& host_arg, const std::string& user_arg, + curl_transfer (const std::string& host, const std::string& user_arg, const std::string& passwd, std::ostream& os) - : base_url_transfer (host_arg, user_arg, passwd, os), - curl (curl_easy_init ()), errnum () + : base_url_transfer (host, user_arg, passwd, os), + curl (curl_easy_init ()), errnum (), url (), userpwd () { if (curl) valid = true; @@ -296,17 +300,16 @@ init (user_arg, passwd, std::cin, os); - std::string url ("ftp://" + host_arg); + url = "ftp://" + host; SETOPT (CURLOPT_URL, url.c_str ()); - // Setup the link, with no transfer. + // Set up the link, with no transfer. perform (); } - curl_transfer (const std::string& url, const std::string& method, - const Array& param, std::ostream& os) - : base_url_transfer (url, method, param, os), - curl (curl_easy_init ()), errnum () + curl_transfer (const std::string& url_str, std::ostream& os) + : base_url_transfer (url_str, os), curl (curl_easy_init ()), errnum (), + url (), userpwd () { if (curl) valid = true; @@ -321,28 +324,10 @@ SETOPT (CURLOPT_NOBODY, 0); // Restore the default HTTP request method to GET after setting - // NOBODY to true and back to false. This is needed for backward - // compatibility with versions of libcurl < 7.18.2. + // NOBODY to true (in the init method) and back to false (above). + // This is needed for backward compatibility with versions of + // libcurl < 7.18.2. SETOPT (CURLOPT_HTTPGET, 1); - - // Don't need to store the parameters here as we can't change - // the URL after the object is created - std::string query_string = form_query_string (param); - - if (method == "get") - { - query_string = url + "?" + query_string; - SETOPT (CURLOPT_URL, query_string.c_str ()); - } - else if (method == "post") - { - SETOPT (CURLOPT_URL, url.c_str ()); - SETOPT (CURLOPT_POSTFIELDS, query_string.c_str ()); - } - else - SETOPT (CURLOPT_URL, url.c_str ()); - - perform (); } ~curl_transfer (void) @@ -401,74 +386,22 @@ void cwd (const std::string& path) { - struct curl_slist *slist = 0; - - unwind_protect frame; - frame.add_fcn (curl_slist_free_all, slist); - - std::string cmd = "cwd " + path; - slist = curl_slist_append (slist, cmd.c_str ()); - SETOPT (CURLOPT_POSTQUOTE, slist); - - perform (); - if (! good ()) - return; - - SETOPT (CURLOPT_POSTQUOTE, 0); + ftp_file_or_dir_action (path, "cwd"); } void del (const std::string& file) { - struct curl_slist *slist = 0; - - unwind_protect frame; - frame.add_fcn (curl_slist_free_all, slist); - - std::string cmd = "dele " + file; - slist = curl_slist_append (slist, cmd.c_str ()); - SETOPT (CURLOPT_POSTQUOTE, slist); - - perform (); - if (! good ()) - return; - - SETOPT (CURLOPT_POSTQUOTE, 0); + ftp_file_or_dir_action (file, "dele"); } void rmdir (const std::string& path) { - struct curl_slist *slist = 0; - - unwind_protect frame; - frame.add_fcn (curl_slist_free_all, slist); - - std::string cmd = "rmd " + path; - slist = curl_slist_append (slist, cmd.c_str ()); - SETOPT (CURLOPT_POSTQUOTE, slist); - - perform (); - if (! good ()) - return; - - SETOPT (CURLOPT_POSTQUOTE, 0); + ftp_file_or_dir_action (path, "rmd"); } void mkdir (const std::string& path) { - struct curl_slist *slist = 0; - - unwind_protect frame; - frame.add_fcn (curl_slist_free_all, slist); - - std::string cmd = "mkd " + path; - slist = curl_slist_append (slist, cmd.c_str ()); - SETOPT (CURLOPT_POSTQUOTE, slist); - - perform (); - if (! good ()) - return; - - SETOPT (CURLOPT_POSTQUOTE, 0); + ftp_file_or_dir_action (path, "mkd"); } void rename (const std::string& oldname, const std::string& newname) @@ -493,7 +426,7 @@ void put (const std::string& file, std::istream& is) { - std::string url = "ftp://" + host + "/" + file; + url = "ftp://" + host_or_url + "/" + file; SETOPT (CURLOPT_URL, url.c_str ()); SETOPT (CURLOPT_UPLOAD, 1); SETOPT (CURLOPT_NOBODY, 0); @@ -506,13 +439,13 @@ set_istream (old_is); SETOPT (CURLOPT_NOBODY, 1); SETOPT (CURLOPT_UPLOAD, 0); - url = "ftp://" + host; + url = "ftp://" + host_or_url; SETOPT (CURLOPT_URL, url.c_str ()); } void get (const std::string& file, std::ostream& os) { - std::string url = "ftp://" + host + "/" + file; + url = "ftp://" + host_or_url + "/" + file; SETOPT (CURLOPT_URL, url.c_str ()); SETOPT (CURLOPT_NOBODY, 0); std::ostream& old_os = set_ostream (os); @@ -523,13 +456,13 @@ set_ostream (old_os); SETOPT (CURLOPT_NOBODY, 1); - url = "ftp://" + host; + url = "ftp://" + host_or_url; SETOPT (CURLOPT_URL, url.c_str ()); } void dir (void) { - std::string url = "ftp://" + host + "/"; + url = "ftp://" + host_or_url + "/"; SETOPT (CURLOPT_URL, url.c_str ()); SETOPT (CURLOPT_NOBODY, 0); @@ -538,7 +471,7 @@ return; SETOPT (CURLOPT_NOBODY, 1); - url = "ftp://" + host; + url = "ftp://" + host_or_url; SETOPT (CURLOPT_URL, url.c_str ()); } @@ -547,7 +480,7 @@ string_vector retval; std::ostringstream buf; - std::string url = "ftp://" + host + "/"; + url = "ftp://" + host_or_url + "/"; SETOPTR (CURLOPT_WRITEDATA, static_cast (&buf)); SETOPTR (CURLOPT_URL, url.c_str ()); SETOPTR (CURLOPT_DIRLISTONLY, 1); @@ -558,7 +491,7 @@ return retval; SETOPTR (CURLOPT_NOBODY, 1); - url = "ftp://" + host; + url = "ftp://" + host_or_url; SETOPTR (CURLOPT_WRITEDATA, static_cast (curr_ostream)); SETOPTR (CURLOPT_DIRLISTONLY, 0); SETOPTR (CURLOPT_URL, url.c_str ()); @@ -595,7 +528,7 @@ { std::string path = pwd (); - std::string url = "ftp://" + host + "/" + path + "/" + filename; + url = "ftp://" + host_or_url + "/" + path + "/" + filename; SETOPT (CURLOPT_URL, url.c_str ()); SETOPT (CURLOPT_FILETIME, 1); SETOPT (CURLOPT_HEADERFUNCTION, throw_away); @@ -627,7 +560,7 @@ SETOPT (CURLOPT_WRITEFUNCTION, write_data); SETOPT (CURLOPT_HEADERFUNCTION, 0); SETOPT (CURLOPT_FILETIME, 0); - url = "ftp://" + host; + url = "ftp://" + host_or_url; SETOPT (CURLOPT_URL, url.c_str ()); // The MDTM command seems to reset the path to the root with the @@ -671,11 +604,68 @@ return retval; } + void http_get (const Array& param) + { + url = host_or_url; + + std::string query_string = form_query_string (param); + + if (! query_string.empty ()) + url += "?" + query_string; + + SETOPT (CURLOPT_URL, url.c_str ()); + + perform (); + } + + void http_post (const Array& param) + { + SETOPT (CURLOPT_URL, host_or_url.c_str ()); + + std::string query_string = form_query_string (param); + + SETOPT (CURLOPT_POSTFIELDS, query_string.c_str ()); + + perform (); + } + + void http_action (const Array& param, const std::string& action) + { + if (action.empty () || action == "get") + http_get (param); + else if (action == "post") + http_post (param); + else + { + ok = false; + errmsg = "curl_transfer: unknown http action"; + } + } + private: + // Pointer to cURL object. CURL *curl; + + // cURL error code. CURLcode errnum; + // The cURL library changed the curl_easy_setopt call to make an + // internal copy of string parameters in version 7.17.0. Prior + // versions only held a pointer to a string provided by the caller + // that must persist for the lifetime of the CURL handle. + // + // The associated API did not change, only the behavior of the library + // implementing the function call. + // + // To be compatible with any version of cURL, the caller must keep a + // copy of all string parameters associated with a CURL handle until + // the handle is released. The curl_handle::curl_handle_rep class + // contains the pointer to the CURL handle and so is the best + // candidate for storing the strings as well. (bug #36717) + std::string url; + std::string userpwd; + // No copying! curl_transfer (const curl_transfer&); @@ -750,6 +740,29 @@ return query.str (); } + + void ftp_file_or_dir_action (const std::string& file_or_dir, + const std::string& action) + { + struct curl_slist *slist = 0; + + unwind_protect frame; + + frame.add_fcn (curl_slist_free_all, slist); + + std::string cmd = action + " " + file_or_dir; + + slist = curl_slist_append (slist, cmd.c_str ()); + + SETOPT (CURLOPT_POSTQUOTE, slist); + + perform (); + + if (! good ()) + return; + + SETOPT (CURLOPT_POSTQUOTE, 0); + } }; #undef SETOPT @@ -787,9 +800,8 @@ #endif } -url_transfer::url_transfer (const std::string& url, const std::string& method, - const Array& param, std::ostream& os) - : rep (new REP_CLASS (url, method, param, os)) +url_transfer::url_transfer (const std::string& url, std::ostream& os) + : rep (new REP_CLASS (url, os)) { #if !defined (HAVE_CURL) disabled_error (); diff -r a98902bda11a -r bb2fa6e5b348 liboctave/util/url-transfer.h --- a/liboctave/util/url-transfer.h Mon Oct 14 11:28:29 2013 -0400 +++ b/liboctave/util/url-transfer.h Mon Oct 14 15:00:12 2013 -0400 @@ -47,24 +47,23 @@ friend class url_transfer; base_url_transfer (void) - : count (1), host (), userpwd (), valid (false), ascii_mode (false), - ok (true), errmsg (), curr_istream (&std::cin), curr_ostream (&std::cout) + : count (1), host_or_url (), valid (false), ftp (false), + ascii_mode (false), ok (true), errmsg (), + curr_istream (&std::cin), curr_ostream (&std::cout) { } - base_url_transfer (const std::string& host_arg, + base_url_transfer (const std::string& host, const std::string& /* user_arg */, const std::string& /* passwd */, std::ostream& os) - : count (1), host (host_arg), userpwd (), valid (false), + : count (1), host_or_url (host), valid (false), ftp (true), ascii_mode (false), ok (true), errmsg (), curr_istream (&std::cin), curr_ostream (&os) { } - base_url_transfer (const std::string& /* url */, - const std::string& /* method */, - const Array& /* param */, - std::ostream& os) - : count (1), host (), userpwd (), valid (false), ascii_mode (false), - ok (true), errmsg (), curr_istream (&std::cin), curr_ostream (&os) { } + base_url_transfer (const std::string& url, std::ostream& os) + : count (1), host_or_url (url), valid (false), ftp (false), + ascii_mode (false), ok (true), errmsg (), + curr_istream (&std::cin), curr_ostream (&os) { } virtual ~base_url_transfer (void) { } @@ -128,12 +127,22 @@ virtual std::string pwd (void) { return std::string (); } + virtual void http_get (const Array& /* param */) { } + + virtual void http_post (const Array& /* param */) { } + + virtual void http_action (const Array& /* param */, + const std::string& /* action */) { } + protected: + // Reference count. octave_refcount count; - std::string host; - std::string userpwd; + + // Host for ftp transfers or full URL for http requests. + std::string host_or_url; bool valid; + bool ftp; bool ascii_mode; bool ok; std::string errmsg; @@ -158,8 +167,7 @@ url_transfer (const std::string& host, const std::string& user, const std::string& passwd, std::ostream& os); - url_transfer (const std::string& url, const std::string& method, - const Array& param, std::ostream& os); + url_transfer (const std::string& url, std::ostream& os); url_transfer (const url_transfer& h) : rep (h.rep) { @@ -257,6 +265,16 @@ std::string pwd (void) { return rep->pwd (); } + void http_get (const Array& param) { rep->http_get (param); } + + void http_post (const Array& param) { rep->http_post (param); } + + void http_action (const Array& param, + const std::string& action) + { + rep->http_action (param, action); + } + private: base_url_transfer *rep; diff -r a98902bda11a -r bb2fa6e5b348 m4/acinclude.m4 --- a/m4/acinclude.m4 Mon Oct 14 11:28:29 2013 -0400 +++ b/m4/acinclude.m4 Mon Oct 14 15:00:12 2013 -0400 @@ -1467,7 +1467,7 @@ [octave_cv_callinst_addattribute_arg_is_attributes], [AC_LANG_PUSH(C++) AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([ + [AC_LANG_PROGRAM([[ #ifdef HAVE_LLVM_IR_FUNCTION_H #include #include @@ -1475,7 +1475,7 @@ #include #include #endif - ], [[ + ]], [[ llvm::CallInst *callinst; llvm::AttrBuilder attr_builder; attr_builder.addAttribute(llvm::Attributes::StructRet); @@ -1534,9 +1534,9 @@ [AC_LANG_PUSH(C++) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ -#ifdef LLVM_HAVE_IR_FUNCTION_H - #include - #include +#ifdef HAVE_LLVM_IR_FUNCTION_H + #include + #include #else #include #include diff -r a98902bda11a -r bb2fa6e5b348 scripts/general/cart2pol.m --- a/scripts/general/cart2pol.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/general/cart2pol.m Mon Oct 14 15:00:12 2013 -0400 @@ -19,20 +19,20 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{theta}, @var{r}] =} cart2pol (@var{x}, @var{y}) ## @deftypefnx {Function File} {[@var{theta}, @var{r}, @var{z}] =} cart2pol (@var{x}, @var{y}, @var{z}) -## @deftypefnx {Function File} {[@var{theta}, @var{r}] =} cart2pol (@var{c}) -## @deftypefnx {Function File} {[@var{theta}, @var{r}, @var{z}] =} cart2pol (@var{c}) -## @deftypefnx {Function File} {@var{p} =} cart2pol (@dots{}) +## @deftypefnx {Function File} {[@var{theta}, @var{r}] =} cart2pol (@var{C}) +## @deftypefnx {Function File} {[@var{theta}, @var{r}, @var{z}] =} cart2pol (@var{C}) +## @deftypefnx {Function File} {@var{P} =} cart2pol (@dots{}) ## ## Transform Cartesian to polar or cylindrical coordinates. ## ## @var{theta} describes the angle relative to the positive x-axis. ## @var{r} is the distance to the z-axis @w{(0, 0, z)}. -## @var{x}, @var{y} (and @var{z}) must be the same shape, or scalar. -## If called with a single matrix argument then each row of @var{c} +## @var{x}, @var{y} (, and @var{z}) must be the same shape, or scalar. +## If called with a single matrix argument then each row of @var{C} ## represents the Cartesian coordinate (@var{x}, @var{y} (, @var{z})). ## ## If only a single return argument is requested then return a matrix -## @var{p} where each row represents one polar/(cylindrical) coordinate +## @var{P} where each row represents one polar/(cylindrical) coordinate ## (@var{theta}, @var{phi} (, @var{z})). ## @seealso{pol2cart, cart2sph, sph2cart} ## @end deftypefn @@ -40,7 +40,7 @@ ## Author: Kai Habel ## Adapted-by: jwe -function [theta, r, z] = cart2pol (x, y, z) +function [theta, r, z] = cart2pol (x, y, z = []) if (nargin < 1 || nargin > 3) print_usage (); @@ -50,8 +50,6 @@ if (ismatrix (x) && (columns (x) == 2 || columns (x) == 3)) if (columns (x) == 3) z = x(:,3); - else - z = []; endif y = x(:,2); x = x(:,1); @@ -76,7 +74,7 @@ r = sqrt (x .^ 2 + y .^ 2); if (nargout <= 1) - theta = [theta, r, z]; + theta = [theta(:), r(:), z(:)]; endif endfunction @@ -92,9 +90,9 @@ %!test %! x = [0, 1, 2]; %! y = [0, 1, 2]; -%! [t, r] = cart2pol (x, y); -%! assert (t, [0, pi/4, pi/4], sqrt (eps)); -%! assert (r, sqrt (2)*[0, 1, 2], sqrt (eps)); +%! P = cart2pol (x, y); +%! assert (P(:,1), [0; pi/4; pi/4], sqrt (eps)); +%! assert (P(:,2), sqrt (2)*[0; 1; 2], sqrt (eps)); %!test %! x = [0, 1, 2]; diff -r a98902bda11a -r bb2fa6e5b348 scripts/general/cart2sph.m --- a/scripts/general/cart2sph.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/general/cart2sph.m Mon Oct 14 15:00:12 2013 -0400 @@ -26,11 +26,11 @@ ## @var{phi} is the angle relative to the xy-plane. ## @var{r} is the distance to the origin @w{(0, 0, 0)}. ## @var{x}, @var{y}, and @var{z} must be the same shape, or scalar. -## If called with a single matrix argument then each row of @var{c} +## If called with a single matrix argument then each row of @var{C} ## represents the Cartesian coordinate (@var{x}, @var{y}, @var{z}). ## ## If only a single return argument is requested then return a matrix -## @var{s} where each row represents one spherical coordinate +## @var{S} where each row represents one spherical coordinate ## (@var{theta}, @var{phi}, @var{r}). ## @seealso{sph2cart, cart2pol, pol2cart} ## @end deftypefn @@ -66,7 +66,7 @@ r = sqrt (x .^ 2 + y .^ 2 + z .^ 2); if (nargout <= 1) - theta = [theta, phi, r]; + theta = [theta(:), phi(:), r(:)]; endif endfunction @@ -85,10 +85,10 @@ %! x = 0; %! y = [0, 1, 2]; %! z = [0, 1, 2]; -%! [t, p, r] = cart2sph (x, y, z); -%! assert (t, [0, 1, 1] * pi/2, eps); -%! assert (p, [0, 1, 1] * pi/4, eps); -%! assert (r, [0, 1, 2] * sqrt (2), eps); +%! S = cart2sph (x, y, z); +%! assert (S(:,1), [0; 1; 1] * pi/2, eps); +%! assert (S(:,2), [0; 1; 1] * pi/4, eps); +%! assert (S(:,3), [0; 1; 2] * sqrt (2), eps); %!test %! x = [0, 1, 2]; diff -r a98902bda11a -r bb2fa6e5b348 scripts/general/pol2cart.m --- a/scripts/general/pol2cart.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/general/pol2cart.m Mon Oct 14 15:00:12 2013 -0400 @@ -19,16 +19,17 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{x}, @var{y}] =} pol2cart (@var{theta}, @var{r}) ## @deftypefnx {Function File} {[@var{x}, @var{y}, @var{z}] =} pol2cart (@var{theta}, @var{r}, @var{z}) -## @deftypefnx {Function File} {[@var{x}, @var{y}] =} pol2cart (@var{p}) -## @deftypefnx {Function File} {[@var{x}, @var{y}, @var{z}] =} pol2cart (@var{p}) +## @deftypefnx {Function File} {[@var{x}, @var{y}] =} pol2cart (@var{P}) +## @deftypefnx {Function File} {[@var{x}, @var{y}, @var{z}] =} pol2cart (@var{P}) ## @deftypefnx {Function File} {@var{C} =} pol2cart (@dots{}) ## Transform polar or cylindrical to Cartesian coordinates. ## ## @var{theta}, @var{r}, (and @var{z}) must be the same shape, or scalar. ## @var{theta} describes the angle relative to the positive x-axis. ## @var{r} is the distance to the z-axis (0, 0, z). -## If called with a single matrix argument then each row of @var{p} -## represents the polar/(cylindrical) coordinate (@var{x}, @var{y} (, @var{z})). +## If called with a single matrix argument then each row of @var{P} +## represents the polar/(cylindrical) coordinate (@var{theta}, @var{r} (, +## @var{z})). ## ## If only a single return argument is requested then return a matrix ## @var{C} where each row represents one Cartesian coordinate @@ -39,7 +40,7 @@ ## Author: Kai Habel ## Adapted-by: jwe -function [x, y, z] = pol2cart (theta, r, z) +function [x, y, z] = pol2cart (theta, r, z = []) if (nargin < 1 || nargin > 3) print_usage (); @@ -49,8 +50,6 @@ if (ismatrix (theta) && (columns (theta) == 2 || columns (theta) == 3)) if (columns (theta) == 3) z = theta(:,3); - else - z = []; endif r = theta(:,2); theta = theta(:,1); @@ -75,7 +74,7 @@ y = r .* sin (theta); if (nargout <= 1) - x = [x, y, z]; + x = [x(:), y(:), z(:)]; endif endfunction @@ -91,9 +90,9 @@ %!test %! t = [0, 1, 1] * pi/4; %! r = sqrt (2) * [0, 1, 2]; -%! [x, y] = pol2cart (t, r); -%! assert (x, [0, 1, 2], sqrt (eps)); -%! assert (y, [0, 1, 2], sqrt (eps)); +%! C = pol2cart (t, r); +%! assert (C(:,1), [0; 1; 2], sqrt (eps)); +%! assert (C(:,2), [0; 1; 2], sqrt (eps)); %!test %! t = [0, 1, 1] * pi/4; diff -r a98902bda11a -r bb2fa6e5b348 scripts/general/sph2cart.m --- a/scripts/general/sph2cart.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/general/sph2cart.m Mon Oct 14 15:00:12 2013 -0400 @@ -19,14 +19,14 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{x}, @var{y}, @var{z}] =} sph2cart (@var{theta}, @var{phi}, @var{r}) ## @deftypefnx {Function File} {[@var{x}, @var{y}, @var{z}] =} sph2cart (@var{S}) -## @deftypefnx {Function File} {C =} sph2cart (@dots{}) +## @deftypefnx {Function File} {@var{C} =} sph2cart (@dots{}) ## Transform spherical to Cartesian coordinates. ## ## @var{theta} describes the angle relative to the positive x-axis. ## @var{phi} is the angle relative to the xy-plane. ## @var{r} is the distance to the origin @w{(0, 0, 0)}. ## @var{theta}, @var{phi}, and @var{r} must be the same shape, or scalar. -## If called with a single matrix argument then each row of @var{s} +## If called with a single matrix argument then each row of @var{S} ## represents the spherical coordinate (@var{theta}, @var{phi}, @var{r}). ## ## If only a single return argument is requested then return a matrix @@ -66,7 +66,7 @@ z = r .* sin (phi); if (nargout <= 1) - x = [x, y, z]; + x = [x(:), y(:), z(:)]; endif endfunction @@ -85,10 +85,10 @@ %! t = 0; %! p = [0, 0, 0]; %! r = [0, 1, 2]; -%! [x, y, z] = sph2cart (t, p, r); -%! assert (x, r); -%! assert (y, [0, 0, 0]); -%! assert (z, [0, 0, 0]); +%! C = sph2cart (t, p, r); +%! assert (C(:,1), r(:)); +%! assert (C(:,2), [0; 0; 0]); +%! assert (C(:,3), [0; 0; 0]); %!test %! t = [0, 0, 0]; diff -r a98902bda11a -r bb2fa6e5b348 scripts/help/get_first_help_sentence.m --- a/scripts/help/get_first_help_sentence.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/help/get_first_help_sentence.m Mon Oct 14 15:00:12 2013 -0400 @@ -107,10 +107,9 @@ for k = 1:length (def_idx) endl = endl_idx(find (endl_idx > def_idx(k), 1)); if (isempty (endl)) - keep(def_idx(k):end) = false; - else - keep(def_idx(k):endl) = false; + endl = numel (keep); endif + keep(def_idx(k):endl) = false; endfor ## Remove the @end ... that corresponds to the @def we removed above @@ -125,16 +124,11 @@ sep_idx = min (space_idx, bracket_idx); def_type = help_text(def1+1:sep_idx-1); - end_idx = strfind (help_text, sprintf ("@end %s", def_type)); + end_idx = strfind (help_text, sprintf ("@end %s", def_type))(1); if (isempty (end_idx)) error ("get_first_help_sentence: couldn't parse texinfo"); endif - endl = endl_idx(find (endl_idx > end_idx, 1)); - if (isempty (endl)) - keep(end_idx:end) = false; - else - keep(end_idx:endl) = false; - endif + keep(end_idx:end) = false; help_text = help_text(keep); endif diff -r a98902bda11a -r bb2fa6e5b348 scripts/image/image.m --- a/scripts/image/image.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/image/image.m Mon Oct 14 15:00:12 2013 -0400 @@ -121,12 +121,13 @@ if (numel (x) > 2 && numel (y) > 2) ## Test data for non-linear spacing which is unsupported - ## FIXME: Need a better check on linearity - tol = 100*eps; + tol = .01; # 1% tolerance. FIXME: this value was chosen without thought. dx = diff (x); + dxmean = (max (x) - min (x)) / (numel (x) - 1); + dx = abs ((dx - dxmean) / dxmean); dy = diff (y); - dx = std (dx) / mean (abs (dx)); - dy = std (dy) / mean (abs (dy)); + dymean = (max (y) - min (y)) / (numel (y) - 1); + dy = abs ((dy - dymean) / dymean); if (any (dx > tol) || any (dy > tol)) warning ("image: non-linear X, Y data is ignored. IMG will be shown with linear mapping"); endif diff -r a98902bda11a -r bb2fa6e5b348 scripts/image/imformats.m --- a/scripts/image/imformats.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/image/imformats.m Mon Oct 14 15:00:12 2013 -0400 @@ -222,7 +222,6 @@ "PBM", {"pbm"}, false; "PCX", {"pcx"}, true; "PGM", {"pgm"}, false; - "PGM", {"pgm"}, false; "PNG", {"png"}, true; ## PNM is a family of formats supporting portable bitmaps (PBM), ## graymaps (PGM), and pixmaps (PPM). There is no file format diff -r a98902bda11a -r bb2fa6e5b348 scripts/miscellaneous/edit.m --- a/scripts/miscellaneous/edit.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/miscellaneous/edit.m Mon Oct 14 15:00:12 2013 -0400 @@ -229,8 +229,8 @@ endif return; otherwise - ## If none of the states match, assume both inputs are - ## actually both file names to be opened + ## If none of the states match, assume both inputs are actually + ## file names to be opened. editfilelist = varargin; endswitch elseif (nargin > 2) @@ -267,7 +267,7 @@ else ## Only one file name was supplied, get it from the cell array - file = editfilelist{1}; + file = tilde_expand (editfilelist{1}); ## Check whether the user is trying to edit a builtin or compiled function. switch (exist (file)) @@ -300,20 +300,20 @@ if (idx == 0) if (isempty (regexp (file, '\.m$'))) ## No ".m" at the end of the file, add to the list. - filelist{end+1} = [file ".m"]; + filelist(end+1) = [file ".m"]; endif if (isempty (regexp (file, '\.cc$'))) ## No ".cc" at the end of the file, add to the list. - filelist{end+1} = [file ".cc"]; + filelist(end+1) = [file ".cc"]; endif endif ## If the file includes a path, it may be an overloaded function. - if (! strcmp (file, "@") && index (file, filesep)) + if (! index (file, "@") && index (file, filesep)) ## No "@" at the beginning of the file, add to the list. numfiles = numel (filelist); for n = 1:numfiles - filelist{n+numfiles} = ["@" filelist{n}]; + filelist(n+numfiles) = ["@" filelist{n}]; endfor endif @@ -353,7 +353,7 @@ endif endif - ## If editing a new file that is neither a m-file or an oct-file, + ## If editing a new file that is neither an m-file or an oct-file, ## just edit it. fileandpath = file; idx = rindex (file, "."); diff -r a98902bda11a -r bb2fa6e5b348 scripts/miscellaneous/mkoctfile.m --- a/scripts/miscellaneous/mkoctfile.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/miscellaneous/mkoctfile.m Mon Oct 14 15:00:12 2013 -0400 @@ -143,8 +143,9 @@ function [output, status] = mkoctfile (varargin) bindir = octave_config_info ("bindir"); + ext = octave_config_info ("EXEEXT"); - shell_script = fullfile (bindir, sprintf ("mkoctfile-%s", OCTAVE_VERSION)); + shell_script = fullfile (bindir, sprintf ("mkoctfile-%s%s", OCTAVE_VERSION, ext)); if (! exist (shell_script, "file")) __gripe_missing_component__ ("mkoctfile", "mkoctfile"); diff -r a98902bda11a -r bb2fa6e5b348 scripts/miscellaneous/orderfields.m --- a/scripts/miscellaneous/orderfields.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/miscellaneous/orderfields.m Mon Oct 14 15:00:12 2013 -0400 @@ -19,19 +19,18 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{t}, @var{p}] =} orderfields (@var{s1}) ## @deftypefnx {Function File} {[@var{t}, @var{p}] =} orderfields (@var{s1}, @var{s2}) -## Return a copy of @var{s1} with fields arranged alphabetically or -## as specified by @var{s2}. +## Return a copy of @var{s1} with fields arranged alphabetically or as +## specified by @var{s2}. ## ## Given one struct, arrange field names in @var{s1} alphabetically. ## -## If the second argument is a struct, arrange field names in @var{s1} -## as they appear in @var{s2}. The second argument may also specify the -## order in a permutation vector or a cell array of strings containing -## the fieldnames of @var{s1} in the desired order. +## If the second argument is a struct, arrange field names in @var{s1} as they +## appear in @var{s2}. The second argument may also specify the order in a +## permutation vector or a cell array of strings containing the fieldnames of +## @var{s1} in the desired order. ## ## The optional second output argument @var{p} is assigned the permutation -## vector -## which converts the original name order into the new name order. +## vector which converts the original name order into the new name order. ## ## Examples: ## @@ -95,7 +94,7 @@ if (nargin == 1 || nargin == 2) if (! isstruct (s1)) - error ("orderfields: expecting argument to be a struct"); + error ("orderfields: S1 must be a struct"); endif else print_usage (); @@ -111,7 +110,7 @@ ## Two structures: return the fields in the order of s2. names = fieldnames (s2); if (! isequal (sort (fieldnames (s1)), sort (names))) - error ("orderfields: structures do not have same fields"); + error ("orderfields: structures do not have the same fields"); endif elseif (iscellstr (s2)) ## A structure and a list of fields: order by the list of fields. @@ -130,17 +129,23 @@ if (! isequal (t1, t2)) error ("orderfields: invalid permutation vector"); endif - names = names (s2); + names = names(s2); endif endif + ## Corner case of empty struct + if (isempty (names)) + t = struct (); + p = []; + endif + ## Find permutation vector which converts the original name order ## into the new name order. Note: could save a couple of sorts ## in some cases, but performance isn't critical. if (nargout == 2) - [oldel, oldidx] = sort (fieldnames (s1)); - [newel, newidx] = sort (names); + [~, oldidx] = sort (fieldnames (s1)); + [~, newidx] = sort (names); p = oldidx(newidx); endif @@ -195,3 +200,6 @@ %! assert (aa(2).x, 8); %! assert (aa(2).y{1}, 6); +## Corner case of empty struct, bug #40224 +%!assert (orderfields (struct ()), struct ()) + diff -r a98902bda11a -r bb2fa6e5b348 scripts/pkg/private/configure_make.m --- a/scripts/pkg/private/configure_make.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/pkg/private/configure_make.m Mon Oct 14 15:00:12 2013 -0400 @@ -28,9 +28,10 @@ src = fullfile (packdir, "src"); octave_bindir = octave_config_info ("bindir"); ver = version (); - mkoctfile_program = fullfile (octave_bindir, sprintf ("mkoctfile-%s", ver)); - octave_config_program = fullfile (octave_bindir, sprintf ("octave-config-%s", ver)); - octave_binary = fullfile (octave_bindir, sprintf ("octave-%s", ver)); + ext = octave_config_info ("EXEEXT"); + mkoctfile_program = fullfile (octave_bindir, sprintf ("mkoctfile-%s%s", ver, ext)); + octave_config_program = fullfile (octave_bindir, sprintf ("octave-config-%s%s", ver, ext)); + octave_binary = fullfile (octave_bindir, sprintf ("octave-%s%s", ver, ext)); cenv = {"MKOCTFILE"; mkoctfile_program; "OCTAVE_CONFIG"; octave_config_program; "OCTAVE"; octave_binary; diff -r a98902bda11a -r bb2fa6e5b348 scripts/plot/appearance/daspect.m --- a/scripts/plot/appearance/daspect.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/plot/appearance/daspect.m Mon Oct 14 15:00:12 2013 -0400 @@ -27,7 +27,7 @@ ## The aspect ratio is a normalized 3-element vector representing the span of ## the x, y, and z-axis limits. ## -## @code{(daspect (@var{mode}))} +## @code{daspect (@var{mode})} ## ## Set the data aspect ratio mode of the current axes. @var{mode} is ## either @qcode{"auto"} or @qcode{"manual"}. @@ -69,7 +69,7 @@ daratio = get (hax, "dataaspectratio"); else arg = varargin{1}; - if (isreal (arg)) + if (isnumeric (arg)) if (numel (arg) == 2) set (hax, "dataaspectratio", [arg, 1]); elseif (numel (arg) == 3) diff -r a98902bda11a -r bb2fa6e5b348 scripts/plot/appearance/pbaspect.m --- a/scripts/plot/appearance/pbaspect.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/plot/appearance/pbaspect.m Mon Oct 14 15:00:12 2013 -0400 @@ -70,7 +70,7 @@ pbratio = get (hax, "plotboxaspectratio"); else arg = varargin{1}; - if (isreal (arg)) + if (isnumeric (arg)) if (numel (arg) == 2) set (hax, "plotboxaspectratio", [arg, 1]); elseif (numel (arg) == 3) diff -r a98902bda11a -r bb2fa6e5b348 scripts/plot/draw/fill.m --- a/scripts/plot/draw/fill.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/plot/draw/fill.m Mon Oct 14 15:00:12 2013 -0400 @@ -72,6 +72,15 @@ hlist = []; iargs = __find_patches__ (varargin{:}); + opts = {}; + if (numel (varargin) > iargs(end) + 2) + opts = varargin(iargs(end)+3 : end); + endif + + if (! all (cellfun (@(x) iscolorspec (x), varargin(iargs + 2)))) + print_usage (); + endif + oldfig = []; if (! isempty (hax)) oldfig = get (0, "currentfigure"); @@ -79,24 +88,33 @@ unwind_protect hax = newplot (hax); old_nxtplt = get (hax, "nextplot"); - set (hax, "nextplot", "add"); + unwind_protect + set (hax, "nextplot", "add"); + + for i = 1 : length (iargs) + cdata = varargin{iargs(i) + 2}; + + ## Matlab uses flat/interp shading based on orientation of cdata. + if (isnumeric (cdata) && isrow (cdata)) + popt = ["facecolor", "flat", opts]; + else + popt = opts; + endif - for i = 1 : length (iargs) - if (i == length (iargs)) - args = varargin(iargs(i):end); - else - args = varargin(iargs(i):iargs(i+1)-1); + [htmp, fail] = __patch__ (hax, varargin{iargs(i)+(0:1)}, cdata, + popt{:}); + if (fail) + print_usage (); + endif + + hlist(end+1, 1) = htmp; + endfor + + unwind_protect_cleanup + if (strcmp (old_nxtplt, "replace")) + set (hax, "nextplot", old_nxtplt); endif - [htmp, fail] = __patch__ (hax, args{:}); - if (fail) - print_usage (); - endif - hlist(end + 1, 1) = htmp; - endfor - - if (strcmp (old_nxtplt, "replace")) - set (hax, "nextplot", old_nxtplt); - endif + end_unwind_protect unwind_protect_cleanup if (! isempty (oldfig)) @@ -111,45 +129,25 @@ endfunction function iargs = __find_patches__ (varargin) - iargs = []; - i = 1; - while (i < nargin) - iargs(end + 1) = i; - if (ischar (varargin{i}) - && (strcmpi (varargin{i}, "faces") - || strcmpi (varargin{i}, "vertices"))) - i += 4; - elseif (isnumeric (varargin{i})) - i += 2; - endif + iargs = 1:3:nargin; + optidx = find (! cellfun (@isnumeric, varargin(iargs)), 1); + iargs(optidx:end) = []; +endfunction - if (i <= nargin) - while (true); - if (ischar (varargin{i}) - && (strcmpi (varargin{i}, "faces") - || strcmpi (varargin{i}, "vertices"))) - break; - elseif (isnumeric (varargin{i})) - ## Assume its the colorspec - i++; - break; - elseif (ischar (varargin{i})) - colspec = tolower (varargin{i}); - collen = length (colspec); - if (any (strncmp (colspec, - {"blue", "black", "k", "red", "green", ... - "yellow", "magenta", "cyan", "white"}, - collen))) - i++; - break; - endif - else - i += 2; - endif - endwhile +function retval = iscolorspec (arg) + retval = false; + if (ischar (arg)) + persistent colors = {"y", "yellow", "r", "red", "m", "magenta", ... + "c", "cyan", "g", "green", "b", "blue", ... + "w", "white", "k", "black"}; + if (any (strcmpi (arg, colors))) + retval = true; endif - endwhile - + elseif (isnumeric (arg)) + ## Assume any numeric argument is correctly formatted cdata. + ## Let patch worry about the multple different input formats + retval = true; + endif endfunction diff -r a98902bda11a -r bb2fa6e5b348 scripts/plot/draw/isosurface.m --- a/scripts/plot/draw/isosurface.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/plot/draw/isosurface.m Mon Oct 14 15:00:12 2013 -0400 @@ -174,8 +174,7 @@ "FaceColor", "g", "EdgeColor", "k"); endif if (! ishold ()) - set (hax, "view", [-37.5, 30], - "xgrid", "on", "ygrid", "on", "zgrid", "on"); + set (hax, "view", [-37.5, 30], "box", "off"); endif case 1 varargout = {fvc}; @@ -195,6 +194,7 @@ %! [x,y,z] = meshgrid (-2:0.5:2, -2:0.5:2, -2:0.5:2); %! v = x.^2 + y.^2 + z.^2; %! isosurface (x, y, z, v, 1); +%! axis equal; %! title ('isosurface of a sphere'); %!shared x, y, z, val diff -r a98902bda11a -r bb2fa6e5b348 scripts/plot/draw/pcolor.m --- a/scripts/plot/draw/pcolor.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/plot/draw/pcolor.m Mon Oct 14 15:00:12 2013 -0400 @@ -63,7 +63,8 @@ if (nargin == 1) c = varargin{1}; [nr, nc] = size (c); - [x, y] = meshgrid (1:nc, 1:nr); + x = 1:nc; + y = 1:nr; z = zeros (nr, nc); elseif (nargin == 3) x = varargin{1}; @@ -85,6 +86,36 @@ set (htmp, "facecolor", "flat"); if (! ishold ()) set (hax, "view", [0, 90], "box", "on"); + ## FIXME: Maybe this should be in the general axis limit setting routine? + ## When values are integers (such as from meshgrid), we want to + ## use tight limits for pcolor, mesh, surf, etc. Situation is + ## complicated immensely by vector or matrix input and meshgrid() + ## or ndgrid() format. + meshgrid_fmt = true; + if (isvector (x)) + xrng = x(isfinite (x)); + else + xrng = x(1, isfinite (x(1,:))); # meshgrid format (default) + if (all (xrng == xrng(1))) + xrng = x(isfinite (x(:,1)), 1); # ndgrid format + meshgrid_fmt = false; + endif + endif + if (isvector (y)) + yrng = y(isfinite (y)); + else + if (meshgrid_fmt) + yrng = y(isfinite (y(:,1)), 1); + else + yrng = y(1, isfinite (y(1,:))); + endif + endif + if (all (xrng == fix (xrng))) + xlim ([min(xrng), max(xrng)]); + endif + if (all (yrng == fix (yrng))) + ylim ([min(yrng), max(yrng)]); + endif endif unwind_protect_cleanup diff -r a98902bda11a -r bb2fa6e5b348 scripts/plot/draw/private/__errcomm__.m --- a/scripts/plot/draw/private/__errcomm__.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/plot/draw/private/__errcomm__.m Mon Oct 14 15:00:12 2013 -0400 @@ -58,7 +58,8 @@ if (isvector (arg)) arg = arg(:); endif - if (any (size (arg) != sz)) + if (! isscalar (arg) && ((isvector (arg) && numel (arg) != prod (sz)) + || any (size (arg) != sz))) error ("%s: size of argument %d does not match others", caller, k-1); endif data{++ndata} = arg; diff -r a98902bda11a -r bb2fa6e5b348 scripts/plot/draw/rectangle.m --- a/scripts/plot/draw/rectangle.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/plot/draw/rectangle.m Mon Oct 14 15:00:12 2013 -0400 @@ -24,7 +24,6 @@ ## @deftypefnx {Function File} {} rectangle (@dots{}, "FaceColor", @var{fc}) ## @deftypefnx {Function File} {} rectangle (@var{hax}, @dots{}) ## @deftypefnx {Function File} {@var{h} =} rectangle (@dots{}) -## ## Draw a rectangular patch defined by @var{pos} and @var{curv}. ## ## The variable @code{@var{pos}(1:2)} defines the lower left-hand corner of @@ -43,7 +42,7 @@ ## by ## ## @example -## min (pos (1:2)) / max (pos (1:2)) * curv +## min (pos(1:2)) / max (pos(1:2)) * curv ## @end example ## ## Additional property/value pairs are passed to the underlying patch command. @@ -93,14 +92,14 @@ if (strcmpi (arg, "position")) pos = varargin{iarg+1}; varargin(iarg:iarg+1) = []; - if (!isvector (pos) || numel (pos) != 4) + if (! isvector (pos) || numel (pos) != 4) error ("rectangle: position must be a 4 element vector"); endif elseif (strcmpi (arg, "curvature")) curv2 = varargin{iarg+1}; varargin(iarg:iarg+1) = []; if (!isnumeric (curv2) || (numel (curv2) != 1 && numel (curv2) != 2)) - error ("rectangle: curvature must be a 2 element vector or a scalar"); + error ("rectangle: curvature must be a 2-element vector or a scalar"); endif if (any (curv2 < 0) || any (curv2 > 1)) error ("rectangle: curvature values must be between 0 and 1"); @@ -120,8 +119,8 @@ endwhile if (numel (curv2) == 1) - [a, ai] = min (pos (3 : 4)); - [b, bi] = max (pos (3 : 4)); + [a, ai] = min (pos(3:4)); + [b, bi] = max (pos(3:4)); if (ai < bi) curv = [curv2, curv2 .* a ./ b]; else @@ -131,13 +130,13 @@ curv = curv2; endif - if (all (curv) < 0.01) + if (all (curv < 0.01)) ## Special case : no curvature x = [pos(1), pos(1) + pos(3), pos(1) + pos(3), pos(1), pos(1)]; y = [pos(2), pos(2), pos(2) + pos(4), pos(2) + pos(4), pos(2)]; else p = pi / 2 * [0 : 15] / 15; - c = curv .* pos(3 : 4) / 2; + c = curv .* pos(3:4) / 2; cx = c(1) * sin (p) - c(1); cy = c(2) * cos (p) - c(2); x = [pos(1) - fliplr(cx), pos(1) + pos(3) + cx, ... @@ -148,7 +147,7 @@ hg = hggroup (); - h = patch ("xdata", x(:), "ydata", y(:), "facecolor", fc, "edgecolor", ec, ... + h = patch ("xdata", x(:), "ydata", y(:), "facecolor", fc, "edgecolor", ec, "parent", hg, varargin{:}); addproperty ("curvature", hg, "data", curv2); @@ -166,11 +165,11 @@ addlistener (hg, "facecolor", @update_props); endfunction -function update_data (h, d) +function update_data (h, ~) persistent recursion = false; ## Don't allow recursion - if (!recursion) + if (! recursion) unwind_protect recursion = true; @@ -179,8 +178,8 @@ curv2 = get (h, "curvature"); if (numel (curv2) == 1) - [a, ai] = min (pos (3 : 4)); - [b, bi] = max (pos (3 : 4)); + [a, ai] = min (pos(3:4)); + [b, bi] = max (pos(3:4)); if (ai < bi) curv = [curv2, curv2 .* a ./ b]; else @@ -190,13 +189,13 @@ curv = curv2; endif - if (all (curv) < 0.01) + if (all (curv < 0.01)) ## Special case : no curvature x = [pos(1), pos(1) + pos(3), pos(1) + pos(3), pos(1), pos(1)]; y = [pos(2), pos(2), pos(2) + pos(4), pos(2) + pos(4), pos(2)]; else p = pi / 2 * [0 : 15] / 15; - c = curv .* pos(3 : 4) / 2; + c = curv .* pos(3:4) / 2; cx = c(1) * sin (p) - c(1); cy = c(2) * cos (p) - c(2); x = [pos(1) - fliplr(cx), pos(1) + pos(3) + cx, ... @@ -212,12 +211,11 @@ endif endfunction -function update_props (h, d) +function update_props (h, ~) kids = get (h, "children"); - set (kids, "edgecolor", get (h, "edgecolor"), - "linewidth", get (h, "linewidth"), - "linestyle", get (h, "linestyle"), - "facecolor", get (h, "facecolor")); + set (kids, {"edgecolor", "linewidth", "linestyle", "facecolor"}, + get (h, {"edgecolor", "linewidth", "linestyle", "facecolor"})); + endfunction diff -r a98902bda11a -r bb2fa6e5b348 scripts/statistics/base/skewness.m --- a/scripts/statistics/base/skewness.m Mon Oct 14 11:28:29 2013 -0400 +++ b/scripts/statistics/base/skewness.m Mon Oct 14 15:00:12 2013 -0400 @@ -1,3 +1,4 @@ +## Copyright (C) 2013 Julien Bect ## Copyright (C) 1996-2012 John W. Eaton ## ## This file is part of Octave. @@ -18,26 +19,58 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {} skewness (@var{x}) -## @deftypefnx {Function File} {} skewness (@var{x}, @var{dim}) -## Compute the skewness of the elements of the vector @var{x}. +## @deftypefnx {Function File} {} skewness (@var{x}, @var{flag}) +## @deftypefnx {Function File} {} skewness (@var{x}, @var{flag}, @var{dim}) +## Compute the sample skewness of the elements of @var{x}: ## @tex ## $$ -## {\rm skewness} (x) = {1\over N \sigma^3} \sum_{i=1}^N (x_i-\bar{x})^3 +## {\rm skewness} (@var{x}) = {{{1\over N}\, +## \sum_{i=1}^N (@var{x}_i - \bar{@var{x}})^3} \over \sigma^3}, ## $$ -## where $\bar{x}$ is the mean value of $x$. +## where $N$ is the length of @var{x}, $\bar{@var{x}}$ its mean and $\sigma$ +## its (uncorrected) standard deviation. ## @end tex ## @ifnottex ## ## @example -## skewness (x) = 1/N std(x)^(-3) sum ((x - mean(x)).^3) +## @group +## mean ((@var{x} - mean (@var{x})).^3) +## skewness (@var{X}) = ------------------------. +## std (@var{x}).^3 +## @end group ## @end example ## ## @end ifnottex ## ## @noindent -## If @var{x} is a matrix, return the skewness along the -## first non-singleton dimension of the matrix. If the optional +## The optional argument @var{flag} controls which normalization is used. +## If @var{flag} is equal to 1 (default value, used when @var{flag} is omitted +## or empty), return the sample skewness as defined above. If @var{flag} is +## equal to 0, return the adjusted skewness coefficient instead: +## @tex +## $$ +## {\rm skewness} (@var{x}) = {\sqrt{N (N - 1)} \over N - 2} \times \, +## {{{1 \over N} \sum_{i=1}^N (@var{x}_i - \bar{@var{x}})^3} \over \sigma^3} +## $$ +## @end tex +## @ifnottex +## +## @example +## @group +## sqrt (N*(N-1)) mean ((@var{x} - mean (@var{x})).^3) +## skewness (@var{X}, 0) = -------------- * ------------------------. +## (N - 2) std (@var{x}).^3 +## @end group +## @end example +## +## @end ifnottex +## The adjusted skewness coefficient is obtained by replacing the sample second +## and third central moments by their bias-corrected versions. +## +## If @var{x} is a matrix, or more generally a multi-dimensional array, return +## the skewness along the first non-singleton dimension. If the optional ## @var{dim} argument is given, operate along this dimension. +## ## @seealso{var, kurtosis, moment} ## @end deftypefn @@ -45,9 +78,9 @@ ## Created: 29 July 1994 ## Adapted-By: jwe -function retval = skewness (x, dim) +function y = skewness (x, flag, dim) - if (nargin != 1 && nargin != 2) + if (nargin < 1) || (nargin > 3) print_usage (); endif @@ -55,47 +88,84 @@ error ("skewness: X must be a numeric vector or matrix"); endif + if (nargin < 2 || isempty (flag)) + flag = 1; # default: do not use the "bias corrected" version + else + if ((! isscalar (flag)) || (flag != 0 && flag != 1)) + error ("skewness: FLAG must be 0 or 1"); + endif + endif + nd = ndims (x); sz = size (x); - if (nargin != 2) + if (nargin < 3) ## Find the first non-singleton dimension. (dim = find (sz > 1, 1)) || (dim = 1); else - if (!(isscalar (dim) && dim == fix (dim)) - || !(1 <= dim && dim <= nd)) + if (!(isscalar (dim) && dim == fix (dim)) || !(1 <= dim && dim <= nd)) error ("skewness: DIM must be an integer and a valid dimension"); endif endif n = sz(dim); sz(dim) = 1; - x = center (x, dim); # center also promotes integer to double for next line - retval = zeros (sz, class (x)); - s = std (x, [], dim); - idx = find (s > 0); - x = sum (x .^ 3, dim); - retval(idx) = x(idx) ./ (n * s(idx) .^ 3); + + x = center (x, dim); # center also promotes integer, logical to double + s = std (x, 1, dim); # Normalize with 1/N + y = sum (x .^ 3, dim); + idx = (s != 0); + y(idx) ./= (n * s(idx) .^ 3); + y(! idx) = NaN; + + ## Apply bias correction to the second and third central sample moment + if (flag == 0) + if (n > 2) + y *= sqrt (n * (n - 1)) / (n - 2); + else + y(:) = NaN; + endif + endif endfunction -%!assert (skewness ([-1,0,1]), 0) -%!assert (skewness ([-2,0,1]) < 0) -%!assert (skewness ([-1,0,2]) > 0) -%!assert (skewness ([-3,0,1]) == -1*skewness ([-1,0,3])) +%!assert (skewness ([-1, 0, 1]), 0) +%!assert (skewness ([-2, 0, 1]) < 0) +%!assert (skewness ([-1, 0, 2]) > 0) +%!assert (skewness ([-3, 0, 1]) == -1 * skewness ([-1, 0, 3])) +%!assert (skewness (ones (3, 5)), NaN (1, 5)) + %!test %! x = [0; 0; 0; 1]; %! y = [x, 2*x]; -%! assert(all (abs (skewness (y) - [0.75, 0.75]) < sqrt (eps))); +%! assert (skewness (y), 1.154700538379251 * [1 1], 5*eps); + +%!assert (skewness ([1:5 10; 1:5 10], 0, 2), 1.439590274527954 * [1; 1], eps) +%!assert (skewness ([1:5 10; 1:5 10], 1, 2), 1.051328089232020 * [1; 1], 2*eps) +%!assert (skewness ([1:5 10; 1:5 10], [], 2), 1.051328089232020 * [1; 1], 2*eps) + +## Test behaviour on single input +%!assert (skewness (single ([1:5 10])), single (1.0513283), eps ("single")) +%!assert (skewness (single ([1 2]), 0), single (NaN)) -%!assert (skewness (single (1)), single (0)) +## Verify no "division-by-zero" warnings +%!test +%! wstate = warning ("query", "Octave:divide-by-zero"); +%! unwind_protect +%! lastwarn (""); # clear last warning +%! skewness (1); +%! assert (lastwarn (), ""); +%! unwind_protect_cleanup +%! warning (wstate, "Octave:divide-by-zero"); +%! end_unwind_protect -%% Test input validation +## Test input validation %!error skewness () %!error skewness (1, 2, 3) -%!error skewness (['A'; 'B']) -%!error skewness (1, ones (2,2)) -%!error skewness (1, 1.5) -%!error skewness (1, 0) -%!error skewness (1, 3) - +%!error skewness (['A'; 'B']) +%!error skewness (1, 2) +%!error skewness (1, [1 0]) +%!error skewness (1, [], ones (2,2)) +%!error skewness (1, [], 1.5) +%!error skewness (1, [], 0) +%!error skewness (1, [], 3) diff -r a98902bda11a -r bb2fa6e5b348 test/index.tst --- a/test/index.tst Mon Oct 14 11:28:29 2013 -0400 +++ b/test/index.tst Mon Oct 14 15:00:12 2013 -0400 @@ -227,3 +227,277 @@ %!error d(3,6); %!error dd(3,6); +## bug 31287 +%!test +%! y = ones (2, 2, 2); +%! x = ones (2, 2, 2); +%! x(false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2, 2); +%! x = ones (2, 2, 2); +%! x(false,[]) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2, 2); +%! x = ones (2, 2, 2); +%! x(false,[],false) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2, 2); +%! x = ones (2, 2, 2); +%! x(false, 1) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2, 2); +%! x = ones (2, 2, 2); +%! x(false, false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], []) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x([], []) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(1, []) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], 1, []) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(1, [], 1, 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], 1, 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! ea2 = ones (3, 2, 0, 2); +%! x(1, ea2) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! ea2 = ones (3, 2, 0, 2); +%! x(1, ea2) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! ea2 = ones (3, 2, 0, 2); +%! x([], 1, ea2) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! ea2 = ones (3, 2, 0, 2); +%! x(1, ea2, ea2) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! ea2 = ones (3, 2, 0, 2); +%! x(1, ea2, 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, 1) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x(false, 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(1, [], false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, false) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x(false, false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, [], false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], false, false, false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(1, [], false, false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(:, false) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x(:, false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, :) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x(false, :) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, :, [], 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(:, [], false) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%!error x(1, 1, []) = []; + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, false, 1) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, false, []) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, false, [], false) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(1, false, [], false) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(:, false, 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([]) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x([]) = []; +%! assert (x, y); + +%!test +%! y = []; +%! x = ones (2, 2); +%! x(:) = []; +%! assert (x, y); + +%!test +%! y = sparse ([]); +%! x = sparse (ones (2, 2)); +%! x(:) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x(false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], false) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x([], false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], false, :) = []; +%! assert (x, y); diff -r a98902bda11a -r bb2fa6e5b348 test/parser.tst --- a/test/parser.tst Mon Oct 14 11:28:29 2013 -0400 +++ b/test/parser.tst Mon Oct 14 15:00:12 2013 -0400 @@ -80,7 +80,19 @@ ## Level 11 (transpose and exponentiation) %!test +%! a = 2; +%! assert (2 ^a++, 4) +%! assert (a, 3) +%! assert (2 ^--a ^2, 16) +%! assert (a, 2) +%! assert (2 ^++a, 8) +%! assert (a, 3) +%! assert (a' ^2, 9) +%! assert (2 ^sin(0), 1) %! assert (-2 ^2, -4); +%! assert (2 ^+1 ^3, 8) +%! assert (2 ^-1 ^3, 0.125) +%! assert (2 ^~0 ^2, 4) %! assert (!0 ^0, false); %! assert (2*3 ^2, 18); %! assert (2+3 ^2, 11); @@ -196,8 +208,6 @@ ## Level 12 (postfix increment and decrement) ## No tests possible since a++-- is not valid ## Level 11 (transpose and exponentiation) -## Note: Exponentiation should be left-to-right, but Octave does right-to-left. -## See bug #33304. %!test %! assert (2^3**2, 64); %! assert ([2 3].^2.', [4;9]); @@ -208,9 +218,6 @@ %! assert (2^+4^3, 16^3); %! assert (2^~0^2, 4); -## Note: Exponentiation should be left-to-right, but Octave does right-to-left. -## See bug #33304. - ## Level 10 (unary plus/minus, prefix increment/decrement, not) %!test %! assert (+-+1, -1); @@ -275,3 +282,4 @@ %!test %! xyz(1) = 1; xyz /= 1; %! assert (xyz, 1); +