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

Bug#925219: marked as done (unblock: sigil/0.9.13-1)



Your message dated Tue, 02 Apr 2019 18:12:00 +0000
with message-id <e4de057a-9400-4e95-102c-7dff2611d16d@thykier.net>
and subject line Re: Bug#925219: unblock: sigil/0.9.13-1
has caused the Debian Bug report #925219,
regarding unblock: sigil/0.9.13-1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
925219: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=925219
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
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


--- End Message ---
--- Begin Message ---
Mattia Rizzolo:
> 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.
> 

Unblocked, thanks.
~Niels

--- End Message ---

Reply to: