[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#925219: unblock: sigil/0.9.13-1



Package: release.debian.org
User: release.debian.org@packages.debian.org
Usertags: unblock

Dear RT,

I've just uploaded a sigil/0.9.13-1, with the latest upstream release.

It's a mostly bugfix release, that once stripped of the doc changes and
translation updates boils down to
     57 files changed, 643 insertions(+), 883 deletions(-)

According to upstream, 0.9.12 (released in February) is "very buggy"
(https://github.com/Sigil-Ebook/Sigil/wiki#versions-0911-and-0912-of-sigil-are-very-buggy)
and are not quite fit for usage.

Also, there is finally built-in support for system-wide mathjs, so we
are not patch-free, which is a great thing by itself for me :)

Please find attached the stripped down debdiff created with
    /usr/bin/debdiff sigil_0.9.12+dfsg-1.dsc sigil_0.9.13+dfsg-1.dsc | filterdiff -x '*/ts/*' | filterdiff -x '*/docs/*'

Thanks for considering.

-- 
regards,
                        Mattia Rizzolo

GPG Key: 66AE 2B4A FCCF 3F52 DA18  4D18 4B04 3FCD B944 4540      .''`.
more about me:  https://mapreri.org                             : :'  :
Launchpad user: https://launchpad.net/~mapreri                  `. `'`
Debian QA page: https://qa.debian.org/developer.php?login=mattia  `-
diffstat for sigil-0.9.12+dfsg sigil-0.9.13+dfsg

 CMakeLists.txt                                             |    2 
 ChangeLog.txt                                              |   23 
 README.md                                                  |    2 
 appveyor.yml                                               |   13 
 debian/changelog                                           |   11 
 debian/control                                             |    2 
 debian/copyright                                           |    8 
 debian/patches/mathajx                                     |   50 -
 debian/patches/series                                      |    1 
 debian/rules                                               |    3 
 debian/sigil-data.install                                  |    1 
 internal/gumbo/tokenizer.c                                 |    6 
 src/CMakeLists.txt                                         |   40 
 src/Dialogs/ClipEditor.cpp                                 |   22 
 src/Dialogs/ClipboardHistorySelector.cpp                   |    3 
 src/Dialogs/Reports.cpp                                    |    1 
 src/Dialogs/ReportsWidgets/AllFilesWidget.cpp              |    7 
 src/Dialogs/ReportsWidgets/AllFilesWidget.h                |    2 
 src/Dialogs/ReportsWidgets/CSSFilesWidget.cpp              |    7 
 src/Dialogs/ReportsWidgets/CSSFilesWidget.h                |    2 
 src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.cpp |    6 
 src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.h   |    2 
 src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.cpp    |    6 
 src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.h      |    2 
 src/Dialogs/ReportsWidgets/HTMLFilesWidget.cpp             |    7 
 src/Dialogs/ReportsWidgets/HTMLFilesWidget.h               |    2 
 src/Dialogs/ReportsWidgets/ImageFilesWidget.cpp            |    7 
 src/Dialogs/ReportsWidgets/ImageFilesWidget.h              |    2 
 src/Dialogs/ReportsWidgets/LinksWidget.cpp                 |    6 
 src/Dialogs/ReportsWidgets/LinksWidget.h                   |    2 
 src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.cpp      |    6 
 src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.h        |    2 
 src/Dialogs/SearchEditor.cpp                               |   15 
 src/MainUI/FindReplace.cpp                                 |    5 
 src/MainUI/FindReplace.h                                   |    1 
 src/MainUI/MainWindow.cpp                                  |   60 +
 src/MainUI/MainWindow.h                                    |    1 
 src/MainUI/PreviewWindow.cpp                               |   22 
 src/Misc/CSSInfo.cpp                                       |   24 
 src/Misc/CSSInfo.h                                         |    3 
 src/Misc/EmbeddedPythonPkg.cpp                             |  617 -------------
 src/Misc/FilenameDelegate.cpp                              |   13 
 src/Misc/SettingsStore.cpp                                 |   10 
 src/MiscEditors/ClipEditorModel.cpp                        |   99 +-
 src/MiscEditors/ClipEditorModel.h                          |    1 
 src/MiscEditors/IndexEditorModel.cpp                       |  103 +-
 src/MiscEditors/SearchEditorModel.cpp                      |  106 +-
 src/Resource_Files/plugin_launchers/python/wrapper.py      |    2 
 src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js        |   23 
 src/Resource_Files/windows/version.rc.in                   |    2 
 src/SourceUpdates/PerformCSSUpdates.cpp                    |    2 
 src/Tabs/TabManager.cpp                                    |   33 
 src/ViewEditors/BookViewPreview.cpp                        |   17 
 src/ViewEditors/CodeViewEditor.cpp                         |    9 
 src/main.cpp                                               |  100 +-
 src/sigil_constants.cpp                                    |    1 
 src/sigil_constants.h                                      |    1 
 57 files changed, 643 insertions(+), 883 deletions(-)

diff -Nru sigil-0.9.12+dfsg/appveyor.yml sigil-0.9.13+dfsg/appveyor.yml
--- sigil-0.9.12+dfsg/appveyor.yml	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/appveyor.yml	2019-03-20 01:01:44.000000000 +0100
@@ -1,4 +1,4 @@
-version: '0.9.10-{build}'
+version: '0.9.13-{build}'
 
 branches:
   only:
@@ -13,7 +13,6 @@
 configuration: Release
 
 platform:
-- x86
 - x64
 
 clone_script:
@@ -34,19 +33,19 @@
   global:
       INNO: C:\Program Files (x86)\Inno Setup 5
       REDIST: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\1033\vcredist_%PLATFORM%.exe
-      DOWNLOAD: https://github.com/dougmassay/win-qtwebkit-5.212/releases/download/v5.212-1/qt5.11-custom-webkit-%PLATFORM%.zip
+      DOWNLOAD: https://github.com/dougmassay/win-qtwebkit-5.212/releases/download/v5.212-1/qt5.12-custom-webkit-%PLATFORM%.zip
   matrix:
     - PYTHON: C:\Python37
-      QT: C:\Qt\5.11\msvc2015
+      QT: C:\Qt\5.12\msvc2015
       CMAKE64BIT:
     - PYTHON: C:\Python37-x64
-      QT: C:\Qt\5.11\msvc2015_64
+      QT: C:\Qt\5.12\msvc2015_64
       CMAKE64BIT: -DWIN_INSTALLER_USE_64BIT_CRT=1
 
 matrix:
   exclude:
     - platform: x86
-      PYTHON: C:\Python37-x64
+      PYTHON: C:\Python37
     - platform: x64
       PYTHON: C:\Python37
   fast_finish: true
@@ -81,7 +80,7 @@
     pip3.7 install cssselect==1.0.3
     pip3.7 install chardet==3.0.4
     pip3.7 install pillow==5.4.1
-    pip3.7 install PyQt5==5.11.3
+    pip3.7 install PyQt5==5.12
     pip3.7 install lxml==4.2.6
     cd project\sigil\build
     call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %PLATFORM%
diff -Nru sigil-0.9.12+dfsg/ChangeLog.txt sigil-0.9.13+dfsg/ChangeLog.txt
--- sigil-0.9.12+dfsg/ChangeLog.txt	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/ChangeLog.txt	2019-03-20 01:01:44.000000000 +0100
@@ -1,3 +1,26 @@
+Sigil-0.9.13
+   Bug Fixes
+     - Revert change of INI encoding to utf-8 as QSettings very broken under utf-8 (commit 5484463)
+     - Ensure all url attributes in shape-outside properties in CSS stylesheets get updated (commit de7b09f)
+     - Workaround for lost cursor in qlineedit Qt bug (issue #398) (commit a8acab7)
+     - Workaround missing File New, Open, Quit menus in Mac menubar if windows closed (commit 660a8aa)
+     - Remove Icon from Tab for macOS only to workaround Qt bug (commit 5c91924)
+     - Plug some memory leaks (commits: 85f78d7, cb9b833, 614d601, bf2f2f4, ebfb613, 4qa8f33) 
+     - Backport Qt 5.12alpha fix to prevent heap corruption due to qwidget next focus pointers (commit f5c7284)
+     - Plug macOS memory leaks when closing a main window (commit fbf9015)
+     - Put back quote in tag name bug fix lost in recent changes (commit ebd8c7c)
+     - Disable Netscape Plugins being used in BookView and Preview Window (commit 79314ea)
+     - Use custom version of qtwebkit with Qt 5.5 memory leak fix added back and no load plugins if disabled 
+       	   (see commits 94a28d7,  9f7ebba, and 4b968a9)
+
+   New Features
+     - Add filename to tab tooltip (commit 27f8db7)
+     - Clear memory caches when Preview changes to keep memory footprint smaller (commit 87b9247)
+     - Update to MathJax 2.75, adds support for mathml mlongdiv, mstack, mcarries (commit 568aba5)
+     - Reduce memory footprint by letting worker threads expire (commit c1ee7ca)
+     - Reduce memory footprint by properly setting web page caches (commit 9f07cbe)
+
+
 Sigil-0.9.12
    Bug Fixes
     - fix typo in cssreformatter that caused errors with @fontface (issue #394)
diff -Nru sigil-0.9.12+dfsg/CMakeLists.txt sigil-0.9.13+dfsg/CMakeLists.txt
--- sigil-0.9.12+dfsg/CMakeLists.txt	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/CMakeLists.txt	2019-03-20 01:01:44.000000000 +0100
@@ -29,7 +29,7 @@
 
 set( SIGIL_MAJOR_VERSION 0 )
 set( SIGIL_MINOR_VERSION 9 )
-set( SIGIL_REVISION_VERSION 12 )
+set( SIGIL_REVISION_VERSION 13 )
 set( SIGIL_FULL_VERSION ${SIGIL_MAJOR_VERSION}.${SIGIL_MINOR_VERSION}.${SIGIL_REVISION_VERSION} )
 
 if( UNIX AND NOT APPLE )
diff -Nru sigil-0.9.12+dfsg/debian/changelog sigil-0.9.13+dfsg/debian/changelog
--- sigil-0.9.12+dfsg/debian/changelog	2019-02-19 13:50:47.000000000 +0100
+++ sigil-0.9.13+dfsg/debian/changelog	2019-03-21 13:02:08.000000000 +0100
@@ -1,3 +1,14 @@
+sigil (0.9.13+dfsg-1) unstable; urgency=medium
+
+  * New upstream version 0.9.13+dfsg.
+  * d/copyright:
+    + Update the Files-Excluded pattern.
+    + Update.
+  * Sigil now has native support for system-wide mathjx, leverage it,
+    and drop the local patch.
+
+ -- Mattia Rizzolo <mattia@debian.org>  Thu, 21 Mar 2019 13:02:08 +0100
+
 sigil (0.9.12+dfsg-1) unstable; urgency=medium
 
   * New upstream version 0.9.12+dfsg.
diff -Nru sigil-0.9.12+dfsg/debian/control sigil-0.9.13+dfsg/debian/control
--- sigil-0.9.12+dfsg/debian/control	2019-02-16 20:52:45.000000000 +0100
+++ sigil-0.9.13+dfsg/debian/control	2019-03-21 12:39:01.000000000 +0100
@@ -31,7 +31,7 @@
 Depends:
  libhunspell-dev,
  libjs-jquery-scrollto,
- libjs-mathjax,
+ libjs-mathjax (>= 2.7.0),
  python3-lxml,
  sigil-data (= ${source:Version}),
  ${misc:Depends},
diff -Nru sigil-0.9.12+dfsg/debian/copyright sigil-0.9.13+dfsg/debian/copyright
--- sigil-0.9.12+dfsg/debian/copyright	2019-02-16 20:43:41.000000000 +0100
+++ sigil-0.9.13+dfsg/debian/copyright	2019-03-21 12:42:32.000000000 +0100
@@ -10,7 +10,9 @@
  src/Resource_Files/dictionaries
  src/Resource_Files/javascript/jquery-*
  src/Resource_Files/javascript/jquery.scrollTo-*
- src/Resource_Files/polyfills
+ src/Resource_Files/polyfills/MathJax_License.txt
+ src/Resource_Files/polyfills/MathJax_README.md
+ src/Resource_Files/polyfills/ML.zip
 
 Files: *
 Copyright: 2009-2011 Strahinja Markovic <strahinja.markovic@gmail.com>
@@ -89,6 +91,10 @@
 Copyright: 2004-2013 Christof Hoeke
 License: LGPL-3+
 
+Files: src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js
+Copyright: 2010-2018 The MathJax Consortium
+License: Apache-2.0
+
 Files: src/Resource_Files/python3lib/cssreformatter.py
 Copyright: 2016 Francesco Martini
 License: GPL-3+
diff -Nru sigil-0.9.12+dfsg/debian/patches/mathajx sigil-0.9.13+dfsg/debian/patches/mathajx
--- sigil-0.9.12+dfsg/debian/patches/mathajx	2018-07-29 18:23:23.000000000 +0200
+++ sigil-0.9.13+dfsg/debian/patches/mathajx	1970-01-01 01:00:00.000000000 +0100
@@ -1,50 +0,0 @@
-Description: use system installation of MathJax instead of the bundled one
- This drops support for SIGIL_EXTRA_ROOT variable here, and given that common
- installation of MathJax are not single-file-built we need to configure the
- loader to load our the extensions we need.
- Thanks to Dmitry Shachnev <mitya57@debian.org> for helping out with the MathJax
- configuration.
-Author: Mattia Rizzolo <mattia@debian.org>
-Forwarded: no
-Last-Update: 2016-06-13
-
---- a/src/MainUI/PreviewWindow.cpp
-+++ b/src/MainUI/PreviewWindow.cpp
-@@ -211,18 +211,21 @@
-         mathjaxurl = "/" + QCoreApplication::applicationDirPath() + "/polyfills/MathJax.js";
- #else
-         // all flavours of linux / unix
--        // user supplied environment variable to 'share/sigil' directory will overrides everything
--        if (!sigil_extra_root.isEmpty()) {
--            mathjaxurl = sigil_extra_root + "/polyfills/MathJax.js";
--        } else {
--            mathjaxurl = sigil_share_root + "/polyfills/MathJax.js";
--        }
-+        mathjaxurl = "/usr/share/javascript/mathjax/MathJax.js";
- #endif
- 
-         mathjaxurl = "file://" + Utility::URLEncodePath(mathjaxurl);
-         int endheadpos = text.indexOf("</head>");
-         if (endheadpos > 1) {
-             QString inject_mathjax = 
-+              "<script type=\"text/x-mathjax-config\">"
-+              " MathJax.Hub.Config({"
-+              "  config: [\"MML_SVG.js\"],"
-+              "  extensions: [\"MatchWebFonts.js\"],"
-+              "  MathML: { extensions: [\"mml3.js\"] },"
-+              "  SVG: { blacker: 1 },"
-+              " });"
-+              "</script>"
-               "<script type=\"text/javascript\" "
-               "src=\"" + mathjaxurl + "\"></script>";
-             text.insert(endheadpos, inject_mathjax);
---- a/src/CMakeLists.txt
-+++ b/src/CMakeLists.txt
-@@ -997,7 +997,6 @@
-     if ( INSTALL_BUNDLED_DICTS )
-         install( FILES ${DIC_FILES} DESTINATION ${SIGIL_SHARE_ROOT}/hunspell_dictionaries/ )
-     endif()
--    install( FILES ${CMAKE_SOURCE_DIR}/src/Resource_Files/polyfills/MathJax.js DESTINATION ${SIGIL_SHARE_ROOT}/polyfills/ )
-     install( DIRECTORY ${CMAKE_SOURCE_DIR}/src/Resource_Files/plugin_launchers/python/ DESTINATION ${SIGIL_SHARE_ROOT}/plugin_launchers/python )
-     install( DIRECTORY ${CMAKE_SOURCE_DIR}/src/Resource_Files/python3lib/ DESTINATION ${SIGIL_SHARE_ROOT}/python3lib )
-     install( FILES ${EXAMPLE_FILES} DESTINATION ${SIGIL_SHARE_ROOT}/examples/ )
diff -Nru sigil-0.9.12+dfsg/debian/patches/series sigil-0.9.13+dfsg/debian/patches/series
--- sigil-0.9.12+dfsg/debian/patches/series	2017-03-22 10:26:53.000000000 +0100
+++ sigil-0.9.13+dfsg/debian/patches/series	1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-mathajx
diff -Nru sigil-0.9.12+dfsg/debian/rules sigil-0.9.13+dfsg/debian/rules
--- sigil-0.9.12+dfsg/debian/rules	2019-02-16 20:49:44.000000000 +0100
+++ sigil-0.9.13+dfsg/debian/rules	2019-03-21 12:39:01.000000000 +0100
@@ -13,7 +13,8 @@
 	dh_auto_configure -- \
 		-DUSE_SYSTEM_LIBS=1 \
 		-DSYSTEM_LIBS_REQUIRED=1 \
-		-DINSTALL_BUNDLED_DICTS=0
+		-DINSTALL_BUNDLED_DICTS=0 \
+		-DMATHJAX_DIR=/usr/share/javascript/mathjax/ \
 
 override_dh_install:
 	rm -v $(CURDIR)/debian/tmp/usr/share/sigil/plugin_launchers/python/sigil_bs4/COPYING.txt
diff -Nru sigil-0.9.12+dfsg/debian/sigil-data.install sigil-0.9.13+dfsg/debian/sigil-data.install
--- sigil-0.9.12+dfsg/debian/sigil-data.install	2017-03-22 10:37:37.000000000 +0100
+++ sigil-0.9.13+dfsg/debian/sigil-data.install	2019-03-21 12:40:27.000000000 +0100
@@ -1,2 +1,3 @@
+usr/share/javascript/mathjax/config/local/SIGIL_EBOOK_MML_SVG.js
 usr/share/pixmaps
 usr/share/sigil
diff -Nru sigil-0.9.12+dfsg/internal/gumbo/tokenizer.c sigil-0.9.13+dfsg/internal/gumbo/tokenizer.c
--- sigil-0.9.12+dfsg/internal/gumbo/tokenizer.c	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/internal/gumbo/tokenizer.c	2019-03-20 01:01:44.000000000 +0100
@@ -1088,6 +1088,12 @@
       abandon_current_tag(parser);
       gumbo_tokenizer_set_state(parser, GUMBO_LEX_DATA);
       return NEXT_CHAR;
+    // xml parsing rules do not allow single or double quotes in tag names
+    case '"':
+    case '\'':
+      tokenizer_add_parse_error(parser, GUMBO_ERR_TAG_INVALID);
+      append_char_to_tag_buffer(parser, '_', false);
+      return NEXT_CHAR;
     default:
       append_char_to_tag_buffer(parser, gumbo_tolower(c), true);
       return NEXT_CHAR;
diff -Nru sigil-0.9.12+dfsg/README.md sigil-0.9.13+dfsg/README.md
--- sigil-0.9.12+dfsg/README.md	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/README.md	2019-03-20 01:01:44.000000000 +0100
@@ -101,7 +101,7 @@
 * ZLib Data Compression Library (zlib 1.2.8)
 * jQuery-2.2.4 (src/Resource_Files/javascript/jquery-2.2.4.min.js)
 * jQuery.ScrollTo-2.1.2 (src/Resource_Files/javascript/jquery.scrollTo-2.1.2.min.js)
-* MathJax.js single file version: (src/Resource_Files/polyfills)
+* MathJax.js Version 2.75: (src/Resource_Files/polyfills)
 
 In addtion, Sigil uses the following other packages that have been specifically
 modified for use inside Sigil:
diff -Nru sigil-0.9.12+dfsg/src/CMakeLists.txt sigil-0.9.13+dfsg/src/CMakeLists.txt
--- sigil-0.9.12+dfsg/src/CMakeLists.txt	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/CMakeLists.txt	2019-03-20 01:01:44.000000000 +0100
@@ -585,7 +585,12 @@
 
 set( ALL_SOURCES ${RAW_SOURCES} ${UI_FILES_H} ${QRC_FILES_CPP} ${QM_FILES} )
 
+# Location of the MathJax zip archive for all platforms
+set( MATHJAX_ZIP "${CMAKE_SOURCE_DIR}/src/Resource_Files/polyfills/ML.zip" )
+
 # Adding resource (RC) files for Windows
+# Grab the current year so copyright notice is updated on Windows file properties
+string( TIMESTAMP SIGIL_BUILD_YEAR "%Y" )
 if ( WIN32 )
     configure_file( Resource_files/windows/version.rc.in ${PROJECT_BINARY_DIR}/version.rc )
     set( WINDOWS_RC_FILES
@@ -606,7 +611,7 @@
     if( CMAKE_GENERATOR STREQUAL Xcode )
         exec_program("mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/Resources")
         exec_program("mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/polyfills")
-        exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/polyfills/MathJax.js ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/polyfills")
+        exec_program("unzip ${MATHJAX_ZIP} -d ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/polyfills")
         exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/Sigil.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/Resources")
         exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/sgf.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/Resources")
         exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/epub.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/Sigil.app/Contents/Resources")
@@ -621,7 +626,7 @@
     else()
         exec_program("mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/Resources")
         exec_program("mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/polyfills")
-        exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/polyfills/MathJax.js ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/polyfills")
+        exec_program("unzip ${MATHJAX_ZIP} -d ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/polyfills")
         exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/Sigil.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/Resources")
         exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/sgf.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/Resources")
         exec_program("cp ${PROJECT_SOURCE_DIR}/Resource_Files/icon/epub.icns ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Sigil.app/Contents/Resources")
@@ -812,7 +817,7 @@
 
     # windeployqt
     add_custom_command( TARGET ${TARGET_FOR_COPY} POST_BUILD COMMAND
-	    windeployqt.exe --release --no-webkit2 --no-opengl-sw --no-translations --no-compiler-runtime --dir ${MAIN_PACKAGE_DIR} --libdir ${MAIN_PACKAGE_DIR} ${MAIN_PACKAGE_DIR}/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX} )
+	    windeployqt.exe --release --no-webkit2 --no-translations --no-compiler-runtime --dir ${MAIN_PACKAGE_DIR} --libdir ${MAIN_PACKAGE_DIR} ${MAIN_PACKAGE_DIR}/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX} )
 
     set( LIBXML2 ${QT_INSTALL_BINS}/libxml2.dll )
     if ( EXISTS ${LIBXML2} )
@@ -841,10 +846,10 @@
         endif()
     endforeach( QM )
 
-    # Copy the MathJax polyfill
-    set( MATHJAX_FILE ${CMAKE_SOURCE_DIR}/src/Resource_Files/polyfills/MathJax_win.js  )
-    add_custom_command( TARGET ${TARGET_FOR_COPY} PRE_BUILD COMMAND cmake -E make_directory ${MAIN_PACKAGE_DIR}/polyfills/ )
-    add_custom_command( TARGET ${TARGET_FOR_COPY} POST_BUILD COMMAND cmake -E copy ${MATHJAX_FILE} ${MAIN_PACKAGE_DIR}/polyfills/MathJax.js )
+    # Extract the MathJax polyfill archive into the package directory
+    set( MATHJAX_UNZIP_DEST ${MAIN_PACKAGE_DIR}/polyfills )
+    add_custom_command( TARGET ${TARGET_FOR_COPY} PRE_BUILD COMMAND cmake -E make_directory ${MATHJAX_UNZIP_DEST} )
+    add_custom_command( TARGET ${TARGET_FOR_COPY} POST_BUILD COMMAND cmake -E tar xzf ${MATHJAX_ZIP} WORKING_DIRECTORY ${MATHJAX_UNZIP_DEST} )
 
     # Copy the dictionary files
     add_custom_command( TARGET ${TARGET_FOR_COPY} PRE_BUILD COMMAND cmake -E make_directory ${MAIN_PACKAGE_DIR}/hunspell_dictionaries/ )
@@ -958,12 +963,25 @@
     set_property (
         SOURCE sigil_constants.cpp
         PROPERTY COMPILE_DEFINITIONS
-        SIGIL_SHARE_ROOT="${SIGIL_SHARE_ROOT}" DICTS_ARE_BUNDLED=${INSTALL_BUNDLED_DICTS} EXTRA_DICT_DIRS="${EXTRA_DICT_DIRS}"
+        SIGIL_SHARE_ROOT="${SIGIL_SHARE_ROOT}" DICTS_ARE_BUNDLED=${INSTALL_BUNDLED_DICTS}
+        EXTRA_DICT_DIRS="${EXTRA_DICT_DIRS}" MATHJAX_DIR="${MATHJAX_DIR}"
     )
 
     # Launch script for sigil
     set( LINUX_LAUNCH_INSTALL_SCRIPT_CONFIGURED ${CMAKE_BINARY_DIR}/sigil-sh_install_configured )
     set( SIGIL_EXECUTABLE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX} )
+    
+    # Destination directory for unzipped MathJax archive
+    set( MATHJAX_UNZIP_DEST "${CMAKE_BINARY_DIR}/polyfills" )
+    # Remove previous directories
+    if ( EXISTS ${MATHJAX_UNZIP_DEST} )
+        file( REMOVE_RECURSE ${MATHJAX_UNZIP_DEST} )
+    endif()
+    # Create the polyfills dir and extract the MathJax archive to it
+    if ( NOT DEFINED MATHJAX_DIR )
+        file( MAKE_DIRECTORY ${MATHJAX_UNZIP_DEST} )
+        execute_process( COMMAND cmake -E tar xvzf ${MATHJAX_ZIP} WORKING_DIRECTORY ${MATHJAX_UNZIP_DEST} )
+    endif()
 
     # Configure Linux launch script
     configure_file( ${LINUX_LAUNCH_INSTALL_SCRIPT} ${LINUX_LAUNCH_INSTALL_SCRIPT_CONFIGURED} )
@@ -997,7 +1015,11 @@
     if ( INSTALL_BUNDLED_DICTS )
         install( FILES ${DIC_FILES} DESTINATION ${SIGIL_SHARE_ROOT}/hunspell_dictionaries/ )
     endif()
-    install( FILES ${CMAKE_SOURCE_DIR}/src/Resource_Files/polyfills/MathJax.js DESTINATION ${SIGIL_SHARE_ROOT}/polyfills/ )
+    if ( MATHJAX_DIR )
+        install( FILES ${CMAKE_SOURCE_DIR}/src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js DESTINATION ${MATHJAX_DIR}/config/local/ )
+    else()
+        install( DIRECTORY ${MATHJAX_UNZIP_DEST}/MJ/ DESTINATION ${SIGIL_SHARE_ROOT}/polyfills/MJ )
+    endif()
     install( DIRECTORY ${CMAKE_SOURCE_DIR}/src/Resource_Files/plugin_launchers/python/ DESTINATION ${SIGIL_SHARE_ROOT}/plugin_launchers/python )
     install( DIRECTORY ${CMAKE_SOURCE_DIR}/src/Resource_Files/python3lib/ DESTINATION ${SIGIL_SHARE_ROOT}/python3lib )
     install( FILES ${EXAMPLE_FILES} DESTINATION ${SIGIL_SHARE_ROOT}/examples/ )
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ClipboardHistorySelector.cpp sigil-0.9.13+dfsg/src/Dialogs/ClipboardHistorySelector.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/ClipboardHistorySelector.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ClipboardHistorySelector.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -65,8 +65,7 @@
 
 void ClipboardHistorySelector::ApplicationActivated()
 {
-    // Turned on when Sigil is activated, put the latest text if any at the top of the history
-    ClipboardChanged();
+    // Turned on when Sigil is activated
     connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(ClipboardChanged()));
 
     // If we are currently showing this dialog, refresh the display
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ClipEditor.cpp sigil-0.9.13+dfsg/src/Dialogs/ClipEditor.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/ClipEditor.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ClipEditor.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2012 Grant Drake
@@ -95,6 +96,8 @@
 
 void ClipEditor::PasteIntoDocument()
 {
+    // GetSelectedEntries creates each clipEntry with new
+    // and so they will need to be deleted to prevent memory leaks
     emit PasteSelectedClipRequest(GetSelectedEntries());
 }
 
@@ -151,6 +154,10 @@
     return count;
 }
 
+
+// Note this routine invokes ClipEditorModel GetEntries or GetEntry
+// which creates the clipEntry structs using new so we will need
+// to clean up after we are done to prevent memory leaks
 QList<ClipEditorModel::clipEntry *> ClipEditor::GetSelectedEntries()
 {
     QList<ClipEditorModel::clipEntry *> selected_entries;
@@ -254,10 +261,15 @@
     }
 
     while (m_SavedClipEntries.count()) {
+        // these were previously generated with new
+        ClipEditorModel::clipEntry * p = m_SavedClipEntries.at(0);
+	delete p;
         m_SavedClipEntries.removeAt(0);
     }
 
+    // we will need to clean up the entries below to prevent memory leaks
     QList<ClipEditorModel::clipEntry *> entries = GetSelectedEntries();
+   
 
     if (!entries.count()) {
         return false;
@@ -268,16 +280,22 @@
 
         if (entry->is_group) {
             Utility::DisplayStdErrorDialog(tr("You cannot Copy or Cut groups - use drag-and-drop.")) ;
+	    delete entry;
             return false;
         }
+	delete entry;
     }
     foreach(ClipEditorModel::clipEntry * entry, entries) {
+        // need to clean up m_SavedClipEntries when done to prevent memory leak
         ClipEditorModel::clipEntry *save_entry = new ClipEditorModel::clipEntry();
         save_entry->name = entry->name;
         save_entry->is_group = entry->is_group;
         save_entry->text = entry->text;
         m_SavedClipEntries.append(save_entry);
     }
+    // to prevent memory leaks
+    qDeleteAll(entries);
+    entries.clear();
     return true;
 }
 
@@ -410,6 +428,7 @@
             parent_path = m_ClipEditorModel->GetFullName(item->parent());
         }
 
+	// Note GetEntry creates the clipEntry with new and it is just a struct
         foreach(QStandardItem * item, sub_items) {
             ClipEditorModel::clipEntry *entry = m_ClipEditorModel->GetEntry(item);
             // Remove the top level paths since we're exporting a subset
@@ -443,6 +462,9 @@
         m_LastFolderOpen = QFileInfo(filename).absolutePath();
         WriteSettings();
     }
+    // need to delete the entries to prevent a leak
+    qDeleteAll(entries);
+    entries.clear();
 }
 
 void ClipEditor::CollapseAll()
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/Reports.cpp sigil-0.9.13+dfsg/src/Dialogs/Reports.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/Reports.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/Reports.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019  Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2011  John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012  Dave Heiland
 **
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,6 +1,6 @@
 /************************************************************************
 **
-**  Copyright (C) 2017, 2018 Kevin B. Hendricks, Stratford, Ontario
+**  Copyright (C) 2017, 2018, 2019 Kevin B. Hendricks, Stratford, Ontario
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012, 2013 Dave Heiland
 **
@@ -52,6 +52,11 @@
     connectSignalsSlots();
 }
 
+AllFilesWidget::~AllFilesWidget()
+{
+  delete m_ItemModel;
+}
+
 void AllFilesWidget::CreateReport(QSharedPointer<Book> book)
 {
     m_Book = book;
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.h
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/AllFilesWidget.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **
@@ -47,6 +48,7 @@
 
 public:
     AllFilesWidget();
+    ~AllFilesWidget();
 
     void CreateReport(QSharedPointer<Book> book);
 
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **
@@ -54,6 +55,11 @@
     connectSignalsSlots();
 }
 
+CharactersInHTMLFilesWidget::~CharactersInHTMLFilesWidget()
+{
+    delete m_ItemModel;
+}
+
 void CharactersInHTMLFilesWidget::CreateReport(QSharedPointer<Book> book)
 {
     m_Book = book;
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.h
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CharactersInHTMLFilesWidget.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **
@@ -44,6 +45,7 @@
 
 public:
     CharactersInHTMLFilesWidget();
+    ~CharactersInHTMLFilesWidget();
 
     void CreateReport(QSharedPointer<Book> m_Book);
 
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **
@@ -51,6 +52,11 @@
     connectSignalsSlots();
 }
 
+ClassesInHTMLFilesWidget::~ClassesInHTMLFilesWidget()
+{
+    delete m_ItemModel;
+}
+
 void ClassesInHTMLFilesWidget::CreateReport(QSharedPointer<Book> book)
 {
     m_Book = book;
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.h
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ClassesInHTMLFilesWidget.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **
@@ -44,6 +45,7 @@
 
 public:
     ClassesInHTMLFilesWidget();
+    ~ClassesInHTMLFilesWidget();
 
     void CreateReport(QSharedPointer<Book> book);
 
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,6 +1,6 @@
 /************************************************************************
 **
-**  Copyright (C) 2018 Kevin B. Hendricks, Stratford, ON
+**  Copyright (C) 2018, 2019 Kevin B. Hendricks, Stratford, ON
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **
@@ -54,6 +54,11 @@
     connectSignalsSlots();
 }
 
+CSSFilesWidget::~CSSFilesWidget() {
+    delete m_ItemModel;
+}
+
+
 void CSSFilesWidget::CreateReport(QSharedPointer<Book> book)
 {
     m_Book = book;
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.h
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/CSSFilesWidget.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **
@@ -46,6 +47,7 @@
 
 public:
     CSSFilesWidget();
+    ~CSSFilesWidget();
 
     void CreateReport(QSharedPointer<Book> book);
 
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,6 +1,6 @@
 /************************************************************************
 **
-**  Copyright (C) 2018 Kevin B. Hendricks, Stratford, ON
+**  Copyright (C) 2018, 2019 Kevin B. Hendricks, Stratford, ON
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **
@@ -54,6 +54,11 @@
     connectSignalsSlots();
 }
 
+HTMLFilesWidget::~HTMLFilesWidget()
+{
+    delete m_ItemModel;
+}
+
 void HTMLFilesWidget::CreateReport(QSharedPointer<Book> book)
 {
     m_Book = book;
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.h
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/HTMLFilesWidget.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **
@@ -47,6 +48,7 @@
 
 public:
     HTMLFilesWidget();
+    ~HTMLFilesWidget();
 
     void CreateReport(QSharedPointer<Book> book);
 
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,6 +1,6 @@
 /************************************************************************
 **
-**  Copyright (C) 2018 Kevin Hendricks, Statford, ON 
+**  Copyright (C) 2018, 2019 Kevin Hendricks, Statford, ON 
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **
@@ -57,6 +57,11 @@
     ReadSettings();
 }
 
+ImageFilesWidget::~ImageFilesWidget()
+{
+    delete m_ItemModel;
+}
+
 void ImageFilesWidget::CreateReport(QSharedPointer<Book> book)
 {
     m_Book = book;
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.h
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/ImageFilesWidget.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **
@@ -46,6 +47,7 @@
 
 public:
     ImageFilesWidget();
+    ~ImageFilesWidget();
 
     void CreateReport(QSharedPointer<Book> book);
 
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2013 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2013 Dave Heiland
 **
@@ -50,6 +51,11 @@
     connectSignalsSlots();
 }
 
+LinksWidget::~LinksWidget()
+{
+    delete m_ItemModel;
+}
+
 void LinksWidget::CreateReport(QSharedPointer<Book> book)
 {
     m_Book = book;
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.h
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/LinksWidget.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2013 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2013 Dave Heiland
 **
@@ -47,6 +48,7 @@
 
 public:
     LinksWidget();
+    ~LinksWidget();
 
     void CreateReport(QSharedPointer<Book> book);
 
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.cpp sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **
@@ -52,6 +53,11 @@
     connectSignalsSlots();
 }
 
+StylesInCSSFilesWidget::~StylesInCSSFilesWidget()
+{
+    delete m_ItemModel;
+}
+
 void StylesInCSSFilesWidget::CreateReport(QSharedPointer<Book> book)
 {
     m_Book = book;
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.h sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.h
--- sigil-0.9.12+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/ReportsWidgets/StylesInCSSFilesWidget.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **
@@ -47,6 +48,7 @@
 
 public:
     StylesInCSSFilesWidget();
+    ~StylesInCSSFilesWidget();
 
     void CreateReport(QSharedPointer<Book> book);
 
diff -Nru sigil-0.9.12+dfsg/src/Dialogs/SearchEditor.cpp sigil-0.9.13+dfsg/src/Dialogs/SearchEditor.cpp
--- sigil-0.9.12+dfsg/src/Dialogs/SearchEditor.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Dialogs/SearchEditor.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2012 Grant Drake
@@ -94,31 +95,37 @@
 
 void SearchEditor::LoadFindReplace()
 {
+    // destination needs to delete each searchEntry when done
     emit LoadSelectedSearchRequest(GetSelectedEntry(false));
 }
 
 void SearchEditor::Find()
 {
+    // destination needs to delete each searchEntry when done
     emit FindSelectedSearchRequest(GetSelectedEntries());
 }
 
 void SearchEditor::ReplaceCurrent()
 {
+    // destination needs to delete each searchEntry when done
     emit ReplaceCurrentSelectedSearchRequest(GetSelectedEntries());
 }
 
 void SearchEditor::Replace()
 {
+    // destination needs to delete each searchEntry when done
     emit ReplaceSelectedSearchRequest(GetSelectedEntries());
 }
 
 void SearchEditor::CountAll()
 {
+    // destination needs to delete each searchEntry when done
     emit CountAllSelectedSearchRequest(GetSelectedEntries());
 }
 
 void SearchEditor::ReplaceAll()
 {
+    // destination needs to delete each searchEntry when done
     emit ReplaceAllSelectedSearchRequest(GetSelectedEntries());
 }
 
@@ -183,6 +190,10 @@
 
 SearchEditorModel::searchEntry *SearchEditor::GetSelectedEntry(bool show_warning)
 {
+    // Note: a SeachEditorModel::searchEntry is a simple struct that is created
+    // by new in SearchEditorModel GetEntry() and GetEntries()
+    // These must be manually deleted when done to prevent memory leaks
+
     SearchEditorModel::searchEntry *entry = NULL;
 
     if (ui.SearchEditorTree->selectionModel()->hasSelection()) {
@@ -210,6 +221,10 @@
 
 QList<SearchEditorModel::searchEntry *> SearchEditor::GetSelectedEntries()
 {
+    // Note: a SeachEditorModel::searchEntry is a simple struct that is created 
+    // by new in SearchEditorModel GetEntry() and GetEntries()
+    // These must be manually deleted when done to prevent memory leaks
+
     QList<SearchEditorModel::searchEntry *> selected_entries;
 
     if (ui.SearchEditorTree->selectionModel()->hasSelection()) {
diff -Nru sigil-0.9.12+dfsg/src/main.cpp sigil-0.9.13+dfsg/src/main.cpp
--- sigil-0.9.12+dfsg/src/main.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/main.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2018, 2019  Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2009, 2010, 2011  Strahinja Markovic  <strahinja.markovic@gmail.com>
 **
 **  This file is part of Sigil.
@@ -32,6 +33,7 @@
 #include <QtWidgets/QMessageBox>
 #include <QXmlStreamReader>
 #include <QFileInfo>
+#include <QDebug>
 
 #include "Misc/PluginDB.h"
 #include "Misc/UILanguage.h"
@@ -65,14 +67,12 @@
 // on command line arguments
 static MainWindow *GetMainWindow(const QStringList &arguments)
 {
-    // We use the first argument
-    // as the file to load after starting
-    if (arguments.size() > 1 &&
-        Utility::IsFileReadable(arguments.at(1))) {
-        return new MainWindow(arguments.at(1));
-    } else {
-        return new MainWindow();
+    // We use the first argument as the file to load after starting
+    QString filepath;
+    if (arguments.size() > 1 && Utility::IsFileReadable(arguments.at(1))) {
+        filepath = arguments.at(1);
     }
+    return new MainWindow(filepath);
 }
 
 #ifdef Q_OS_MAC
@@ -226,33 +226,46 @@
 #ifndef QT_DEBUG
     qInstallMessageHandler(MessageHandler);
 #endif
+
+    // Set application information for easier use of QSettings classes
+    QCoreApplication::setOrganizationName("sigil-ebook");
+    QCoreApplication::setOrganizationDomain("sigil-ebook.com");
+    QCoreApplication::setApplicationName("sigil");
+    QCoreApplication::setApplicationVersion(SIGIL_VERSION);
+    
+    // many qtbugs related to mixing 32 and 64 bit qt apps when shader disk cache is used
+    QCoreApplication::setAttribute(Qt::AA_DisableShaderDiskCache);
+
+ 
+#if 0   // On recent processors with multiple cores this leads to over 40 threads at times
+        // We prevent Qt from constantly creating and deleting threads.
+        // Using a negative number forces the threads to stay around;
+        // that way, we always have a steady number of threads ready to do work.
+        QThreadPool::globalInstance()->setExpiryTimeout(-1);
+#endif
+
     MainApplication app(argc, argv);
 
+    // drag and drop in main tab bar is too touchy and that can cause problems.
+    // default drag distance limit is much too small especially for hpi displays
+    // startDragDistance default is just 10 pixels
+    if (app.startDragDistance() < 50) app.setStartDragDistance(50);
+
     // Set up embedded python integration first thing
     EmbeddedPython* epython = EmbeddedPython::instance();
     epython->addToPythonSysPath(epython->embeddedRoot());
     epython->addToPythonSysPath(PluginDB::launcherRoot() + "/python");
 
     try {
-        // We prevent Qt from constantly creating and deleting threads.
-        // Using a negative number forces the threads to stay around;
-        // that way, we always have a steady number of threads ready to do work.
-        QThreadPool::globalInstance()->setExpiryTimeout(-1);
+
         // Specify the plugin folders
         // (language codecs and image loaders)
         app.addLibraryPath("codecs");
         app.addLibraryPath("iconengines");
         app.addLibraryPath("imageformats");
-        // Set application information for
-        // easier use of QSettings classes
-        QCoreApplication::setOrganizationName("sigil-ebook");
-        QCoreApplication::setOrganizationDomain("sigil-ebook.com");
-        QCoreApplication::setApplicationName("sigil");
-        QCoreApplication::setApplicationVersion(SIGIL_VERSION);
 
         QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf8"));
         SettingsStore settings;
-
         // Setup the qtbase_ translator and load the translation for the selected language
         QTranslator qtbaseTranslator;
         const QString qm_name_qtbase = QString("qtbase_%1").arg(settings.uiLanguage());
@@ -321,26 +334,51 @@
         } else {
             // Normal startup
 #ifdef Q_OS_MAC
+            // Work around QTBUG-62193 and QTBUG-65245 and others where menubar
+	    // menu items are lost under File and Sigil menus and where
+	    // Quit menu gets lost when deleting other windows first
+
+	    // Now we Create and show a frameless translucent QMainWindow to hold
+	    // the menubar.  Note: macOS has a single menubar attached at 
+	    // the top of the screen that all mainwindows share.
+
             app.setQuitOnLastWindowClosed(false);
 
+	    Qt::WindowFlags flags = Qt::Window | Qt::FramelessWindowHint;
+	    QMainWindow * basemw = new QMainWindow(NULL, flags);
+	    basemw->setAttribute(Qt::WA_TranslucentBackground, true);
+
             QMenuBar *mac_menu = new QMenuBar(0);
             QMenu *file_menu = new QMenu("File");
-            QAction *action;
-            // New
-            action = file_menu->addAction("New");
-            action->setShortcut(QKeySequence("Ctrl+N"));
-            QObject::connect(action, &QAction::triggered, file_new);
+
+	    // New
+            QAction * new_action = new QAction("New");
+            new_action->setShortcut(QKeySequence("Ctrl+N"));
+            QObject::connect(new_action, &QAction::triggered, file_new);
+	    file_menu ->addAction(new_action);
+
             // Open
-            action = file_menu->addAction("Open");
-            action->setShortcut(QKeySequence("Ctrl+O"));
-            QObject::connect(action, &QAction::triggered, file_open);
-            // Quit
-            action = file_menu->addAction("Quit");
-            action->setShortcut(QKeySequence("Ctrl+Q"));
-            QObject::connect(action, &QAction::triggered, qApp->quit);
+	    QAction* open_action = new QAction("Open");
+            open_action->setShortcut(QKeySequence("Ctrl+O"));
+            QObject::connect(open_action, &QAction::triggered, file_open);
+	    file_menu ->addAction(open_action);
+
+            // Quit - force add of a secondary quit menu to the file menu
+	    QAction* quit_action = new QAction("Quit");
+            quit_action->setMenuRole(QAction::NoRole);
+            quit_action->setShortcut(QKeySequence("Ctrl+Q"));
+            QObject::connect(quit_action, &QAction::triggered, qApp->quit);
+	    file_menu ->addAction(quit_action);
 
             mac_menu->addMenu(file_menu);
-            mac_menu->show();
+            
+	    // Application specific quit menu
+	    // according to Qt docs this is the right way to add an application
+	    // quit menu - but it does not work and will still sometimes get lost
+	    mac_menu->addAction("quit");
+
+	    basemw->setMenuBar(mac_menu);
+            basemw->show();
 #endif
             VerifyPlugins();
             MainWindow *widget = GetMainWindow(arguments);
diff -Nru sigil-0.9.12+dfsg/src/MainUI/FindReplace.cpp sigil-0.9.13+dfsg/src/MainUI/FindReplace.cpp
--- sigil-0.9.12+dfsg/src/MainUI/FindReplace.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/MainUI/FindReplace.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2011, 2012  John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012  Dave Heiland
 **  Copyright (C) 2009, 2010, 2011  Strahinja Markovic  <strahinja.markovic@gmail.com>
@@ -1170,6 +1171,10 @@
         message = QString("%1: %2 ").arg(tr("Loaded")).arg(search_entry->name.replace('<', "&lt;").replace('>', "&gt;").left(50));
     }
 
+    // prevent memory leak in FindSearch, ReplaceCurrentSearch, ReplaceSearch,
+    // CountAllSearch, and ReplaceAllSearch
+    delete search_entry;
+
     ShowMessage(message);
 }
 
diff -Nru sigil-0.9.12+dfsg/src/MainUI/FindReplace.h sigil-0.9.13+dfsg/src/MainUI/FindReplace.h
--- sigil-0.9.12+dfsg/src/MainUI/FindReplace.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/MainUI/FindReplace.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2011, 2012  John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2009, 2010, 2011  Strahinja Markovic  <strahinja.markovic@gmail.com>
diff -Nru sigil-0.9.12+dfsg/src/MainUI/MainWindow.cpp sigil-0.9.13+dfsg/src/MainUI/MainWindow.cpp
--- sigil-0.9.12+dfsg/src/MainUI/MainWindow.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/MainUI/MainWindow.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,6 +1,6 @@
 /************************************************************************
 **
-**  Copyright (C) 2016 Kevin B. Hendricks, Stratford, Ontario Canada
+**  Copyright (C) 2016, 2017, 2018, 2019 Kevin B. Hendricks, Stratford, Ontario Canada
 **  Copyright (C) 2012-2015 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012-2013 Dave Heiland
 **  Copyright (C) 2009-2011 Strahinja Markovic  <strahinja.markovic@gmail.com>
@@ -222,6 +222,31 @@
         m_ViewImage->close();
         m_ViewImage = NULL;
     }
+
+#ifdef Q_OS_MAC
+    if (m_ClipboardHistorySelector) delete m_ClipboardHistorySelector;
+    if (m_LinkOrStyleBookmark) delete m_LinkOrStyleBookmark;
+    if (m_Reports) delete m_Reports;
+    if (m_ViewImage) delete m_ViewImage;
+    if (m_SelectCharacter) delete m_SelectCharacter;
+    if (m_SpellcheckEditor) delete m_SpellcheckEditor;
+    if (m_IndexEditor) delete m_IndexEditor;
+    if (m_ClipEditor) delete m_ClipEditor;
+    if (m_SearchEditor) delete m_SearchEditor;
+    if (m_pluginMapper) delete m_pluginMapper;
+    if (m_casingChangeMapper) delete m_casingChangeMapper;
+    if (m_headingMapper) delete m_headingMapper;
+    if (m_lbZoomLabel) delete m_lbZoomLabel;
+    if (m_slZoomSlider) delete m_slZoomSlider;
+    if (m_ValidationResultsView) delete m_ValidationResultsView;
+    if (m_TableOfContents) delete m_TableOfContents;
+    if (m_FindReplace) delete m_FindReplace;
+    if (m_Clips) delete m_Clips;
+    if (m_BookBrowser) delete m_BookBrowser;
+    if (m_TabManager) delete m_TabManager;
+    if (m_PreviewWindow) delete m_PreviewWindow;
+#endif
+
 }
 
 
@@ -1084,15 +1109,15 @@
 
 void MainWindow::clearMemoryCaches()
 {
-    // See https://bugreports.qt-project.org/browse/QTBUG-4350
-    // QWebSettinbgs::clearMemoryCaches();
+    // See https://bugreports.qt-project.org/browse/QTBUG-43504
+    // QWebSettings::clearMemoryCaches();
 
     // replace the above with a similar sequence 
     // that does not invalidate the fontCache
 
     // toggle memory caches to disable and then re-enable
     QWebSettings::setObjectCacheCapacities(0,0,0);
-    QWebSettings::setObjectCacheCapacities(0, 0, 100 * 1024 * 1024);
+    QWebSettings::setObjectCacheCapacities(0, 8 * 1024 * 1024, 16 * 1024 * 1024);
 
     // do the same to flush the page cache
     int numpages = QWebSettings::maximumPagesInCache();
@@ -1228,7 +1253,7 @@
 
     m_BookBrowser->Refresh();
     m_Book->SetModified();
-    clearMemoryCaches();
+    MainWindow::clearMemoryCaches();
     OpenResourceAndWaitUntilLoaded(html_cover_resource);
     // Reload the tab to ensure it reflects updated image.
     FlowTab *flow_tab = GetCurrentFlowTab();
@@ -1749,7 +1774,7 @@
     QStringList filenames = m_BookBrowser->AddExisting(true);
     connect(m_BookBrowser, SIGNAL(ResourcesAdded()), this, SLOT(ResourcesAddedOrDeleted()));
     // Since we disconnected the signal we will have missed forced clearing of cache
-    clearMemoryCaches();
+    MainWindow::clearMemoryCaches();
     QStringList internal_filenames;
     foreach(QString filename, filenames) {
         QString internal_filename = filename.right(filename.length() - filename.lastIndexOf("/") - 1);
@@ -2042,10 +2067,17 @@
     PasteClipIntoCurrentTarget(20);
 }
 
+// How to deal with this as each clipEntry struct created with new and passed via
+// emit signal to here?  Where and show should their memory be freed.
+// Perhaps we need to make clipEntry a QObject instead of just a struct or use
+// smart pointers
 void MainWindow::PasteClipEntriesIntoCurrentTarget(const QList<ClipEditorModel::clipEntry *> &clips)
 {
     if (m_LastPasteTarget == NULL) {
         ShowMessageOnStatusBar(tr("Select the destination to paste into first."));
+	foreach(ClipEditorModel::clipEntry * entry, clips) {
+	    if (entry) delete entry;
+	}
         return;
     }
 
@@ -2055,6 +2087,11 @@
         // Clear the statusbar afterwards but only if entries were pasted.
         ShowMessageOnStatusBar();
     }
+
+    foreach(ClipEditorModel::clipEntry * entry, clips) {
+        if (entry) delete entry;
+    }
+
 }
 
 void MainWindow::PasteClipEntriesIntoPreviousTarget(const QList<ClipEditorModel::clipEntry *> &clips)
@@ -3317,6 +3354,8 @@
 
         html_resource = qobject_cast<HTMLResource *>(tab->GetLoadedResource());
 
+        // handle any memory cache clearing inside BookViewPreview
+
         // handles all cases of non-html resource in front tab
         if (!html_resource) {
             // note: must handle case of m_PreviousHTMLResource being deleted by user
@@ -3644,6 +3683,9 @@
     web_settings->setFontFamily(QWebSettings::StandardFont, bookViewAppearance.font_family_standard);
     web_settings->setFontFamily(QWebSettings::SerifFont, bookViewAppearance.font_family_serif);
     web_settings->setFontFamily(QWebSettings::SansSerifFont, bookViewAppearance.font_family_sans_serif);
+    web_settings->setObjectCacheCapacities(0, 8 * 1024 * 1024, 16 * 1024 * 1024);
+    web_settings->setMaximumPagesInCache(2);
+
     // Check for existing custom Preview/Book View stylesheet in Prefs dir and load it if present
     QFileInfo CustomPreviewStylesheetInfo(QDir(Utility::DefinePrefsDir()).filePath(CUSTOM_PREVIEW_STYLE_FILENAME));
     if (CustomPreviewStylesheetInfo.exists() && CustomPreviewStylesheetInfo.isFile() && CustomPreviewStylesheetInfo.isReadable()) {
@@ -3730,7 +3772,7 @@
 
 void MainWindow::ResourcesAddedOrDeleted()
 {
-    clearMemoryCaches();
+    MainWindow::clearMemoryCaches();
 
     // Make sure currently visible tab is updated immediately
     FlowTab *flow_tab = GetCurrentFlowTab();
@@ -4521,6 +4563,8 @@
 
 void MainWindow::UpdateClipButton(int clip_number, QAction *ui_action)
 {
+    // clipEntry is a simple struct created by GetEntry with new,
+    // no reference counting or smart pointers so they must be cleaned up appropriately
     ClipEditorModel::clipEntry *clip_entry = ClipEditorModel::instance()->GetEntryFromNumber(clip_number);
 
     if (clip_entry) {
@@ -4529,6 +4573,8 @@
         clip_text.replace('&', "&amp;").replace('<', "&lt;").replace('>', "&gt;");
         ui_action->setToolTip(clip_text);
         ui_action->setVisible(true);
+	// prevent memory leak
+	delete clip_entry;
     } else {
         ui_action->setText("");
         ui_action->setToolTip("");
diff -Nru sigil-0.9.12+dfsg/src/MainUI/MainWindow.h sigil-0.9.13+dfsg/src/MainUI/MainWindow.h
--- sigil-0.9.12+dfsg/src/MainUI/MainWindow.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/MainUI/MainWindow.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2016-2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012-2015 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2009-2011  Strahinja Markovic  <strahinja.markovic@gmail.com>
diff -Nru sigil-0.9.12+dfsg/src/MainUI/PreviewWindow.cpp sigil-0.9.13+dfsg/src/MainUI/PreviewWindow.cpp
--- sigil-0.9.12+dfsg/src/MainUI/PreviewWindow.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/MainUI/PreviewWindow.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin Hendricks, Doug Massay
 **  Copyright (C) 2012 Dave Heiland, John Schember
 **
 **  This file is part of Sigil.
@@ -206,24 +207,31 @@
         // On Mac OS X QCoreApplication::applicationDirPath() points to Sigil.app/Contents/MacOS/ 
         QDir execdir(QCoreApplication::applicationDirPath());
         execdir.cdUp();
-        mathjaxurl = execdir.absolutePath() + "/polyfills/MathJax.js";
+        mathjaxurl = execdir.absolutePath() + "/polyfills/MJ/MathJax.js";
 #elif defined(Q_OS_WIN32)
-        mathjaxurl = "/" + QCoreApplication::applicationDirPath() + "/polyfills/MathJax.js";
+        mathjaxurl = "/" + QCoreApplication::applicationDirPath() + "/polyfills/MJ/MathJax.js";
 #else
         // all flavours of linux / unix
-        // user supplied environment variable to 'share/sigil' directory will overrides everything
-        if (!sigil_extra_root.isEmpty()) {
-            mathjaxurl = sigil_extra_root + "/polyfills/MathJax.js";
+        // First check if system MathJax was configured to be used at compile time
+        if (!mathjax_dir.isEmpty()) {
+            mathjaxurl = mathjax_dir + "/MathJax.js";
         } else {
-            mathjaxurl = sigil_share_root + "/polyfills/MathJax.js";
+            // otherwise user supplied environment variable to 'share/sigil'
+            // takes precedence over Sigil's usual share location.
+            if (!sigil_extra_root.isEmpty()) {
+                mathjaxurl = sigil_extra_root + "/polyfills/MJ/MathJax.js";
+            } else {
+                mathjaxurl = sigil_share_root + "/polyfills/MJ/MathJax.js";
+            }
         }
 #endif
 
         mathjaxurl = "file://" + Utility::URLEncodePath(mathjaxurl);
+        mathjaxurl = mathjaxurl + "?config=local/SIGIL_EBOOK_MML_SVG";
         int endheadpos = text.indexOf("</head>");
         if (endheadpos > 1) {
             QString inject_mathjax = 
-              "<script type=\"text/javascript\" "
+              "<script type=\"text/javascript\" async=\"async\" "
               "src=\"" + mathjaxurl + "\"></script>";
             text.insert(endheadpos, inject_mathjax);
         }
diff -Nru sigil-0.9.12+dfsg/src/Misc/CSSInfo.cpp sigil-0.9.13+dfsg/src/Misc/CSSInfo.cpp
--- sigil-0.9.12+dfsg/src/Misc/CSSInfo.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Misc/CSSInfo.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,6 +1,6 @@
 /************************************************************************
 **
-**  Copyright (C) 2016 Kevin B. Hendricks, Stratford, ON Canada
+**  Copyright (C) 2016, 2017, 2018, 2019 Kevin B. Hendricks, Stratford, ON Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2012 Grant Drake
@@ -32,6 +32,11 @@
 const QString LINE_MARKER("[SIGIL_NEWLINE]");
 static const QString DELIMITERS = "}{;";
 
+
+// Note: CSSProperties and CSSSelectors are simple struct that this code
+// created with new and so need to be manually cleaned up to prevent
+// large memory leaks
+
 CSSInfo::CSSInfo(const QString &text, bool isCSSFile)
     : m_OriginalText(text),
       m_IsCSSFile(isCSSFile)
@@ -52,6 +57,15 @@
     }
 }
 
+// Need to manually clean up the Selector List
+CSSInfo::~CSSInfo()
+{
+  foreach(CSSSelector * sp, m_CSSSelectors) {
+      if (sp) delete sp;
+  } 
+}
+
+
 QList<CSSInfo::CSSSelector *> CSSInfo::getClassSelectors(const QString filterClassName)
 {
     QList<CSSInfo::CSSSelector *> selectors;
@@ -156,6 +170,7 @@
             if (property.isEmpty() || p->name == property) {
                 property_values.append(p->value);
             }
+	    delete p;
         }
     }
 
@@ -233,6 +248,10 @@
         QList<CSSInfo::CSSProperty *> new_properties = getCSSProperties(m_OriginalText, cssSelector->openingBracePos + 1, cssSelector->closingBracePos);
         const QString &new_properties_text = formatCSSProperties(new_properties, multipleLineFormat, selector_indent);
         new_text.replace(cssSelector->openingBracePos + 1, cssSelector->closingBracePos - cssSelector->openingBracePos - 1, new_properties_text);
+	// clear up new_properties as they were created with new
+	foreach(CSSInfo::CSSProperty* p, new_properties) {
+	    if (p) delete p;
+	}
         // Reformat the selector text itself - whitespace only since incomplete parsing.
         // Will ensure the braces are placed on the same line as the selector name,
         // comma separated groups are spaced apart and double spaces are removed.
@@ -444,7 +463,8 @@
 {
     QRegularExpression strip_attributes_regex("\\[[^\\]]*\\]");
     QRegularExpression strip_ids_regex("#[^\\s\\.]+");
-    QRegularExpression strip_non_name_chars_regex("[^A-Za-z0-9_\\-\\.:]+");
+    // QRegularExpression strip_non_name_chars_regex("[^A-Za-z0-9_\\-\\.:]+");
+    QRegularExpression strip_non_name_chars_regex("[^\\w_\\-\\.:]+", QRegularExpression::UseUnicodePropertiesOption);
     QString search_text = replaceBlockComments(text);
     // CSS selectors can be in a myriad of formats... the class based selectors could be:
     //    .c1 / e1.c1 / e1.c1.c2 / e1[class~=c1] / e1#id1.c1 / e1.c1#id1 / .c1, .c2 / ...
diff -Nru sigil-0.9.12+dfsg/src/Misc/CSSInfo.h sigil-0.9.13+dfsg/src/Misc/CSSInfo.h
--- sigil-0.9.12+dfsg/src/Misc/CSSInfo.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Misc/CSSInfo.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, ON, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2012 Grant Drake
@@ -41,6 +42,8 @@
      */
     CSSInfo(const QString &text, bool isCSSFile = true);
 
+    ~CSSInfo();
+
     struct CSSSelector {
         QString originalText;       /* The original text of the complete selector                  */
         bool isGroup;               /* Whether selector was declared in a comma separated group    */
diff -Nru sigil-0.9.12+dfsg/src/Misc/EmbeddedPythonPkg.cpp sigil-0.9.13+dfsg/src/Misc/EmbeddedPythonPkg.cpp
--- sigil-0.9.12+dfsg/src/Misc/EmbeddedPythonPkg.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Misc/EmbeddedPythonPkg.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,617 +0,0 @@
-/************************************************************************
-**
-**  Copyright (C) 2015  Kevin Hendricks
-**  Copyright (C) 2015  John Schember <john@nachtimwald.com>
-**
-**  This file is part of Sigil.
-**
-**  Sigil 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.
-**
-**  Sigil 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 Sigil.  If not, see <http://www.gnu.org/licenses/>.
-**
-*************************************************************************/
-
-#include "Misc/EmbeddedPython.h"
-#include <QString>
-#include <QByteArray>
-#include <QList>
-#include <QStringList>
-#include <QVariant>
-#include <QMetaType>
-#include <QStandardPaths>
-#include <QDir>
-#include "Misc/Utility.h"
-#include "sigil_constants.h"
-
-/**
- * Possibly Useful QMetaTypes::Type types
- *
- * QMetaType::Bool             1	bool
- * QMetaType::Int              2	int
- * QMetaType::UInt             3	unsigned int
- * QMetaType::Double           6	double
- * QMetaType::QChar            7	QChar
- * QMetaType::QString         10	QString
- * QMetaType::QByteArray      12	QByteArray
- * QMetaType::Long            32	long
- * QMetaType::LongLong         4	LongLong
- * QMetaType::Short           33	short
- * QMetaType::Char            34	char
- * QMetaType::ULong           35	unsigned long
- * QMetaType::ULongLong        5	ULongLong
- * QMetaType::UShort          36	unsigned short
- * QMetaType::SChar           40	signed char
- * QMetaType::UChar           37	unsigned char
- * QMetaType::Float           38	float
- * QMetaType::QVariant        41	QVariant
- * QMetaType::QVariantList     9	QVariantList
- * QMetaType::QStringList     11	QStringList
- * QMetaType::QVariantMap      8	QVariantMap
- * QMetaType::QVariantHash    28	QVariantHash
- * QMetaType::User           1024       Base value for User registered Type
- * QMetaType::UnknownType      0	This is an invalid type id. It is returned from QMetaType for types that are not registered
- */
-
-
-/**
- *  // example of how to run a python function inside a specific module
- *
- *  void EmbeddedPython::multiply_pushed(int val1, int val2)
- *  {
- *      int rv   = 0;
- *      QString error_traceback;
- *      QList<QVariant> args;
- *      args.append(QVariant(val1));
- *      args.append(QVariant(val2));
- *      QVariant res = runInPython(QString("multiply"),
- *                                 QString("multiply"),
- *                                 args,
- *                                 &rv,
- *                                 error_traceback);
- *      if (rv == 0) {
- *          // no errors
- *      } else {
- *         // error occured 
- *      }
- *  }
- *
- *  // Where multiply.py is:
- *
- *  #!/usr/bin/env python3
- *                                                                                                           
- *  def multiply(a,b):
- *      print("Will compute", a, "times", b)
- *      c  = a * b
- *      return c
- */
-
-/**
- * // example of how to use the callPyObjMethod
- *
- *  // First invoke module function to get the Python object
- *
- *  PyObjectPtr MyClass::get_object()
- *  {
- *      int rv = 0;
- *      QString traceback;
- *      QString v1 = QString("Hello");
- *      QList<QVariant> args;
- *      args.append(QVariant(v1));
- *  
- *      QVariant res = m_epp->runInPython( QString("multiply"),
- *                                         QString("get_object"),
- *                                         args,
- *                                         &rv,
- *                                         traceback,
- *                                         true);
- *      if (rv == 0) {
- *          return PyObjectPtr(res);
- *      } else {
- *          return PyObjectPtr();
- *      }
- *  }
- *
- * // Now invoke its "get_len" method
- *
- * QString MyClass:use_object(PyObjectPtr v)
- * {
- *     int rv = 0;
- *     QString traceback;
- *     QList<QVariant> args;
- *     QVariant res = m_epp->callPyObjMethod(v,
- *                                           QString("get_len"),
- *                                           args,
- *                                           &rv,
- *                                           traceback);
- *     if (rv == 0) {
- *         return res.toString();
- *     } else {
- *         return QString("Error: ") + QString::number(rv);
- *     }
- * }
- *
- *
- * # With the following python code inside of multiply.py
- *
- * class TestMe:
- *     def __init__(self, storeme):
- *         self.storeme = storeme
- *         self.mylen = len(self.storeme)
- * 
- *     def get_me(self):
- *         return self.storeme
- *
- *     def get_len(self):
- *         return self.mylen
- * 
- * def get_object(v1):
- *     tme = TestMe(v1)
- *     return tme
- */
-
-QMutex EmbeddedPython::m_mutex;
-
-EmbeddedPython* EmbeddedPython::m_instance = 0;
-int EmbeddedPython::m_pyobjmetaid = 0;
-PyThreadState * EmbeddedPython::m_threadstate = NULL;
-
-EmbeddedPython* EmbeddedPython::instance()
-{
-    if (m_instance == 0) {
-        m_instance = new EmbeddedPython();
-    }
-    return m_instance;
-}
-
-EmbeddedPython::EmbeddedPython()
-{
-    // Build string list of paths that will
-    // comprise the embedded Python's sys.path.
-#if defined(__APPLE__)
-    // On Mac OS X QCoreApplication::applicationDirPath() points to 
-    // whereever Sigil.app/Contents/MacOS/ is located
-    // but the python3 dir is in Contents
-    QDir execdir(QCoreApplication::applicationDirPath());
-    execdir.cdUp();
-    QString pyhomepath = execdir.absolutePath();
-#else
-    QString pyhomepath = QCoreApplication::applicationDirPath();
-#endif
-    wchar_t *hpath = new wchar_t[pyhomepath.size()+1];
-    pyhomepath.toWCharArray(hpath);
-    hpath[pyhomepath.size()]=L'\0';
-
-    QString pysyspath = pyhomepath + PYTHON_MAIN_PATH;
-    foreach (const QString &src_path, PYTHON_SYS_PATHS) {
-        pysyspath = pysyspath + PATH_LIST_DELIM + pyhomepath + PYTHON_MAIN_PATH + src_path;
-    }
-    wchar_t *mpath = new wchar_t[pysyspath.size()+1];
-    pysyspath.toWCharArray(mpath);
-    mpath[pysyspath.size()]=L'\0';
-    delete[] hpath;
-
-    Py_OptimizeFlag = 2;
-    Py_NoSiteFlag = 1;
-    Py_DontWriteBytecodeFlag = 1;
-    Py_IgnoreEnvironmentFlag = 1;
-    Py_NoUserSiteDirectory = 1;
-    /*Py_DebugFlag = 0;
-    Py_VerboseFlag = 0;
-    Py_SetProgramName(progname);
-    delete[] progname;
-    Py_SetPythonHome(hpath);
-    delete[] hpath;*/
-
-    // Set before Py_Initialize to ensure isolation from system python
-    Py_SetPath(mpath);
-    delete[] mpath;
-
-    Py_Initialize();
-    PyEval_InitThreads();
-    m_threadstate = PyEval_SaveThread();
-    m_pyobjmetaid = qMetaTypeId<PyObjectPtr>();
-}
-
-
-EmbeddedPython::~EmbeddedPython()
-{
-    if (m_instance) {
-        delete m_instance;
-        m_instance = 0;
-    }
-    m_pyobjmetaid = 0;
-    PyEval_RestoreThread(m_threadstate);
-    Py_Finalize();
-}
-
-QString EmbeddedPython::embeddedRoot()
-{
-    QString     embedded_root;
-    QStringList embedded_roots;
-    QDir        d;
-
-#ifdef Q_OS_MAC
-    embedded_roots.append(QCoreApplication::applicationDirPath() + "/../python3lib/");
-#elif defined(Q_OS_WIN32)
-    embedded_roots.append(QCoreApplication::applicationDirPath() + "/python3lib/");
-#elif !defined(Q_OS_WIN32) && !defined(Q_OS_MAC)
-    // all flavours of linux / unix
-    if (!sigil_extra_root.isEmpty()) {
-        embedded_roots.append(sigil_extra_root + "/python3lib/");
-    } else {
-        embedded_roots.append(sigil_share_root + "/python3lib/");
-    }
-#endif
-    
-    Q_FOREACH (QString s, embedded_roots) {
-        if (d.exists(s)) {
-            embedded_root = s;
-            break;
-        }
-    }
-
-    QDir base(embedded_root);
-    return base.absolutePath();
-}
-
-bool EmbeddedPython::addToPythonSysPath(const QString &mpath)
-{
-    EmbeddedPython::m_mutex.lock();
-    PyGILState_STATE gstate = PyGILState_Ensure();
-        
-    PyObject* sysPath    = NULL;
-    PyObject* aPath = NULL;
-    bool success = false;
-
-    // PySys_GetObject borrows a reference */
-    sysPath = PySys_GetObject((char*)"path");
-    if (sysPath != NULL) {
-        aPath = PyUnicode_FromString(mpath.toUtf8().constData());
-        if (aPath != NULL) {
-            PyList_Append(sysPath, aPath);
-            success = true;
-        }
-    }
-    Py_XDECREF(aPath);
-    PyGILState_Release(gstate);
-    EmbeddedPython::m_mutex.unlock();
-    return success;
-}
-
-// run interpreter without initiating/locking/unlocking GIL 
-// in a single thread at a time
-QVariant EmbeddedPython::runInPython(const QString &mname, 
-                                     const QString &fname, 
-                                     const QVariantList &args, 
-                                     int *rv, 
-                                     QString &tb,
-                                     bool ret_python_object)
-{
-    EmbeddedPython::m_mutex.lock();
-    PyGILState_STATE gstate = PyGILState_Ensure();
-        
-    QVariant  res        = QVariant(QString());
-    PyObject *moduleName = NULL;
-    PyObject *module     = NULL;
-    PyObject *func       = NULL;
-    PyObject *pyargs     = NULL;
-    PyObject *pyres      = NULL;
-    int       idx        = 0;
-
-    moduleName = PyUnicode_FromString(mname.toUtf8().constData());
-    if (moduleName == NULL) {
-        *rv = -1;
-        goto cleanup;
-    }
-
-    module = PyImport_Import(moduleName);
-    if (module == NULL) {
-        *rv = -2;
-        goto cleanup;
-    }
-
-    func = PyObject_GetAttrString(module,fname.toUtf8().constData());
-    if (func == NULL) {
-        *rv = -3;
-        goto cleanup;
-    }
-
-    if (!PyCallable_Check(func)) {
-        *rv = -4;
-        goto cleanup;
-    }
-
-    // Build up Python argument List from args
-    pyargs = PyTuple_New(args.size());
-    idx = 0;
-    foreach(QVariant arg, args) {
-        PyTuple_SetItem(pyargs, idx, QVariantToPyObject(arg));
-        idx++;
-    }
-
-    pyres = PyObject_CallObject(func, pyargs);
-    if (pyres == NULL) {
-        *rv = -5;
-        goto cleanup;
-    }
-
-    *rv = 0;
-
-    res = PyObjectToQVariant(pyres, ret_python_object);
-
-cleanup:
-    if (PyErr_Occurred() != NULL) {
-        tb = getPythonErrorTraceback();
-    }
-    Py_XDECREF(pyres);
-    Py_XDECREF(pyargs);
-    Py_XDECREF(func);
-    Py_XDECREF(module);
-    Py_XDECREF(moduleName);
-
-    PyGILState_Release(gstate);
-    EmbeddedPython::m_mutex.unlock();
-    return res;
-}
-
-
-// given an existing python object instance, invoke one of its methods 
-// grabs mutex to prevent need for Python GIL
-QVariant EmbeddedPython::callPyObjMethod(PyObjectPtr &pyobj, 
-                                         const QString &methname, 
-                                         const QVariantList &args, 
-                                         int *rv, 
-                                         QString &tb,
-                                         bool ret_python_object)
-{
-    EmbeddedPython::m_mutex.lock();
-    PyGILState_STATE gstate = PyGILState_Ensure();
-
-    QVariant  res        = QVariant(QString());
-    PyObject* obj        = pyobj.object();
-    PyObject* func       = NULL;
-    PyObject* pyargs     = NULL;
-    PyObject* pyres      = NULL;
-    int       idx        = 0;
-     
-    func = PyObject_GetAttrString(obj,methname.toUtf8().constData());
-    if (func == NULL) {
-         *rv = -1;
-         goto cleanup;
-    }
-
-    if (!PyCallable_Check(func)) {
-        *rv = -2;
-        goto cleanup;
-    }
-
-    // Build up Python argument List from args
-    pyargs = PyTuple_New(args.size());
-    idx = 0;
-    foreach(QVariant arg, args) {
-        PyTuple_SetItem(pyargs, idx, QVariantToPyObject(arg));
-        idx++;
-    }
-
-    pyres = PyObject_CallObject(func, pyargs);
-    if (pyres == NULL) {
-        *rv = -3;
-        goto cleanup;
-    }
-
-    *rv = 0;
-
-    res = PyObjectToQVariant(pyres, ret_python_object);
-
-    cleanup:
-    if (PyErr_Occurred() != NULL) {
-        tb = getPythonErrorTraceback();
-     }
-    Py_XDECREF(pyres);
-    Py_XDECREF(pyargs);
-    Py_XDECREF(func);
-
-    PyGILState_Release(gstate);
-    EmbeddedPython::m_mutex.unlock();
-    return res;
-}
-
-
-// *** below here all routines are private and only invoked 
-// *** from runInPython and callPyObjMethod with lock held
-
-
-// Convert PyObject types to their QVariant equivalents 
-// call recursively to allow populating QVariant lists and lists of lists
-QVariant EmbeddedPython::PyObjectToQVariant(PyObject *po, bool ret_python_object)
-{
-    QVariant res = QVariant(QString());
-
-    if ((po) == NULL)
-        return res;
-
-    if (PyLong_Check(po)) {
-        res = QVariant(PyLong_AsLongLong(po));
-
-    } else if (PyFloat_Check(po)) {
-        res = QVariant(PyFloat_AsDouble(po));
-
-    } else if (PyBytes_Check(po)) {
-        res = QVariant(QByteArray(PyBytes_AsString(po)));
-
-    } else if (PyUnicode_Check(po)) {
-
-        int kind = PyUnicode_KIND(po);
-
-        if (PyUnicode_READY(po) != 0)
-            return res;
-
-        if (kind == PyUnicode_1BYTE_KIND) {
-            // latin 1 according to PEP 393
-            res = QVariant(QString::fromLatin1(reinterpret_cast<const char *>PyUnicode_1BYTE_DATA(po), -1));
-
-        } else if (kind == PyUnicode_2BYTE_KIND) {
-            res = QVariant(QString::fromUtf16(PyUnicode_2BYTE_DATA(po), -1));
-
-        } else if (kind == PyUnicode_4BYTE_KIND) {
-            // PyUnicode_4BYTE_KIND
-            res = QVariant(QString::fromUcs4(PyUnicode_4BYTE_DATA(po), -1));
-
-        } else {
-            // convert to utf8 since not a known
-            res = QVariant(QString::fromUtf8(PyUnicode_AsUTF8(po),-1));
-        }
-
-    } else if (PyTuple_Check(po)) {
-        QVariantList vlist;
-        int n = PyTuple_Size(po);
-        for (int i=0; i< n; i++) {
-            vlist.append(PyObjectToQVariant(PyTuple_GetItem(po,i)));
-        }
-        res = QVariant(vlist);
-
-    } else if (PyList_Check(po)) {
-        QVariantList vlist;
-        int n = PyList_Size(po);
-        for (int i=0; i< n; i++) {
-            vlist.append(PyObjectToQVariant(PyList_GetItem(po,i)));
-        }
-        res = QVariant(vlist);
-
-    } else if (ret_python_object) {
-        QVariant var;
-        var.setValue(PyObjectPtr(po));
-        res = var;
-    } else { 
-       // do nothing here to return null value
-    }
-    return res;
-}
-
-// Convert QVariant to a Python Equivalent Type
-// call recursively to allow populating tuples/lists and lists of lists
-PyObject* EmbeddedPython::QVariantToPyObject(const QVariant &v)
-{
-    PyObject* value = NULL;
-    bool      ok;
-    switch ((QMetaType::Type)v.type()) {
-        case QMetaType::Double:
-            value = Py_BuildValue("d", v.toDouble(&ok));
-            break;
-        case QMetaType::Float:
-            value = Py_BuildValue("f", v.toFloat(&ok));
-            break;
-        case QMetaType::Int:
-            value = Py_BuildValue("i", v.toInt(&ok));
-            break;
-        case QMetaType::UInt:
-            value = Py_BuildValue("I", v.toUInt(&ok));
-            break;
-        case QMetaType::LongLong:
-            value = Py_BuildValue("L", v.toLongLong(&ok));
-            break;
-        case QMetaType::ULongLong:
-            value = Py_BuildValue("K", v.toULongLong(&ok));
-            break;
-        case QMetaType::QString:
-            value = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, v.toString().utf16(), v.toString().size());
-            // value = Py_BuildValue("s", v.toString().toUtf8().constData());
-            break;
-        case QMetaType::QByteArray:
-            value = Py_BuildValue("y", v.toByteArray().constData());
-            break;
-        case QMetaType::QStringList:
-            {
-              QStringList vlist = v.toStringList();
-              value = PyList_New(vlist.size());
-              int pos = 0;
-              foreach(QString av, vlist) {
-                  PyObject* strval = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, av.utf16(), av.size());
-                  PyList_SetItem(value, pos, strval);
-                  pos++;
-               }
-            }
-            break;
-         case QMetaType::QVariantList:
-            {
-              QVariantList vlist = v.toList();
-              value = PyList_New(vlist.size());
-              int pos = 0;
-              foreach(QVariant av, vlist) {
-                  PyList_SetItem(value, pos, QVariantToPyObject(av));
-                  pos++;
-              }
-            }
-            break;
-        default:
-          {
-            if ((QMetaType::Type)v.type() >= QMetaType::User && (v.userType() ==  m_pyobjmetaid))
-            {
-
-              PyObjectPtr op = v.value<PyObjectPtr>();
-              value = op.object();
-              // Need to increment object count otherwise will go away when Py_XDECREF used on pyargs
-              Py_XINCREF(value);
-
-            } else {
-
-              // Ensure we don't have any holes.
-              value = Py_BuildValue("u", "");
-            }
-          }
-          break;
-    }
-    return value;
-}
-
-
-// get traceback from inside interpreter upon error
-QString EmbeddedPython::getPythonErrorTraceback(bool useMsgBox)
-{
-    PyObject     *etype      = NULL;
-    PyObject     *evalue     = NULL;
-    PyObject     *etraceback = NULL;
-    PyObject     *mod        = NULL;
-    PyObject     *elist      = NULL;
-    QStringList  tblist;
-    
-    PyErr_Fetch(&etype, &evalue, &etraceback);
-    PyErr_NormalizeException(&etype, &evalue, &etraceback);
-
-    mod = PyImport_ImportModule("traceback");
-
-    if (mod) {
-        elist   = PyObject_CallMethod(mod, "format_exception", "OOO", etype, evalue, etraceback);
-        if (elist != NULL) {
-            tblist = PyObjectToQVariant(elist).toStringList();
-        } else {
-            tblist.append(QString("Error: traceback report is missing"));
-        }
-    } else {
-        tblist.append(QString("Error: traceback module failed to load"));
-    }
-
-    Py_XDECREF(elist);
-    Py_XDECREF(mod);
-    Py_XDECREF(etraceback);
-    Py_XDECREF(evalue);
-    Py_XDECREF(etype);
-
-    PyErr_Clear();
-
-    QString tb = tblist.join(QString("\n"));
-    if (useMsgBox) {
-        QString message = QString(tr("Embedded Python Error"));
-        Utility::DisplayStdErrorDialog(message, tb);
-    }
-    return tb;
-}
diff -Nru sigil-0.9.12+dfsg/src/Misc/FilenameDelegate.cpp sigil-0.9.13+dfsg/src/Misc/FilenameDelegate.cpp
--- sigil-0.9.12+dfsg/src/Misc/FilenameDelegate.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Misc/FilenameDelegate.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -20,7 +20,9 @@
 *************************************************************************/
 
 #include <QtCore/QEvent>
+#include <QKeyEvent>
 #include <QtWidgets/QLineEdit>
+#include <QApplication>
 
 #include "Misc/FilenameDelegate.h"
 
@@ -41,6 +43,17 @@
             }
 
             edit->setSelection(0, pos);
+
+	    // Due to bug introduced into Qt sometime after version 5.6
+	    // the cursor is made not visibile whenever a qlinedit
+	    // has a selection when first focused/selected.
+	    // No mouse click will cause the cursor to appear, only a key release event 
+	    // for some insane reason. So create a fake shift key press/release event that
+	    // will not change the cursor position but will make the cursor visible after a
+	    // mouse event deselects things.
+	    QApplication::postEvent(edit, new QKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier));
+	    QApplication::postEvent(edit, new QKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::NoModifier));
+	    QApplication::processEvents();			 
             event->accept();
             return true;
         }
diff -Nru sigil-0.9.12+dfsg/src/Misc/SettingsStore.cpp sigil-0.9.13+dfsg/src/Misc/SettingsStore.cpp
--- sigil-0.9.12+dfsg/src/Misc/SettingsStore.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Misc/SettingsStore.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,6 +1,6 @@
 /************************************************************************
 **
-**  Copyright (C) 2016, 2017, 2018  Kevin B. Hendricks, Stratford, ON
+**  Copyright (C) 2019 - 2016  Kevin B. Hendricks, Stratford, ON
 **  Copyright (C) 2011, 2012, 2013  John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012, 2013  Dave Heiland
 **
@@ -100,14 +100,16 @@
 
 SettingsStore::SettingsStore()
     : QSettings(Utility::DefinePrefsDir() + "/sigil.ini", QSettings::IniFormat)
-{
-     setIniCodec("UTF-8");
+{  
+    // See QTBUG-40796 and QTBUG-54510 as using UTF-8 as a codec for ini files is very broken
+    // setIniCodec("UTF-8");
 }
 
 SettingsStore::SettingsStore(QString filename)
     : QSettings(filename, QSettings::IniFormat)
 {
-     setIniCodec("UTF-8");
+    // See QTBUG-40796 and QTBUG-54510 as using UTF-8 as a codec for ini files is very broken
+    // setIniCodec("UTF-8");
 }
 
 QString SettingsStore::uiLanguage()
diff -Nru sigil-0.9.12+dfsg/src/MiscEditors/ClipEditorModel.cpp sigil-0.9.13+dfsg/src/MiscEditors/ClipEditorModel.cpp
--- sigil-0.9.12+dfsg/src/MiscEditors/ClipEditorModel.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/MiscEditors/ClipEditorModel.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,6 +1,6 @@
 /************************************************************************
 **
-**  Copyright (C) 2018 Kevin B. Hendricks, Stratford, Ontario
+**  Copyright (C) 2018, 2019 Kevin B. Hendricks, Stratford, Ontario
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2012 Grant Drake
@@ -263,6 +263,7 @@
     return item->data(FULLNAME_ROLE).toString();
 }
 
+// potential memory leak here too from GetEntry
 ClipEditorModel::clipEntry *ClipEditorModel::GetEntryFromNumber(int clip_number)
 {
     return GetEntry(GetItemFromNumber(clip_number));
@@ -345,32 +346,29 @@
 
 void ClipEditorModel::LoadData(const QString &filename, QStandardItem *item)
 {
-    SettingsStore *settings;
+    QString settings_path = filename;
+    if (settings_path.isEmpty()) settings_path = m_SettingsPath;
 
-    if (filename.isEmpty()) {
-        settings = new SettingsStore(m_SettingsPath);
-    } else {
-        settings = new SettingsStore(filename);
-    }
+    SettingsStore ss(settings_path);
 
-    int size = settings->beginReadArray(SETTINGS_GROUP);
+    int size = ss.beginReadArray(SETTINGS_GROUP);
 
     // Add one entry at a time to the list
     for (int i = 0; i < size; ++i) {
-        settings->setArrayIndex(i);
+        ss.setArrayIndex(i);
         ClipEditorModel::clipEntry *entry = new ClipEditorModel::clipEntry();
-        QString fullname = settings->value(ENTRY_NAME).toString();
+        QString fullname = ss.value(ENTRY_NAME).toString();
         fullname.replace(QRegularExpression("\\s*/+\\s*"), "/");
         fullname.replace(QRegularExpression("^/"), "");
         entry->is_group = fullname.endsWith("/");
         // Name is set to fullname only while looping through parent groups when adding
         entry->name = fullname;
         entry->fullname = fullname;
-        entry->text = settings->value(ENTRY_TEXT).toString();
+        entry->text = ss.value(ENTRY_TEXT).toString();
         AddFullNameEntry(entry, item);
+	delete entry;
     }
-
-    settings->endArray();
+    ss.endArray();
 }
 
 void ClipEditorModel::AddFullNameEntry(ClipEditorModel::clipEntry *entry, QStandardItem *parent_item, int row)
@@ -414,6 +412,8 @@
                 new_entry->is_group = true;
                 new_entry->name = group_name;
                 parent_item = AddEntryToModel(new_entry, new_entry->is_group, parent_item, parent_item->rowCount());
+		// fix memory leak
+		delete new_entry;
             }
         }
         row = parent_item->rowCount();
@@ -652,56 +652,71 @@
 QString ClipEditorModel::SaveData(QList<ClipEditorModel::clipEntry *> entries, const QString &filename)
 {
     QString message = "";
+    bool clean_up_needed = false;
+    QString settings_path = filename;
+    if (settings_path.isEmpty()) settings_path = m_SettingsPath;
 
     // Save everything if no entries selected
     if (entries.isEmpty()) {
         QList<QStandardItem *> items = GetNonParentItems(invisibleRootItem());
 
         if (!items.isEmpty()) {
+  	    // GetEntries calls GetEntry which creates each entry with new
             entries = GetEntries(items);
+	    clean_up_needed = true;
         }
     }
 
     // Stop watching the file while we save it
-    if (m_FSWatcher->files().contains(m_SettingsPath)) {
-        m_FSWatcher->removePath(m_SettingsPath);
+    if (m_FSWatcher->files().contains(settings_path)) {
+        m_FSWatcher->removePath(settings_path);
     }
 
     // Open the default file for save, or specific file for export
-    SettingsStore *settings;
+    {
+        SettingsStore ss(settings_path);
 
-    if (filename.isEmpty()) {
-        settings = new SettingsStore(m_SettingsPath);
-    } else {
-        settings = new SettingsStore(filename);
-    }
+        if (!ss.isWritable()) {
+            message = tr("Unable to create file %1").arg(filename);
+            // Watch the file again
+            m_FSWatcher->addPath(settings_path);
+
+            // delete each entry if we created them above 
+            if (clean_up_needed) {
+	        foreach(ClipEditorModel::clipEntry* entry, entries) {
+	            delete entry;
+	        }
+            }
+            return message;
+        }
 
-    settings->sync();
+        // Remove the old values to account for deletions
+        ss.remove(SETTINGS_GROUP);
+        ss.beginWriteArray(SETTINGS_GROUP);
+        int i = 0;
+        foreach(ClipEditorModel::clipEntry * entry, entries) {
+            ss.setArrayIndex(i++);
+            ss.setValue(ENTRY_NAME, entry->fullname);
 
-    if (!settings->isWritable()) {
-        message = tr("Unable to create file %1").arg(filename);
-        // Watch the file again
-        m_FSWatcher->addPath(m_SettingsPath);
-        return message;
+            if (!entry->is_group) {
+                ss.setValue(ENTRY_TEXT, entry->text);
+            }
+        }
+        // delete each entry if we created them above
+        if (clean_up_needed) {
+            foreach(ClipEditorModel::clipEntry* entry, entries) {
+	        delete entry;
+            }
+        }
+        ss.endArray();
+
+        // Make sure file is created/updated so it can be checked
+        ss.sync();
     }
 
-    // Remove the old values to account for deletions
-    settings->remove(SETTINGS_GROUP);
-    settings->beginWriteArray(SETTINGS_GROUP);
-    int i = 0;
-    foreach(ClipEditorModel::clipEntry * entry, entries) {
-        settings->setArrayIndex(i++);
-        settings->setValue(ENTRY_NAME, entry->fullname);
 
-        if (!entry->is_group) {
-            settings->setValue(ENTRY_TEXT, entry->text);
-        }
-    }
-    settings->endArray();
-    // Make sure file is created/updated so it can be checked
-    settings->sync();
     // Watch the file again
-    m_FSWatcher->addPath(m_SettingsPath);
+    m_FSWatcher->addPath(settings_path);
     SetDataModified(false);
     return message;
 }
diff -Nru sigil-0.9.12+dfsg/src/MiscEditors/ClipEditorModel.h sigil-0.9.13+dfsg/src/MiscEditors/ClipEditorModel.h
--- sigil-0.9.12+dfsg/src/MiscEditors/ClipEditorModel.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/MiscEditors/ClipEditorModel.h	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2012 Grant Drake
diff -Nru sigil-0.9.12+dfsg/src/MiscEditors/IndexEditorModel.cpp sigil-0.9.13+dfsg/src/MiscEditors/IndexEditorModel.cpp
--- sigil-0.9.12+dfsg/src/MiscEditors/IndexEditorModel.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/MiscEditors/IndexEditorModel.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **
@@ -189,34 +190,33 @@
                 entry->pattern = line;
             }
             AddFullNameEntry(entry, item);
+	    delete entry;
         }
         return;
     }
 
     // Read standard ini files
-    SettingsStore *settings;
+    QString settings_path = filename;
+    if (settings_path.isEmpty()) settings_path = m_SettingsPath;
 
-    if (filename.isEmpty()) {
-        settings = new SettingsStore(m_SettingsPath);
-    } else {
-        settings = new SettingsStore(filename);
-    }
+    SettingsStore ss(settings_path);
 
-    int size = settings->beginReadArray(SETTINGS_GROUP);
+    int size = ss.beginReadArray(SETTINGS_GROUP);
 
     // Add one entry at a time to the list
     for (int i = 0; i < size; ++i) {
-        settings->setArrayIndex(i);
+        ss.setArrayIndex(i);
         IndexEditorModel::indexEntry *entry = new IndexEditorModel::indexEntry();
-        entry->pattern = settings->value(ENTRY_PATTERN).toString();
-        entry->index_entry = settings->value(ENTRY_INDEX_ENTRY).toString();
+        entry->pattern = ss.value(ENTRY_PATTERN).toString();
+        entry->index_entry = ss.value(ENTRY_INDEX_ENTRY).toString();
 
         if (!entry->pattern.isEmpty() || !entry->index_entry.isEmpty()) {
             AddFullNameEntry(entry, item);
         }
+	delete entry;
     }
 
-    settings->endArray();
+    ss.endArray();
 }
 
 QStandardItem *IndexEditorModel::AddFullNameEntry(IndexEditorModel::indexEntry *entry, QStandardItem *parent_item, int row)
@@ -239,6 +239,8 @@
 
 QStandardItem *IndexEditorModel::AddEntryToModel(IndexEditorModel::indexEntry *entry, QStandardItem *parent_item, int row)
 {
+    bool clean_up = false;
+
     // parent_item must be a group item
     if (!parent_item) {
         parent_item = invisibleRootItem();
@@ -249,6 +251,7 @@
         entry = new IndexEditorModel::indexEntry();
         entry->pattern = "";
         entry->index_entry = "";
+	clean_up = true;
     }
 
     QList<QStandardItem *> rowItems;
@@ -266,6 +269,8 @@
     }
 
     SetDataModified(true);
+    if (clean_up) delete entry;
+
     return new_item;
 }
 
@@ -312,59 +317,75 @@
 QString IndexEditorModel::SaveData(QList<IndexEditorModel::indexEntry *> entries, const QString &filename)
 {
     QString message = "";
+    bool clean_up_needed = false;
+    QString settings_path = filename;
+    if (settings_path.isEmpty()) settings_path = m_SettingsPath;
 
     // Save everything if no entries selected
     if (entries.isEmpty()) {
         QList<QStandardItem *> items = GetItems();
 
         if (!items.isEmpty()) {
+            // GetEntries calls GetEntry which creates each entry with new
             entries = GetEntries(items);
+	    clean_up_needed = true;
         }
     }
 
     // Stop watching the file while we save it
-    if (m_FSWatcher->files().contains(m_SettingsPath)) {
-        m_FSWatcher->removePath(m_SettingsPath);
+    if (m_FSWatcher->files().contains(settings_path)) {
+        m_FSWatcher->removePath(settings_path);
     }
 
     // Open the default file for save, or specific file for export
-    SettingsStore *settings;
+    {  
+        SettingsStore ss(settings_path);
 
-    if (filename.isEmpty()) {
-        settings = new SettingsStore(m_SettingsPath);
-    } else {
-        settings = new SettingsStore(filename);
-    }
+        // ss.sync();
 
-    settings->sync();
+        if (!ss.isWritable()) {
+            message = tr("Unable to create file %1").arg(filename);
+            // Watch the file again
+            m_FSWatcher->addPath(settings_path);
+
+            // delete each entry if we created them above 
+            if (clean_up_needed) {
+	        foreach(IndexEditorModel::indexEntry* entry, entries) {
+	            delete entry;
+	        }
+            }
+            return message;
+        }
 
-    if (!settings->isWritable()) {
-        message = tr("Unable to create file %1").arg(filename);
-        // Watch the file again
-        m_FSWatcher->addPath(m_SettingsPath);
-        return message;
-    }
+        // Remove the old values to account for deletions
+        ss.remove(SETTINGS_GROUP);
+        ss.beginWriteArray(SETTINGS_GROUP);
+        int i = 0;
+        foreach(IndexEditorModel::indexEntry * entry, entries) {
+            if (entry->pattern.isEmpty() && entry->index_entry.isEmpty()) {
+                continue;
+            }
 
-    // Remove the old values to account for deletions
-    settings->remove(SETTINGS_GROUP);
-    settings->beginWriteArray(SETTINGS_GROUP);
-    int i = 0;
-    foreach(IndexEditorModel::indexEntry * entry, entries) {
-        if (entry->pattern.isEmpty() && entry->index_entry.isEmpty()) {
-            continue;
+            foreach(QString pattern, entry->pattern.split("\n")) {
+                ss.setArrayIndex(i++);
+                ss.setValue(ENTRY_PATTERN, pattern);
+                ss.setValue(ENTRY_INDEX_ENTRY, entry->index_entry);
+            }
         }
 
-        foreach(QString pattern, entry->pattern.split("\n")) {
-            settings->setArrayIndex(i++);
-            settings->setValue(ENTRY_PATTERN, pattern);
-            settings->setValue(ENTRY_INDEX_ENTRY, entry->index_entry);
+        // delete each entry if we created them above 
+        if (clean_up_needed) {
+	    foreach(IndexEditorModel::indexEntry* entry, entries) {
+	        delete entry;
+	    }
         }
+        ss.endArray();
+        // Make sure file is created/updated so it can be checked
+        ss.sync();
     }
-    settings->endArray();
-    // Make sure file is created/updated so it can be checked
-    settings->sync();
+
     // Watch the file again
-    m_FSWatcher->addPath(m_SettingsPath);
+    m_FSWatcher->addPath(settings_path);
     SetDataModified(false);
     return message;
 }
diff -Nru sigil-0.9.12+dfsg/src/MiscEditors/SearchEditorModel.cpp sigil-0.9.13+dfsg/src/MiscEditors/SearchEditorModel.cpp
--- sigil-0.9.12+dfsg/src/MiscEditors/SearchEditorModel.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/MiscEditors/SearchEditorModel.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,6 +1,6 @@
 /************************************************************************
 **
-**  Copyright (C) 2018 Kevin B. Hendricks, Stratford, Ontario, Canada
+**  Copyright (C) 2018, 2019 Kevin B. Hendricks, Stratford, Ontario, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012 Dave Heiland
 **  Copyright (C) 2012 Grant Drake
@@ -293,33 +293,31 @@
 
 void SearchEditorModel::LoadData(const QString &filename, QStandardItem *item)
 {
-    SettingsStore *settings;
+    QString settings_path = filename;
+    if (settings_path.isEmpty()) settings_path = m_SettingsPath;
 
-    if (filename.isEmpty()) {
-        settings = new SettingsStore(m_SettingsPath);
-    } else {
-        settings = new SettingsStore(filename);
-    }
+    SettingsStore ss(settings_path);
 
-    int size = settings->beginReadArray(SETTINGS_GROUP);
+    int size = ss.beginReadArray(SETTINGS_GROUP);
 
     // Add one entry at a time to the list
     for (int i = 0; i < size; ++i) {
-        settings->setArrayIndex(i);
+        ss.setArrayIndex(i);
         SearchEditorModel::searchEntry *entry = new SearchEditorModel::searchEntry();
-        QString fullname = settings->value(ENTRY_NAME).toString();
+        QString fullname = ss.value(ENTRY_NAME).toString();
         fullname.replace(QRegularExpression("\\s*/+\\s*"), "/");
         fullname.replace(QRegularExpression("^/"), "");
         entry->is_group = fullname.endsWith("/");
         // Name is set to fullname only while looping through parent groups when adding
         entry->name = fullname;
         entry->fullname = fullname;
-        entry->find = settings->value(ENTRY_FIND).toString();
-        entry->replace = settings->value(ENTRY_REPLACE).toString();
+        entry->find = ss.value(ENTRY_FIND).toString();
+        entry->replace = ss.value(ENTRY_REPLACE).toString();
         AddFullNameEntry(entry, item);
+	// done with the temporary entry so remove it
+	delete entry;
     }
-
-    settings->endArray();
+    ss.endArray();
 }
 
 void SearchEditorModel::AddFullNameEntry(SearchEditorModel::searchEntry *entry, QStandardItem *parent_item, int row)
@@ -363,6 +361,7 @@
                 new_entry->is_group = true;
                 new_entry->name = group_name;
                 parent_item = AddEntryToModel(new_entry, new_entry->is_group, parent_item, parent_item->rowCount());
+		delete new_entry;
             }
         }
         row = parent_item->rowCount();
@@ -575,57 +574,74 @@
 QString SearchEditorModel::SaveData(QList<SearchEditorModel::searchEntry *> entries, const QString &filename)
 {
     QString message = "";
+    bool clean_up_needed = false;
+    QString settings_path = filename;
+    if (settings_path.isEmpty()) settings_path = m_SettingsPath;
 
     // Save everything if no entries selected
     if (entries.isEmpty()) {
         QList<QStandardItem *> items = GetNonParentItems(invisibleRootItem());
 
         if (!items.isEmpty()) {
+	    // GetEntries calls GetEntry which creates each entry with new
             entries = GetEntries(items);
+	    clean_up_needed = true;
         }
     }
 
     // Stop watching the file while we save it
-    if (m_FSWatcher->files().contains(m_SettingsPath)) {
-        m_FSWatcher->removePath(m_SettingsPath);
+    if (m_FSWatcher->files().contains(settings_path)) {
+        m_FSWatcher->removePath(settings_path);
     }
 
     // Open the default file for save, or specific file for export
-    SettingsStore *settings;
+    {
+        SettingsStore ss(settings_path);
 
-    if (filename.isEmpty()) {
-        settings = new SettingsStore(m_SettingsPath);
-    } else {
-        settings = new SettingsStore(filename);
-    }
-
-    settings->sync();
+        // ss.sync();
 
-    if (!settings->isWritable()) {
-        message = tr("Unable to create file %1").arg(filename);
-        // Watch the file again
-        m_FSWatcher->addPath(m_SettingsPath);
-        return message;
-    }
+        if (!ss.isWritable()) {
+            message = tr("Unable to create file %1").arg(filename);
+            // Watch the file again
+            m_FSWatcher->addPath(settings_path);
+	    // delete each entry if we created them above   
+	    if (clean_up_needed) {
+	        foreach(SearchEditorModel::searchEntry* entry, entries) {
+	            delete entry;
+	        }
+	    }
+            return message;
+        }
+
+        // Remove the old values to account for deletions
+        ss.remove(SETTINGS_GROUP);
+        ss.beginWriteArray(SETTINGS_GROUP);
+        int i = 0;
+        foreach(SearchEditorModel::searchEntry * entry, entries) {
+            ss.setArrayIndex(i++);
+            ss.setValue(ENTRY_NAME, entry->fullname);
+
+            if (!entry->is_group) {
+                ss.setValue(ENTRY_FIND, entry->find);
+                ss.setValue(ENTRY_REPLACE, entry->replace);
+            }
+        }
+    
+        // delete each entry if we created them above
+        if (clean_up_needed) {
+	    foreach(SearchEditorModel::searchEntry* entry, entries) {
+	        delete entry;
+	    }
+        }
 
-    // Remove the old values to account for deletions
-    settings->remove(SETTINGS_GROUP);
-    settings->beginWriteArray(SETTINGS_GROUP);
-    int i = 0;
-    foreach(SearchEditorModel::searchEntry * entry, entries) {
-        settings->setArrayIndex(i++);
-        settings->setValue(ENTRY_NAME, entry->fullname);
+        ss.endArray();
 
-        if (!entry->is_group) {
-            settings->setValue(ENTRY_FIND, entry->find);
-            settings->setValue(ENTRY_REPLACE, entry->replace);
-        }
+        // Make sure file is created/updated so it can be checked
+        ss.sync();
     }
-    settings->endArray();
-    // Make sure file is created/updated so it can be checked
-    settings->sync();
+
     // Watch the file again
-    m_FSWatcher->addPath(m_SettingsPath);
+    m_FSWatcher->addPath(settings_path);
     SetDataModified(false);
     return message;
 }
diff -Nru sigil-0.9.12+dfsg/src/Resource_Files/plugin_launchers/python/wrapper.py sigil-0.9.13+dfsg/src/Resource_Files/plugin_launchers/python/wrapper.py
--- sigil-0.9.12+dfsg/src/Resource_Files/plugin_launchers/python/wrapper.py	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Resource_Files/plugin_launchers/python/wrapper.py	2019-03-20 01:01:44.000000000 +0100
@@ -35,7 +35,7 @@
 from unipath import pathof
 import unicodedata
 
-_launcher_version=20190218
+_launcher_version=20190309
 
 _PKG_VER = re.compile(r'''<\s*package[^>]*version\s*=\s*["']([^'"]*)['"][^>]*>''',re.IGNORECASE)
 
diff -Nru sigil-0.9.12+dfsg/src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js sigil-0.9.13+dfsg/src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js
--- sigil-0.9.12+dfsg/src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js	1970-01-01 01:00:00.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Resource_Files/polyfills/SIGIL_EBOOK_MML_SVG.js	2019-03-20 01:01:44.000000000 +0100
@@ -0,0 +1,23 @@
+/*************************************************************
+ *
+ *  Modified Version of MathJax/unpacked/config/MML_SVG.js
+ *  Specifically for Sigil-EBook's PreviewWindow
+ *
+ *  Copyright (c) 2010-2018 The MathJax Consortium
+ *
+ *  Part of the MathJax library.
+ *  See http://www.mathjax.org for details.
+ * 
+ *  Licensed under the Apache License, Version 2.0;
+ *  you may not use this file except in compliance with the License.
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+MathJax.Hub.Config({
+  extensions: ["mml2jax.js","MathML/mml3.js","MathEvents.js","fast-preview.js","AssistiveMML.js"],
+  jax: ["input/MathML","output/SVG","output/PreviewHTML"],
+  messageStyle: "none"
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/config/local/SIGIL_EBOOK_MML_SVG.js");
diff -Nru sigil-0.9.12+dfsg/src/Resource_Files/windows/version.rc.in sigil-0.9.13+dfsg/src/Resource_Files/windows/version.rc.in
--- sigil-0.9.12+dfsg/src/Resource_Files/windows/version.rc.in	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Resource_Files/windows/version.rc.in	2019-03-20 01:01:44.000000000 +0100
@@ -14,7 +14,7 @@
             VALUE "FileDescription",    "Sigil is a multi-platform EPUB ebook editor"
             VALUE "FileVersion",        "${SIGIL_FULL_VERSION}.0"
             VALUE "InternalName",       "Sigil"
-            VALUE "LegalCopyright",     "Copyright (c) 2010-2014 Sigil Authors"
+            VALUE "LegalCopyright",     "Copyright (c) 2010-${SIGIL_BUILD_YEAR} Sigil Authors"
             VALUE "LegalTrademarks1",   "All Rights Reserved"
             VALUE "LegalTrademarks2",   "All Rights Reserved"
             VALUE "OriginalFilename",   "Sigil.exe"
diff -Nru sigil-0.9.12+dfsg/src/sigil_constants.cpp sigil-0.9.13+dfsg/src/sigil_constants.cpp
--- sigil-0.9.12+dfsg/src/sigil_constants.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/sigil_constants.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -33,6 +33,7 @@
 const QString sigil_share_root = QString(SIGIL_SHARE_ROOT);
 const bool dicts_are_bundled = DICTS_ARE_BUNDLED;
 const QString extra_dict_dirs = QString(EXTRA_DICT_DIRS);
+const QString mathjax_dir = QString(MATHJAX_DIR);
 const QString PYTHON_MAIN_PATH = "/python3/lib/python3.5";
 #if __x86_64__ || __ppc64__
 const QStringList PYTHON_SYS_PATHS = QStringList () << "/plat-x86_64-linux-gnu" << "/plat-linux" << "/lib-dynload" << "/site-packages";
diff -Nru sigil-0.9.12+dfsg/src/sigil_constants.h sigil-0.9.13+dfsg/src/sigil_constants.h
--- sigil-0.9.12+dfsg/src/sigil_constants.h	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/sigil_constants.h	2019-03-20 01:01:44.000000000 +0100
@@ -131,6 +131,7 @@
 extern const QString sigil_share_root;
 extern const bool dicts_are_bundled;
 extern const QString extra_dict_dirs;
+extern const QString mathjax_dir;
 #endif
 
 #endif // SG_CONSTANTS_H
diff -Nru sigil-0.9.12+dfsg/src/SourceUpdates/PerformCSSUpdates.cpp sigil-0.9.13+dfsg/src/SourceUpdates/PerformCSSUpdates.cpp
--- sigil-0.9.12+dfsg/src/SourceUpdates/PerformCSSUpdates.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/SourceUpdates/PerformCSSUpdates.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -50,7 +50,7 @@
 
     // Now parse the text once looking for keys and replacing them where needed
     QRegularExpression reference(
-        "(?:(?:src|background|background-image|list-style|list-style-image|border-image|border-image-source|content)\\s*:|@import)\\s*"
+        "(?:(?:src|background|background-image|list-style|list-style-image|border-image|border-image-source|content|(?:-webkit-)?shape-outside)\\s*:|@import)\\s*"
         "("
         "[^;\\}]*"
         ")"
diff -Nru sigil-0.9.12+dfsg/src/Tabs/TabManager.cpp sigil-0.9.13+dfsg/src/Tabs/TabManager.cpp
--- sigil-0.9.12+dfsg/src/Tabs/TabManager.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/Tabs/TabManager.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -53,8 +53,18 @@
     connect(this, SIGNAL(currentChanged(int)),         this, SLOT(EmitTabChanged()));
     connect(this, SIGNAL(tabCloseRequested(int)),      this, SLOT(CloseTab(int)));
     setDocumentMode(true);
-    setMovable(true);
+    // QTabBar has a bug when a user "presses and flicks" on a non current tab it will cause it 
+    // to setCurrentIndex() but during EmitTabChanged() it then may allows the resulting mouseMoveEvent
+    // be processed on the same index that is being set in setCurrentIndex which causes a crash.
+    // This bug makes it dangerous to enable dragging and dropping to move tabs in the QTabBar
+    // So default to non-movable but let a environment variable override this decision
+    if (qEnvironmentVariableIsSet("SIGIL_ALLOW_TAB_MOVEMENT")) {
+        setMovable(true);
+    } else {
+        setMovable(false);
+    }
     setTabsClosable(true);
+    // setElideMode(Qt::ElideRight); this is the default after qt-5.6
     setUsesScrollButtons(true);
 }
 
@@ -536,14 +546,29 @@
     if (new_tab == NULL) {
         return false;
     }
-
+    int idx = -1;
     if (!precede_current_tab) {
-        addTab(new_tab, new_tab->GetIcon(), new_tab->GetFilename());
+
+#ifdef Q_OS_MAC
+        // drop use of icons to workaround Qt Bugs: QTBUG-61235, QTBUG-61742, QTBUG-63445, QTBUG-64630
+        idx = addTab(new_tab, new_tab->GetFilename());
+#else
+        idx = addTab(new_tab, new_tab->GetIcon(), new_tab->GetFilename());
+#endif
+
         setCurrentWidget(new_tab);
         new_tab->setFocus();
     } else {
-        insertTab(currentIndex(), new_tab, new_tab->GetIcon(), new_tab->GetFilename());
+
+#ifdef Q_OS_MAC
+        // drop use of icons to workaround Qt Bugs: QTBUG-61235, QTBUG-61742, QTBUG-63445, QTBUG-64630
+        idx = insertTab(currentIndex(), new_tab, new_tab->GetFilename());
+#else
+        idx = insertTab(currentIndex(), new_tab, new_tab->GetIcon(), new_tab->GetFilename());
+#endif
+
     }
+    setTabToolTip(idx, new_tab->GetFilename());
 
     connect(new_tab, SIGNAL(DeleteMe(ContentTab *)), this, SLOT(DeleteTab(ContentTab *)));
     connect(new_tab, SIGNAL(TabRenamed(ContentTab *)), this, SLOT(UpdateTabName(ContentTab *)));
diff -Nru sigil-0.9.12+dfsg/src/ViewEditors/BookViewPreview.cpp sigil-0.9.13+dfsg/src/ViewEditors/BookViewPreview.cpp
--- sigil-0.9.12+dfsg/src/ViewEditors/BookViewPreview.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/ViewEditors/BookViewPreview.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,6 +1,6 @@
 /************************************************************************
 **
-**  Copyright (C) 2015 Kevin B. Hendricks Stratford, ON, Canada
+**  Copyright (C) 2019, 2018, 2017, 2016, 2015 Kevin B. Hendricks Stratford, ON, Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **
 **  This file is part of Sigil.
@@ -73,7 +73,7 @@
     // Enable our link filter.
     page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
     page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
-    page()->settings()->setAttribute(QWebSettings::PluginsEnabled, true);
+    // page()->settings()->setAttribute(QWebSettings::PluginsEnabled, false);
     // Allow epubs to access remote resources via the net
     page()->settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, (settings.remoteOn() == 1));
     // Enable local-storage for epub3
@@ -152,6 +152,19 @@
     // If this is not the very first load of this document, store the caret location
     if (!url().isEmpty()) {
         StoreCurrentCaretLocation();
+        // to help keep memory footprint small clear any memory caches when a new page loads
+ 	if (url().path() != path) {
+	    settings()->clearMemoryCaches();
+#if 0
+	    // An attempt to flush caches but not the font caches
+	    // These need to be kept in sync with MainWindow::clearMemoryCaches()
+	    // settings()->setObjectCacheCapacities(0,0,0);
+	    // settings()->setObjectCacheCapacities(0, 8 * 1024 * 1024, 16 * 1024 * 1024);
+            // int n = settings()->maximumPagesInCache();
+	    // settings()->setMaximumPagesInCache(0);
+	    // settings()->setMaximumPagesInCache(n);
+#endif
+	} 
     }
 
     m_isLoadFinished = false;
diff -Nru sigil-0.9.12+dfsg/src/ViewEditors/CodeViewEditor.cpp sigil-0.9.13+dfsg/src/ViewEditors/CodeViewEditor.cpp
--- sigil-0.9.12+dfsg/src/ViewEditors/CodeViewEditor.cpp	2019-02-18 22:53:28.000000000 +0100
+++ sigil-0.9.13+dfsg/src/ViewEditors/CodeViewEditor.cpp	2019-03-20 01:01:44.000000000 +0100
@@ -1,5 +1,6 @@
 /************************************************************************
 **
+**  Copyright (C) 2019 Doug Massay
 **  Copyright (C) 2015 Kevin B. Hendricks Stratford, ON Canada
 **  Copyright (C) 2012 John Schember <john@nachtimwald.com>
 **  Copyright (C) 2012, 2013 Dave Heiland
@@ -2103,6 +2104,11 @@
 {
     if (m_DelayedCursorScreenCenteringRequired) {
         centerCursor();
+#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC)
+        // The Code View viewport stopped updating on Linux somewhere
+        // around Qt5.12.0 in this delayed call to center the cursor.
+        viewport()->update();
+#endif
         m_DelayedCursorScreenCenteringRequired = false;
     }
 }
@@ -3193,6 +3199,9 @@
                 } else {
                     property_values.append(QString("%1: %2").arg(css_property->name).arg(css_property->value));
                 }
+		// CSSInfo.getCSSProperties creates each CSSProperty pointer with new
+		// and it must be cleaned by caller to prevent memory leak
+		if (css_property) delete css_property;
             }
             style_attribute_value = QString("%1;").arg(property_values.join("; "));
         }

Attachment: signature.asc
Description: PGP signature


Reply to: