# HG changeset patch
# User Markus Mützel <markus.muetzel@gmx.de>
# Date 1572786989 -3600
#      Sun Nov 03 14:16:29 2019 +0100
# Node ID 23a661761d38f52b806eb03a7832e83a094bb38d
# Parent  587771c2899f5b2bd04deaf94a960d8963383442
Check if strings are valid UTF-8 on creation (bug #57107).

* ov-re-mat.cc (convert_to_str_internal): For row vectors only, validate UTF-8.

* chNDArray.cc (charNDArray (char c), charNDArray (const char *s),
  charNDArray (const std::string& s)): Validate UTF-8.

diff -r 587771c2899f -r 23a661761d38 libgui/src/m-editor/octave-qscintilla.cc
--- a/libgui/src/m-editor/octave-qscintilla.cc	Sat Oct 26 13:07:53 2019 +0200
+++ b/libgui/src/m-editor/octave-qscintilla.cc	Sun Nov 03 14:16:29 2019 +0100
@@ -131,6 +131,14 @@
     // Disable buffered drawing on all systems
     SendScintilla (SCI_SETBUFFEREDDRAW, false);
 
+#if defined (Q_OS_WIN32)
+    // enable DirectWrite
+    SendScintilla (SCI_SETBUFFEREDDRAW, SC_TECHNOLOGY_DIRECTWRITERETAIN);
+#endif
+
+    // enable support for bidirectional text
+    SendScintilla (SCI_SETBIDIRECTIONAL, SC_BIDIRECTIONAL_L2R);
+
 #if defined (HAVE_QSCI_VERSION_2_6_0)
     // find () was added in QScintilla 2.6
     cmd_set->find (QsciCommand::SelectionCopy)->setKey (0);
diff -r 587771c2899f -r 23a661761d38 libgui/src/main-window.cc
--- a/libgui/src/main-window.cc	Sat Oct 26 13:07:53 2019 +0200
+++ b/libgui/src/main-window.cc	Sun Nov 03 14:16:29 2019 +0100
@@ -1648,9 +1648,9 @@
               = QDir (settings->value ("octave_startup_dir").toString ());
           }
 
-        update_default_encoding
-          (settings->value (ed_default_enc.key,
-                            ed_default_enc.def).toString ());
+//        update_default_encoding
+//          (settings->value (ed_default_enc.key,
+//                            ed_default_enc.def).toString ());
       }
 
     if (! startup_dir.exists ())
diff -r 587771c2899f -r 23a661761d38 libgui/src/settings-dialog.cc
--- a/libgui/src/settings-dialog.cc	Sat Oct 26 13:07:53 2019 +0200
+++ b/libgui/src/settings-dialog.cc	Sun Nov 03 14:16:29 2019 +0100
@@ -252,7 +252,8 @@
     editor_showLineNumbers->setChecked (settings->value ("editor/showLineNumbers", true).toBool ());
     editor_linenr_size->setValue (settings->value ("editor/line_numbers_size", 0).toInt ());
 
-    m_resource_manager.combo_encoding (editor_combo_encoding);
+    m_resource_manager.combo_encoding (editor_combo_encoding,
+                    settings->value ("editor/default_encoding").toString ());
 
     default_var = QColor (240, 240, 240);
     QColor setting_color = settings->value ("editor/highlight_current_line_color", default_var).value<QColor> ();
diff -r 587771c2899f -r 23a661761d38 libinterp/corefcn/graphics.cc
--- a/libinterp/corefcn/graphics.cc	Sat Oct 26 13:07:53 2019 +0200
+++ b/libinterp/corefcn/graphics.cc	Sun Nov 03 14:16:29 2019 +0100
@@ -11947,7 +11947,8 @@
 
 private:
   set_event (void)
-    : base_graphics_event (), handle (), property_name (), property_value ()
+    : base_graphics_event (), handle (), property_name (), property_value (),
+      notify_toolkit (true), m_redraw_figure (false)
   { }
 
 private:
diff -r 587771c2899f -r 23a661761d38 libinterp/corefcn/interpreter-private.cc
--- a/libinterp/corefcn/interpreter-private.cc	Sat Oct 26 13:07:53 2019 +0200
+++ b/libinterp/corefcn/interpreter-private.cc	Sun Nov 03 14:16:29 2019 +0100
@@ -60,6 +60,11 @@
 
     return *interp;
   }
+  
+  bool __is_interpreter_ready__ (void)
+  {
+    return interpreter::the_interpreter ();
+  }
 
   dynamic_loader& __get_dynamic_loader__ (const std::string& who)
   {
diff -r 587771c2899f -r 23a661761d38 libinterp/corefcn/interpreter-private.h
--- a/libinterp/corefcn/interpreter-private.h	Sat Oct 26 13:07:53 2019 +0200
+++ b/libinterp/corefcn/interpreter-private.h	Sun Nov 03 14:16:29 2019 +0100
@@ -54,6 +54,8 @@
 
   extern interpreter& __get_interpreter__ (const std::string& who);
 
+  extern bool __is_interpreter_ready__ (void);
+
   extern dynamic_loader& __get_dynamic_loader__ (const std::string& who);
 
   extern error_system& __get_error_system__ (const std::string& who);
diff -r 587771c2899f -r 23a661761d38 libinterp/octave-value/ov-re-mat.cc
--- a/libinterp/octave-value/ov-re-mat.cc	Sat Oct 26 13:07:53 2019 +0200
+++ b/libinterp/octave-value/ov-re-mat.cc	Sun Nov 03 14:16:29 2019 +0100
@@ -50,6 +50,7 @@
 #include "mx-base.h"
 #include "quit.h"
 #include "oct-locbuf.h"
+#include "oct-string.h"
 
 #include "defun.h"
 #include "errwarn.h"
@@ -462,6 +463,13 @@
       chm(i) = static_cast<char> (ival);
     }
 
+  if (dv.numel () == 2 && dv(0) == 1)
+    {
+      std::string str = std::string (chm.data (), dv(1));
+      str = octave::string::validate_u8 ("convert_to_str_internal", str);
+      chm = str;
+    }
+
   retval = octave_value (chm, type);
 
   return retval;
diff -r 587771c2899f -r 23a661761d38 libinterp/parse-tree/lex.ll
--- a/libinterp/parse-tree/lex.ll	Sat Oct 26 13:07:53 2019 +0200
+++ b/libinterp/parse-tree/lex.ll	Sun Nov 03 14:16:29 2019 +0100
@@ -3696,6 +3696,10 @@
         bool eof = false;
         m_current_input_line = m_reader.get_input (prompt, eof);
 
+        if (input_from_file ())
+          std::cout << input_source () << std::endl;
+        
+        
         m_input_buf.fill (m_current_input_line, eof);
 
         // Attempt to capture text for functions defined on the
diff -r 587771c2899f -r 23a661761d38 liboctave/array/chNDArray.cc
--- a/liboctave/array/chNDArray.cc	Sat Oct 26 13:07:53 2019 +0200
+++ b/liboctave/array/chNDArray.cc	Sun Nov 03 14:16:29 2019 +0100
@@ -32,6 +32,7 @@
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "mx-op-defs.h"
+#include "oct-string.h"
 #include "str-vec.h"
 
 #include "bsxfun-defs.cc"
@@ -39,11 +40,13 @@
 charNDArray::charNDArray (char c)
   : Array<char> ()
 {
-  octave_idx_type n = 1;
+  std::string s_u8 = octave::string::validate_u8 ("charNDArray", std::string (1, c));
+  octave_idx_type n = s_u8.length ();
 
   resize1 (n);
 
-  elem (0) = c;
+  for (octave_idx_type i = 0; i < n; i++)
+    elem (i) = s_u8[i];
 }
 
 charNDArray::charNDArray (const char *s)
@@ -51,21 +54,25 @@
 {
   octave_idx_type n = (s ? strlen (s) : 0);
 
+  std::string s_u8 = octave::string::validate_u8 ("charNDArray", std::string (s, n));
+  n = s_u8.length ();
+
   resize1 (n);
 
   for (octave_idx_type i = 0; i < n; i++)
-    elem (i) = s[i];
+    elem (i) = s_u8[i];
 }
 
 charNDArray::charNDArray (const std::string& s)
   : Array<char> ()
 {
-  octave_idx_type n = s.length ();
+  std::string s_u8 = octave::string::validate_u8 ("charNDArray", s);
+  octave_idx_type n = s_u8.length ();
 
   resize1 (n);
 
   for (octave_idx_type i = 0; i < n; i++)
-    elem (i) = s[i];
+    elem (i) = s_u8[i];
 }
 
 charNDArray::charNDArray (const string_vector& s, char fill_value)
diff -r 587771c2899f -r 23a661761d38 liboctave/util/lo-error.h
--- a/liboctave/util/lo-error.h	Sat Oct 26 13:07:53 2019 +0200
+++ b/liboctave/util/lo-error.h	Sun Nov 03 14:16:29 2019 +0100
@@ -29,15 +29,19 @@
 extern "C" {
 #endif
 
+OCTAVE_FORMAT_PRINTF (1, 2)
 OCTAVE_NORETURN extern void
 liboctave_fatal (const char *fmt, ...);
 
+OCTAVE_FORMAT_PRINTF (2, 3)
 OCTAVE_NORETURN extern
 void liboctave_fatal_with_id (const char *id, const char *fmt, ...);
 
+OCTAVE_FORMAT_PRINTF (1, 2)
 extern void
 liboctave_warning (const char *fmt, ...);
 
+OCTAVE_FORMAT_PRINTF (2, 3)
 extern void
 liboctave_warning_with_id (const char *id, const char *fmt, ...);
 
diff -r 587771c2899f -r 23a661761d38 scripts/miscellaneous/tar.m
--- a/scripts/miscellaneous/tar.m	Sat Oct 26 13:07:53 2019 +0200
+++ b/scripts/miscellaneous/tar.m	Sun Nov 03 14:16:29 2019 +0100
@@ -122,7 +122,7 @@
 %!   fclose (fid);
 %!   tarname = [tempname() ".tar"];
 %!   filelist = tar (tarname, {dirname2, fname1});
-%!   if (! strcmp (filelist{3}, fname1))
+%!   if (! is_same_file (filelist{3}, fname1))
 %!     error ("tar file contents does not match expected file");
 %!   endif
 %!   if (! exist (tarname, "file"))
diff -r 587771c2899f -r 23a661761d38 scripts/pkg/pkg.m
--- a/scripts/pkg/pkg.m	Sat Oct 26 13:07:53 2019 +0200
+++ b/scripts/pkg/pkg.m	Sun Nov 03 14:16:29 2019 +0100
@@ -316,7 +316,7 @@
   # valid actions in alphabetical order
   available_actions = {"build", "describe", "global_list",  "install", ...
                        "list", "load", "local_list", "prefix", "rebuild", ...
-                       "uninstall", "unload", "update"};
+                       "test", "uninstall", "unload", "update"};
 
   ## Parse input arguments
   if (isempty (varargin) || ! iscellstr (varargin))
@@ -583,6 +583,24 @@
           clear ("local_packages");
         endif
       endif
+    
+    case "test"
+      if (isempty (files))
+        error ("you must specify at least one package, or 'all' when calling 'pkg test'");
+      endif
+      ## Make sure, the packages are loaded
+      load_packages (files, deps, local_list, global_list);
+      
+      if (numel (files) == 1 && strcmp (files {1}, "all"))
+        files = {};
+      endif
+      installed_pkgs_lst = installed_packages (local_list, global_list, files);
+      installed_pkgs_path = cellfun (@(x) x.dir, ...
+                                     installed_pkgs_lst, ...
+                                     "uniformoutput", false);
+      if (not (isempty (installed_pkgs_path)))
+        __run_test_suite__ (installed_pkgs_path, {})
+      endif
 
     case "build"
       if (numel (files) < 2)
