From 9571be670d548df1bc1b64c87b56553bc1114b23 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 25 Sep 2023 05:43:26 +0700 Subject: [PATCH 1/5] feat(windows): create Keyman for Windows installer without buildpkg --- docs/build/windows.md | 6 +++--- windows/src/desktop/inst/Makefile | 14 ++++++++++++-- windows/src/desktop/inst/download.in | 12 ++++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/docs/build/windows.md b/docs/build/windows.md index 9faebc3d632..81a96a4a209 100644 --- a/docs/build/windows.md +++ b/docs/build/windows.md @@ -101,7 +101,7 @@ Building: * Ant * Gradle * Maven -* OpenJDK 11 +* Optional: OpenJDK 11 (https://learn.microsoft.com/en-us/java/openjdk/download) ```ps1 # Elevated PowerShell @@ -254,8 +254,8 @@ choco install openjdk choco install visualstudio2019community visualstudio2019-workload-nativedesktop visualstudio2019buildtools ``` * Verify required build tools are installed - * Run `Visual Studio Installer` - * Check the `Individual components` tab + * Run `Visual Studio Installer` + * Check the `Individual components` tab * Verify `MSVC v142 - VS 2019 c++ x64/x86 build tools (Latest)` is installed. If not, install it. Recommended: configure Visual Studio to use two-space tab stops: diff --git a/windows/src/desktop/inst/Makefile b/windows/src/desktop/inst/Makefile index c247da987b6..68bb12a7352 100644 --- a/windows/src/desktop/inst/Makefile +++ b/windows/src/desktop/inst/Makefile @@ -28,11 +28,19 @@ prereq-resources: $(SIGNCODE) /d "Keyman Resources" desktop_resources.dll desktop: prereq + rem compile .msi $(MAKE) -fdownload.mak candle $(WIXLIGHT) -dWixUILicenseRtf=License.rtf -out keymandesktop.msi -ext WixUIExtension $(DESKTOP_FILES) $(SIGNCODE) /d "Keyman" keymandesktop.msi -# TODO: replace buildpkg with kmc? Or promote it to developer? - $(ROOT)\bin\buildtools\buildpkg -m keymandesktop.msi -s $(ROOT)\bin\desktop -l license.html + + rem build self-extracting archive + $(MAKE) -fdownload.mak setup-inf + $(WZZIP) keymandesktop.zip keymandesktop.msi license.html setup.inf + -del setup.inf + $(COPY) /b $(ROOT)\bin\desktop\setup-redist.exe + keymandesktop.zip keymandesktop.exe + -del keymandesktop.zip + + rem sign and copy files $(SIGNCODE) /d "Keyman" keymandesktop.exe $(MAKE) -fdownload.mak copyredist-desktop @@ -51,6 +59,8 @@ clean: -del /Q desktopui.wxs -del /Q cef.wxs -del /Q locale.wxs + -del keymandesktop.zip + -del setup.inf check: if not exist $(ROOT)\src\engine\inst\keymanengine.msm $(MAKE) check-engine diff --git a/windows/src/desktop/inst/download.in b/windows/src/desktop/inst/download.in index 0bf062eeba4..3fc996840d4 100644 --- a/windows/src/desktop/inst/download.in +++ b/windows/src/desktop/inst/download.in @@ -63,3 +63,15 @@ candle-locale: # locale files are in desktop/locale/* $(WIXHEAT) dir ..\kmshell\locale -o locale.wxs -ag -cg Locale -dr INSTALLDIR -var var.LOCALESOURCE -wx -nologo $(WIXCANDLE) -dVERSION=$VersionWin -dRELEASE=$VersionRelease -dPRODUCTID=$GUID1 -dLOCALESOURCE=..\kmshell\locale locale.wxs + +# +# Build setup.inf +# + +setup-inf: + echo [Setup] > setup.inf + echo Version=$VersionWin >> setup.inf + echo MSIFileName=keymandesktop.msi >> setup.inf + echo MSIOptions= >> setup.inf + echo License=license.html >> setup.inf + echo [Packages] >> setup.inf From 10b2fa4fb598b7e12609f7bbe50d458faa699d72 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 25 Sep 2023 05:43:42 +0700 Subject: [PATCH 2/5] feat(windows): create FV installer without buildpkg --- oem/firstvoices/windows/src/inst/Makefile | 15 +++++++++++---- oem/firstvoices/windows/src/inst/download.in | 12 ++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/oem/firstvoices/windows/src/inst/Makefile b/oem/firstvoices/windows/src/inst/Makefile index 2f3be6990b9..488b837d255 100644 --- a/oem/firstvoices/windows/src/inst/Makefile +++ b/oem/firstvoices/windows/src/inst/Makefile @@ -8,9 +8,9 @@ DESKTOP_FILES=firstvoices.wixobj desktopui.wixobj MSI=firstvoices.msi +EXE_ZIP=firstvoices.zip EXE=firstvoices.exe KMP=fv_all.kmp -INTEXE=firstvoices-fv_all.exe APPTITLE="Keyman for FirstVoices" TITLEIMAGE=setuptitle.png @@ -48,12 +48,19 @@ prereq: cd $(FVROOT)\src\inst desktop: prereq + rem compile .msi $(MAKE) -fdownload.mak candle-desktop $(WIXLIGHT) -dWixUILicenseRtf=License.rtf -out $(MSI) -ext WixUIExtension $(DESKTOP_FILES) $(SIGNCODE) /d $(APPTITLE) $(MSI) - $(ROOT)\bin\buildtools\buildpkg -m $(MSI) -s $(ROOT)\bin\desktop -l license.html -a $(APPTITLE) -i $(TITLEIMAGE) -n "FirstVoices Keyboards" -startDisabled -startWithConfiguration $(KMP) - if exist $(EXE) del $(EXE) - ren $(INTEXE) $(EXE) + + rem build self-extracting archive + $(MAKE) -fdownload.mak setup-inf + $(WZZIP) $(EXE_ZIP) $(MSI) license.html setup.inf $(TITLEIMAGE) $(KMP) + -del setup.inf + $(COPY) /b $(ROOT)\bin\desktop\setup-redist.exe + $(EXE_ZIP) $(EXE) + -del $(EXE_ZIP) + + rem sign and copy files $(SIGNCODE) /d $(APPTITLE) $(EXE) $(MAKE) -fdownload.mak copyredist-desktop diff --git a/oem/firstvoices/windows/src/inst/download.in b/oem/firstvoices/windows/src/inst/download.in index f31c2fe3c40..98d23e1e286 100644 --- a/oem/firstvoices/windows/src/inst/download.in +++ b/oem/firstvoices/windows/src/inst/download.in @@ -22,3 +22,15 @@ candle-desktop: $(WIXHEAT) dir ..\xml -o desktopui.wxs -ag -cg DesktopUI -dr INSTALLDIR -suid -var var.DESKTOPUISOURCE -wx -nologo $(WIXCANDLE) -dOEMNAME="$(OEMNAME)" -dPRODUCTNAME="$(PRODUCTNAME)" -dROOT="$(ROOT)" -dVERSION=$VersionWin -dRELEASE=$VersionRelease -dPRODUCTID=$GUID1 -dDESKTOPUISOURCE=..\xml firstvoices.wxs desktopui.wxs +setup-inf: + echo [Setup] > setup.inf + echo Version=$VersionWin >> setup.inf + echo MSIFileName=firstvoices.msi >> setup.inf + echo MSIOptions= >> setup.inf + echo AppName=Keyman for FirstVoices >> setup.inf + echo License=license.html >> setup.inf + echo TitleImage=setuptitle.png >> setup.inf + echo StartDisabled=True >> setup.inf + echo StartWithConfiguration=True >> setup.inf + echo [Packages] >> setup.inf + echo fv_all.kmp=FirstVoices Keyboards >> setup.inf From 7dc8743cd3c8a837ce48c3be6459fa22bf2d494b Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 25 Sep 2023 06:00:39 +0700 Subject: [PATCH 3/5] chore(windows): remove buildpkg --- developer/src/README.md | 1 - windows/src/buildtools/Makefile | 9 +- windows/src/buildtools/buildpkg/Makefile | 20 - windows/src/buildtools/buildpkg/buildpkg.dpr | 74 -- .../src/buildtools/buildpkg/buildpkg.dproj | 1053 ----------------- windows/src/buildtools/buildpkg/buildpkg.res | Bin 57140 -> 0 bytes .../src/buildtools/buildpkg/buildpkgmain.pas | 214 ---- windows/src/buildtools/buildpkg/version.rc | 32 - 8 files changed, 2 insertions(+), 1401 deletions(-) delete mode 100644 windows/src/buildtools/buildpkg/Makefile delete mode 100644 windows/src/buildtools/buildpkg/buildpkg.dpr delete mode 100644 windows/src/buildtools/buildpkg/buildpkg.dproj delete mode 100644 windows/src/buildtools/buildpkg/buildpkg.res delete mode 100644 windows/src/buildtools/buildpkg/buildpkgmain.pas delete mode 100644 windows/src/buildtools/buildpkg/version.rc diff --git a/developer/src/README.md b/developer/src/README.md index 05afec59633..5d923dd4646 100644 --- a/developer/src/README.md +++ b/developer/src/README.md @@ -8,7 +8,6 @@ We do not have 100% clean separation between Keyman Developer and Keyman for Windows. Shared units are intended to live in common, however the following projects will need to be updated in the future. -* buildpkg in Windows depends on various compiler units in multiple folders. * kmbrowserhost in Windows is included as part of Keyman Developer. # Folders diff --git a/windows/src/buildtools/Makefile b/windows/src/buildtools/Makefile index d6621a889de..06053170500 100644 --- a/windows/src/buildtools/Makefile +++ b/windows/src/buildtools/Makefile @@ -7,7 +7,7 @@ NOTARGET_SIGNCODE=yes !ifdef NODELPHI TARGETS=.virtual !else -TARGETS=common buildpkg +TARGETS=common !endif CLEANS=clean-buildtools @@ -20,15 +20,10 @@ common: .virtual cd $(KEYMAN_ROOT)\common\windows\delphi\tools $(MAKE) $(TARGET) -buildpkg: .virtual - cd $(ROOT)\src\buildtools\buildpkg - $(MAKE) $(TARGET) - # ---------------------------------------------------------------------- clean-buildtools: - cd $(ROOT)\src\buildtools - -del version.txt + rem no action !include ..\Target.mak diff --git a/windows/src/buildtools/buildpkg/Makefile b/windows/src/buildtools/buildpkg/Makefile deleted file mode 100644 index 056011b0bdd..00000000000 --- a/windows/src/buildtools/buildpkg/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# -# Buildpkg Makefile -# - -!include ..\..\Defines.mak - -build: version.res dirs - $(DELPHI_MSBUILD) buildpkg.dproj "/p:Platform=Win32" - $(SENTRYTOOL_DELPHIPREP) $(WIN32_TARGET_PATH)\buildpkg.exe -dpr buildpkg.dpr - $(TDS2DBG) $(WIN32_TARGET_PATH)\buildpkg.exe - $(COPY) $(WIN32_TARGET_PATH)\Buildpkg.exe $(PROGRAM)\online - $(COPY) $(WIN32_TARGET_PATH)\Buildpkg.exe $(PROGRAM)\buildtools - if exist $(WIN32_TARGET_PATH)\buildpkg.dbg $(COPY) $(WIN32_TARGET_PATH)\buildpkg.dbg $(DEBUGPATH)\buildtools - -clean: def-clean - -signcode: - $(SIGNCODE) /d "Package Installer Creator for Server" $(PROGRAM)\online\Buildpkg.exe - -!include ..\..\Target.mak diff --git a/windows/src/buildtools/buildpkg/buildpkg.dpr b/windows/src/buildtools/buildpkg/buildpkg.dpr deleted file mode 100644 index d2c7d21cfa7..00000000000 --- a/windows/src/buildtools/buildpkg/buildpkg.dpr +++ /dev/null @@ -1,74 +0,0 @@ -program buildpkg; - -{$APPTYPE CONSOLE} - -uses - SysUtils, - buildpkgmain in 'buildpkgmain.pas', - CompilePackageInstaller in '..\..\..\..\developer\src\common\delphi\compiler\CompilePackageInstaller.pas', - utilsystem in '..\..\..\..\common\windows\delphi\general\utilsystem.pas', - CompilePackage in '..\..\..\..\developer\src\common\delphi\compiler\CompilePackage.pas', - kmpinffile in '..\..\..\..\common\windows\delphi\packages\kmpinffile.pas', - kpsfile in '..\..\..\..\developer\src\common\delphi\packages\kpsfile.pas', - PackageInfo in '..\..\..\..\common\windows\delphi\packages\PackageInfo.pas', - utildir in '..\..\..\..\common\windows\delphi\general\utildir.pas', - utilstr in '..\..\..\..\common\windows\delphi\general\utilstr.pas', - utilfiletypes in '..\..\..\..\common\windows\delphi\general\utilfiletypes.pas', - Unicode in '..\..\..\..\common\windows\delphi\general\Unicode.pas', - VersionInfo in '..\..\..\..\common\windows\delphi\general\VersionInfo.pas', - PackageFileFormats in '..\..\..\..\common\windows\delphi\packages\PackageFileFormats.pas', - GetOsVersion in '..\..\..\..\common\windows\delphi\general\GetOsVersion.pas', - RegistryKeys in '..\..\..\..\common\windows\delphi\general\RegistryKeys.pas', - KeymanDeveloperOptions in '..\..\..\..\developer\src\tike\main\KeymanDeveloperOptions.pas', - RedistFiles in '..\..\..\..\developer\src\tike\main\RedistFiles.pas', - DebugPaths in '..\..\..\..\common\windows\delphi\general\DebugPaths.pas', - CustomisationStorage in '..\..\global\delphi\cust\CustomisationStorage.pas', - StockFileNames in '..\..\..\..\common\windows\delphi\general\StockFileNames.pas', - klog in '..\..\..\..\common\windows\delphi\general\klog.pas', - httpuploader in '..\..\..\..\common\windows\delphi\general\httpuploader.pas', - Upload_Settings in '..\..\..\..\common\windows\delphi\general\Upload_Settings.pas', - UfrmTike in '..\..\..\..\developer\src\tike\main\UfrmTike.pas' {TikeForm: TTntForm}, - utilhttp in '..\..\..\..\common\windows\delphi\general\utilhttp.pas', - kmxfile in '..\..\..\..\common\windows\delphi\keyboards\kmxfile.pas', - utilkeyboard in '..\..\..\..\common\windows\delphi\keyboards\utilkeyboard.pas', - KeyNames in '..\..\..\..\common\windows\delphi\general\KeyNames.pas', - wininet5 in '..\..\..\..\common\windows\delphi\general\wininet5.pas', - GlobalProxySettings in '..\..\..\..\common\windows\delphi\general\GlobalProxySettings.pas', - ErrorControlledRegistry in '..\..\..\..\common\windows\delphi\vcl\ErrorControlledRegistry.pas', - utilexecute in '..\..\..\..\common\windows\delphi\general\utilexecute.pas', - KeymanVersion in '..\..\..\..\common\windows\delphi\general\KeymanVersion.pas', - Glossary in '..\..\..\..\common\windows\delphi\general\Glossary.pas', - Keyman.Developer.System.Project.ProjectLog in '..\..\..\..\developer\src\tike\project\Keyman.Developer.System.Project.ProjectLog.pas', - UserMessages in '..\..\..\..\common\windows\delphi\general\UserMessages.pas', - VisualKeyboard in '..\..\..\..\common\windows\delphi\visualkeyboard\VisualKeyboard.pas', - VisualKeyboardLoaderBinary in '..\..\..\..\common\windows\delphi\visualkeyboard\VisualKeyboardLoaderBinary.pas', - VisualKeyboardLoaderXML in '..\..\..\..\common\windows\delphi\visualkeyboard\VisualKeyboardLoaderXML.pas', - VisualKeyboardSaverBinary in '..\..\..\..\common\windows\delphi\visualkeyboard\VisualKeyboardSaverBinary.pas', - VisualKeyboardSaverXML in '..\..\..\..\common\windows\delphi\visualkeyboard\VisualKeyboardSaverXML.pas', - TempFileManager in '..\..\..\..\common\windows\delphi\general\TempFileManager.pas', - ExtShiftState in '..\..\..\..\common\windows\delphi\visualkeyboard\ExtShiftState.pas', - VKeyChars in '..\..\..\..\common\windows\delphi\general\VKeyChars.pas', - VKeys in '..\..\..\..\common\windows\delphi\general\VKeys.pas', - JsonUtil in '..\..\..\..\common\windows\delphi\general\JsonUtil.pas', - Keyman.System.PackageInfoRefreshKeyboards in '..\..\..\..\developer\src\common\delphi\packages\Keyman.System.PackageInfoRefreshKeyboards.pas', - Keyman.System.KMXFileLanguages in '..\..\..\..\developer\src\common\delphi\keyboards\Keyman.System.KMXFileLanguages.pas', - Keyman.System.Standards.ISO6393ToBCP47Registry in '..\..\..\..\common\windows\delphi\standards\Keyman.System.Standards.ISO6393ToBCP47Registry.pas', - Keyman.System.Standards.LCIDToBCP47Registry in '..\..\..\..\common\windows\delphi\standards\Keyman.System.Standards.LCIDToBCP47Registry.pas', - Keyman.System.KeyboardJSInfo in '..\..\..\..\developer\src\common\delphi\keyboards\Keyman.System.KeyboardJSInfo.pas', - Keyman.System.KeyboardUtils in '..\..\..\..\developer\src\common\delphi\keyboards\Keyman.System.KeyboardUtils.pas', - Keyman.System.LanguageCodeUtils in '..\..\..\..\common\windows\delphi\general\Keyman.System.LanguageCodeUtils.pas', - Keyman.System.RegExGroupHelperRSP19902 in '..\..\..\..\common\windows\delphi\vcl\Keyman.System.RegExGroupHelperRSP19902.pas', - kmxfileconsts in '..\..\..\..\common\windows\delphi\keyboards\kmxfileconsts.pas', - BCP47Tag in '..\..\..\..\common\windows\delphi\general\BCP47Tag.pas', - Keyman.System.Standards.BCP47SubtagRegistry in '..\..\..\..\common\windows\delphi\standards\Keyman.System.Standards.BCP47SubtagRegistry.pas', - Keyman.System.Standards.BCP47SuppressScriptRegistry in '..\..\..\..\common\windows\delphi\standards\Keyman.System.Standards.BCP47SuppressScriptRegistry.pas', - Keyman.System.CanonicalLanguageCodeUtils in '..\..\..\..\common\windows\delphi\general\Keyman.System.CanonicalLanguageCodeUtils.pas', - Keyman.System.LexicalModelUtils in '..\..\..\..\developer\src\common\delphi\lexicalmodels\Keyman.System.LexicalModelUtils.pas', - Keyman.System.PackageInfoRefreshLexicalModels in '..\..\..\..\developer\src\common\delphi\packages\Keyman.System.PackageInfoRefreshLexicalModels.pas', - Keyman.System.Standards.LangTagsRegistry in '..\..\..\..\common\windows\delphi\standards\Keyman.System.Standards.LangTagsRegistry.pas', - KeymanPaths in '..\..\..\..\common\windows\delphi\general\KeymanPaths.pas', - Keyman.Developer.System.KeymanDeveloperPaths in '..\..\..\..\developer\src\tike\main\Keyman.Developer.System.KeymanDeveloperPaths.pas'; - -begin - Run; -end. diff --git a/windows/src/buildtools/buildpkg/buildpkg.dproj b/windows/src/buildtools/buildpkg/buildpkg.dproj deleted file mode 100644 index 16dbddf62fb..00000000000 --- a/windows/src/buildtools/buildpkg/buildpkg.dproj +++ /dev/null @@ -1,1053 +0,0 @@ - - - {662A6FEA-4D2E-42E8-9292-1B3EE5A1E480} - buildpkg.dpr - True - Debug - 1 - Console - None - 18.8 - Win32 - - - true - - - true - Base - true - - - true - Base - true - - - true - Base - true - - - true - Cfg_2 - true - true - - - buildpkg - $(BDS)\bin\delphi_PROJECTICON.ico - $(BDS)\bin\delphi_PROJECTICNS.icns - true - true - $(DELPHI)\lib;$(DCC_UnitSearchPath) - false - 28 - true - 5 - System;Xml;Data;Datasnap;Web;Soap;Winapi;Vcl;System.Win;Vcl.Imaging;$(DCC_Namespace) - true - VISUALKEYBOARD_NOCUSTOMBITMAP;VERSION_KEYMAN_REDIST;RELEASE_KEYMAN;EXCMAGIC_GUI;$(DCC_Define) - 1 - 3 - false - false - 3081 - false - true - false - CompanyName=;FileDescription=Tavultesoft Keyboard Manager;FileVersion=5.0.0.28;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= - Vcl40;Vclx40;vcljpg40;comp51;VCLZipD4;dclkmn;Vcl50;Vclx50;vclie50;Inetdb50;Inet50;Vcldb50;$(DCC_UsePackage) - 2C400000 - false - true - None - true - .\obj\$(Platform)\$(Config) - .\bin\$(Platform)\$(Config) - - - Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) - CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) - 1033 - - - false - 0 - 0 - RELEASE;$(DCC_Define) - - - DEBUG;$(DCC_Define) - false - - - -m c:\temp\xx\keymandesktop90.msi -l c:\temp\xx\license.html -n "GFF Amharic" -s c:\temp\xx\ c:\temp\xx\gff-amh-powerpack-7.kmp - c:\temp\xx\ - CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) - 1033 - - - - MainSource - - - - - - - - - - - - - - - - - - - - - - - - - -
TikeForm
- TTntForm -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cfg_2 - Base - - - Base - - - Cfg_1 - Base - -
- - Delphi.Personality.12 - - - - - buildpkg.dpr - - - $00000C09 - - - False - True - 5 - 0 - 0 - 32 - False - False - False - False - False - 3081 - 1252 - - - - Tavultesoft Keyboard Manager - 5.0.0.32 - - - - - - 1.0.0.0 - - - - Microsoft Office 2000 Sample Automation Server Wrapper Components - Microsoft Office XP Sample Automation Server Wrapper Components - - - - True - False - - - - - true - - - - - true - - - - - true - - - - - true - - - - - true - - - - - buildpkg.exe - true - - - - - 1 - - - 0 - - - - - classes - 1 - - - classes - 1 - - - - - res\xml - 1 - - - res\xml - 1 - - - - - library\lib\armeabi-v7a - 1 - - - - - library\lib\armeabi - 1 - - - library\lib\armeabi - 1 - - - - - library\lib\armeabi-v7a - 1 - - - - - library\lib\mips - 1 - - - library\lib\mips - 1 - - - - - library\lib\armeabi-v7a - 1 - - - library\lib\arm64-v8a - 1 - - - - - library\lib\armeabi-v7a - 1 - - - - - res\drawable - 1 - - - res\drawable - 1 - - - - - res\values - 1 - - - res\values - 1 - - - - - res\values-v21 - 1 - - - res\values-v21 - 1 - - - - - res\values - 1 - - - res\values - 1 - - - - - res\drawable - 1 - - - res\drawable - 1 - - - - - res\drawable-xxhdpi - 1 - - - res\drawable-xxhdpi - 1 - - - - - res\drawable-ldpi - 1 - - - res\drawable-ldpi - 1 - - - - - res\drawable-mdpi - 1 - - - res\drawable-mdpi - 1 - - - - - res\drawable-hdpi - 1 - - - res\drawable-hdpi - 1 - - - - - res\drawable-xhdpi - 1 - - - res\drawable-xhdpi - 1 - - - - - res\drawable-mdpi - 1 - - - res\drawable-mdpi - 1 - - - - - res\drawable-hdpi - 1 - - - res\drawable-hdpi - 1 - - - - - res\drawable-xhdpi - 1 - - - res\drawable-xhdpi - 1 - - - - - res\drawable-xxhdpi - 1 - - - res\drawable-xxhdpi - 1 - - - - - res\drawable-xxxhdpi - 1 - - - res\drawable-xxxhdpi - 1 - - - - - res\drawable-small - 1 - - - res\drawable-small - 1 - - - - - res\drawable-normal - 1 - - - res\drawable-normal - 1 - - - - - res\drawable-large - 1 - - - res\drawable-large - 1 - - - - - res\drawable-xlarge - 1 - - - res\drawable-xlarge - 1 - - - - - res\values - 1 - - - res\values - 1 - - - - - 1 - - - 1 - - - 0 - - - - - 1 - .framework - - - 1 - .framework - - - 0 - - - - - 1 - .dylib - - - 1 - .dylib - - - 0 - .dll;.bpl - - - - - 1 - .dylib - - - 1 - .dylib - - - 1 - .dylib - - - 1 - .dylib - - - 1 - .dylib - - - 0 - .bpl - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - - - - - - 1 - - - 1 - - - 1 - - - - - - - - Contents\Resources - 1 - - - Contents\Resources - 1 - - - - - library\lib\armeabi-v7a - 1 - - - library\lib\arm64-v8a - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 0 - - - - - library\lib\armeabi-v7a - 1 - - - - - 1 - - - 1 - - - - - Assets - 1 - - - Assets - 1 - - - - - Assets - 1 - - - Assets - 1 - - - - - - - - - - - - - - - 12 - - - - -
diff --git a/windows/src/buildtools/buildpkg/buildpkg.res b/windows/src/buildtools/buildpkg/buildpkg.res deleted file mode 100644 index 6876088a6648ed90b09c480197508e4404c57dbc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57140 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 I2>8kW0h0=QvH$=8 diff --git a/windows/src/buildtools/buildpkg/buildpkgmain.pas b/windows/src/buildtools/buildpkg/buildpkgmain.pas deleted file mode 100644 index 29882895a62..00000000000 --- a/windows/src/buildtools/buildpkg/buildpkgmain.pas +++ /dev/null @@ -1,214 +0,0 @@ -(* - Name: buildpkgmain - Copyright: Copyright (C) SIL International. - Documentation: - Description: - Create Date: 23 Aug 2007 - - Modified Date: 22 Jun 2015 - Authors: mcdurdin - Related Files: - Dependencies: - - Bugs: - Todo: - Notes: - History: 23 Aug 2007 - mcdurdin - Initial version - 17 Sep 2007 - mcdurdin - Support output path parameter - 30 Dec 2010 - mcdurdin - I2562 - EULA as part of setup bootstrapper - 04 May 2012 - mcdurdin - I3306 - V9.0 - Remove TntControls - 23 Feb 2015 - mcdurdin - I4598 - V9.0 - Keyman installer does not show EULA when bundled with a keyboard - 04 May 2015 - mcdurdin - I4694 - V9.0 - Split UI actions from non-UI actions in projects - 11 May 2015 - mcdurdin - I4706 - V9.0 - Update compile logging for silent and warning-as-error cleanness - 22 Jun 2015 - mcdurdin - I4763 - Package compiler (buildpkg) needs to specify username and password on command line - 22 Jun 2015 - mcdurdin - I4764 - Buildpkg needs to support different paths for msi and kmp files - -*) -unit buildpkgmain; // I3306 - -interface - -procedure Run; - -implementation - -uses - Winapi.Windows, - - CompilePackageInstaller, - kpsfile, - Keyman.Developer.System.Project.ProjectLog, - SysUtils; - -type - TParams = class - private - TooManyParams: Boolean; - public - OutputPath, RedistPath, MSIFileName, KMPFileName, KMPName, AppName, LicenseFileName, TitleImageFileName: WideString; // I2562 // I4763 - StartDisabled, StartWithConfiguration: Boolean; - constructor Create; - function Validate: Boolean; - function Completed: Boolean; - - procedure CompilerMessage(Sender: TObject; msg: string; State: TProjectLogState); // I4706 - end; - -procedure Run; -var - Params: TParams; - pack: TKPSFile; -begin - Params := TParams.Create; - - if not Params.Completed then - begin - writeln('buildpkg.exe 1.0'); - writeln('Usage: '+ExtractFileName(ParamStr(0))+' -m [-l ] [-i ] [-a ] (-s )|(-n )'); // I2562 // I4763 - writeln('If setup-redist.exe is in setup folder location, it will be used in preference to setup.exe'); - ExitCode := 3; - Exit; - end; - - if not Params.Validate then - begin - writeln('buildpkg.exe 1.0'); - ExitCode := 4; - Exit; - end; - - if Params.KMPFileName <> '' then - begin - pack := TKPSFile.Create; - pack.KPSOptions.MSIFileName := Params.MSIFileName; - pack.FileName := ChangeFileExt(Params.KMPFileName, '.kps'); - pack.Info.Desc['Name'] := Params.KMPName; - - try - if not DoCompilePackageInstaller(pack, Params.CompilerMessage, False, Params.MSIFileName, - ChangeFileExt(Params.MSIFileName,'')+'-'+ChangeFileExt(ExtractFileName(Params.KMPFileName),'')+'.exe', Params.RedistPath, - False, False, Params.LicenseFileName, Params.TitleImageFileName, Params.AppName, - Params.StartDisabled, Params.StartWithConfiguration) then // I4598 // I4694 // I4764 - ExitCode := 1 - else - ExitCode := 0; - except - on E:Exception do - begin - writeln(E.Message); - ExitCode := 2; - end; - end; - end - else - begin - try - - if Params.OutputPath = '' then - Params.OutputPath := ChangeFileExt(Params.MSIFileName, '.exe'); - - if not DoCompileMSIInstaller(Params.CompilerMessage, False, Params.MSIFileName, Params.OutputPath, Params.RedistPath, - Params.LicenseFileName, Params.TitleImageFileName, Params.AppName, - Params.StartDisabled, Params.StartWithConfiguration) then // I2562 - ExitCode := 1 - else - ExitCode := 0; - except - on E:Exception do - begin - writeln(E.Message); - ExitCode := 2; - end; - end; - end; -end; - -{ TParams } - -procedure TParams.CompilerMessage(Sender: TObject; msg: string; - State: TProjectLogState); // I4706 -begin - if State in [plsError, plsFatal] - then raise Exception.Create(msg) - else writeln(msg); -end; - -function TParams.Completed: Boolean; -begin - Result := - not TooManyParams and - (MSIFileName <> '') and - ( - ((KMPFileName = '') and (RedistPath <> '')) or - ((KMPFileName <> '') and (KMPName <> '')) - ); -end; - -constructor TParams.Create; -var - i: Integer; - Flag: WideString; -begin - { Takes a .kmp file and turns it into a .msi installer } - i := 1; - while i <= ParamCount do - begin - Flag := ParamStr(i); Inc(i); - if Flag = '-m' then - MSIFileName := ParamStr(i) - else if Flag = '-n' then - KMPName := ParamStr(i) - else if Flag = '-s' then - RedistPath := IncludeTrailingPathDelimiter(ParamStr(i)) - else if Flag = '-o' then - OutputPath := ParamStr(i) - else if Flag = '-l' then // I2562 - LicenseFileName := ParamStr(i) - else if Flag = '-i' then - TitleImageFileName := ParamStr(i) - else if Flag = '-a' then - AppName := ParamStr(i) - else if SameText(Flag, '-startDisabled') then - begin - Dec(i); StartDisabled := True; - end - else if SameText(Flag, '-startWithConfiguration') then - begin - Dec(i); StartWithConfiguration := True; - end - else - begin - KMPFileName := Flag; - Break; - end; - Inc(i); - end; - TooManyParams := i <= ParamCount; -end; - -function TParams.Validate: Boolean; -begin - Result := True; - if not FileExists(MSIFileName) then - begin - Result := False; - writeln('File '+MSIFileName+' does not exist.'); - end; - if (KMPFileName <> '') and not FileExists(KMPFileName) then - begin - Result := False; - writeln('File '+KMPFileName+' does not exist.'); - end; - if (LicenseFileName <> '') and not FileExists(LicenseFileName) then // I2562 - begin - Result := False; - writeln('License File '+LicenseFileName+' does not exist.'); - end; - if (RedistPath <> '') and (not FileExists(RedistPath + 'setup.exe') or not FileExists(RedistPath + 'setup-redist.exe')) then - begin - Result := False; - writeln('File '+RedistPath+'setup.exe and '+RedistPath+'setup-redist.exe do not exist.'); - end; -end; - -end. diff --git a/windows/src/buildtools/buildpkg/version.rc b/windows/src/buildtools/buildpkg/version.rc deleted file mode 100644 index 134c4bf8c3c..00000000000 --- a/windows/src/buildtools/buildpkg/version.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" - -1 VERSIONINFO - FILEVERSION KV_FILEVERSION - PRODUCTVERSION KV_PRODUCTVERSION - FILEFLAGSMASK 0x3fL - FILEFLAGS 0x0L - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "0C0904E4" - BEGIN - VALUE "CompanyName", KV_COMPANY_NAME - VALUE "FileDescription", "Buildpkg\0" - VALUE "FileVersion", KV_VERSION_STRING - VALUE "InternalName", "BUILDPKG\0" - VALUE "LegalCopyright", KV_LEGAL_COPYRIGHT - VALUE "LegalTrademarks", KV_LEGAL_TRADEMARKS - VALUE "OriginalFilename", "BUILDPKG.EXE\0" - VALUE "ProductName", "Keyman Build Environment\0" - VALUE "ProductVersion", KV_VERSION_STRING - VALUE "Comments", "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0xc09, 1252 - END - END From 5a6758d12ea350d34b6c4fa5ecdb8a3befb8fe98 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 25 Sep 2023 08:44:11 +0700 Subject: [PATCH 4/5] chore(developer): move package version unit tests into Typescript --- .../versioning}/test-1.0/test-1.0.kpj | 0 .../test/fixtures/versioning/test-1.0/test.js | 1 + .../fixtures/versioning}/test-1.0/test.kmn | 0 .../fixtures/versioning/test-1.0/test.kmx | Bin 0 -> 370 bytes .../versioning}/test-2.0/test-2.0.kpj | 0 .../test/fixtures/versioning/test-2.0/test.js | 1 + .../fixtures/versioning}/test-2.0/test.kmn | 0 .../fixtures/versioning/test-2.0/test.kmx | Bin 0 -> 370 bytes .../test-keyboard-1-vs-package-2.kps | 0 .../test-package-1-vs-keyboard-2.kps | 0 .../test/fixtures/versioning}/test1-2.kps | 0 .../test/fixtures/versioning}/test1.kps | 0 .../test/fixtures/versioning}/test2-1.kps | 0 .../test/fixtures/versioning}/test2.kps | 0 .../src/kmc-package/test/test-versioning.ts | 42 + developer/src/test/auto/Makefile | 5 - .../test/auto/developer-test-auto.groupproj | 18 +- .../auto/keyboard-package-versions/.gitignore | 3 - .../KeyboardPackageVersionsTestSuite.dpr | 142 --- .../KeyboardPackageVersionsTestSuite.dproj | 1034 ----------------- .../KeyboardPackageVersionsTestSuite.res | Bin 57140 -> 0 bytes ...st.System.CompilePackageVersioningTest.pas | 155 --- .../auto/keyboard-package-versions/Makefile | 24 - 23 files changed, 47 insertions(+), 1378 deletions(-) rename developer/src/{test/auto/keyboard-package-versions => kmc-package/test/fixtures/versioning}/test-1.0/test-1.0.kpj (100%) create mode 100644 developer/src/kmc-package/test/fixtures/versioning/test-1.0/test.js rename developer/src/{test/auto/keyboard-package-versions => kmc-package/test/fixtures/versioning}/test-1.0/test.kmn (100%) create mode 100644 developer/src/kmc-package/test/fixtures/versioning/test-1.0/test.kmx rename developer/src/{test/auto/keyboard-package-versions => kmc-package/test/fixtures/versioning}/test-2.0/test-2.0.kpj (100%) create mode 100644 developer/src/kmc-package/test/fixtures/versioning/test-2.0/test.js rename developer/src/{test/auto/keyboard-package-versions => kmc-package/test/fixtures/versioning}/test-2.0/test.kmn (100%) create mode 100644 developer/src/kmc-package/test/fixtures/versioning/test-2.0/test.kmx rename developer/src/{test/auto/keyboard-package-versions => kmc-package/test/fixtures/versioning}/test-keyboard-1-vs-package-2.kps (100%) rename developer/src/{test/auto/keyboard-package-versions => kmc-package/test/fixtures/versioning}/test-package-1-vs-keyboard-2.kps (100%) rename developer/src/{test/auto/keyboard-package-versions => kmc-package/test/fixtures/versioning}/test1-2.kps (100%) rename developer/src/{test/auto/keyboard-package-versions => kmc-package/test/fixtures/versioning}/test1.kps (100%) rename developer/src/{test/auto/keyboard-package-versions => kmc-package/test/fixtures/versioning}/test2-1.kps (100%) rename developer/src/{test/auto/keyboard-package-versions => kmc-package/test/fixtures/versioning}/test2.kps (100%) create mode 100644 developer/src/kmc-package/test/test-versioning.ts delete mode 100644 developer/src/test/auto/keyboard-package-versions/.gitignore delete mode 100644 developer/src/test/auto/keyboard-package-versions/KeyboardPackageVersionsTestSuite.dpr delete mode 100644 developer/src/test/auto/keyboard-package-versions/KeyboardPackageVersionsTestSuite.dproj delete mode 100644 developer/src/test/auto/keyboard-package-versions/KeyboardPackageVersionsTestSuite.res delete mode 100644 developer/src/test/auto/keyboard-package-versions/Keyman.Test.System.CompilePackageVersioningTest.pas delete mode 100644 developer/src/test/auto/keyboard-package-versions/Makefile diff --git a/developer/src/test/auto/keyboard-package-versions/test-1.0/test-1.0.kpj b/developer/src/kmc-package/test/fixtures/versioning/test-1.0/test-1.0.kpj similarity index 100% rename from developer/src/test/auto/keyboard-package-versions/test-1.0/test-1.0.kpj rename to developer/src/kmc-package/test/fixtures/versioning/test-1.0/test-1.0.kpj diff --git a/developer/src/kmc-package/test/fixtures/versioning/test-1.0/test.js b/developer/src/kmc-package/test/fixtures/versioning/test-1.0/test.js new file mode 100644 index 00000000000..9ee538d9ae4 --- /dev/null +++ b/developer/src/kmc-package/test/fixtures/versioning/test-1.0/test.js @@ -0,0 +1 @@ +KeymanWeb.KR(new Keyboard_test());function Keyboard_test(){this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;this.KI="Keyboard_test";this.KN="Keyboard Version Test";this.KMINVER="9.0";this.KV=null;this.KDU=0;this.KH='';this.KM=0;this.KBVER="1.0";this.KMBM=0x0;this.KVER="17.0.159.0";this.KVS=[];this.gs=function(t,e) {return this.g0(t,e);};this.gs=function(t,e) {return this.g0(t,e);};this.g0=function(t,e) {var k=KeymanWeb,r=0,m=0;return r;};} \ No newline at end of file diff --git a/developer/src/test/auto/keyboard-package-versions/test-1.0/test.kmn b/developer/src/kmc-package/test/fixtures/versioning/test-1.0/test.kmn similarity index 100% rename from developer/src/test/auto/keyboard-package-versions/test-1.0/test.kmn rename to developer/src/kmc-package/test/fixtures/versioning/test-1.0/test.kmn diff --git a/developer/src/kmc-package/test/fixtures/versioning/test-1.0/test.kmx b/developer/src/kmc-package/test/fixtures/versioning/test-1.0/test.kmx new file mode 100644 index 0000000000000000000000000000000000000000..9e4bd15d391dea7a1b7e234e8f4f9ee80541836b GIT binary patch literal 370 zcmZvYO$$Lm6o%is!p_3S)4l&6lDtbj2`G0q?@%bfVlSjM&#>Fd| literal 0 HcmV?d00001 diff --git a/developer/src/test/auto/keyboard-package-versions/test-2.0/test-2.0.kpj b/developer/src/kmc-package/test/fixtures/versioning/test-2.0/test-2.0.kpj similarity index 100% rename from developer/src/test/auto/keyboard-package-versions/test-2.0/test-2.0.kpj rename to developer/src/kmc-package/test/fixtures/versioning/test-2.0/test-2.0.kpj diff --git a/developer/src/kmc-package/test/fixtures/versioning/test-2.0/test.js b/developer/src/kmc-package/test/fixtures/versioning/test-2.0/test.js new file mode 100644 index 00000000000..788a3d58ffa --- /dev/null +++ b/developer/src/kmc-package/test/fixtures/versioning/test-2.0/test.js @@ -0,0 +1 @@ +KeymanWeb.KR(new Keyboard_test());function Keyboard_test(){this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;this.KI="Keyboard_test";this.KN="Keyboard Version Test";this.KMINVER="9.0";this.KV=null;this.KDU=0;this.KH='';this.KM=0;this.KBVER="2.0";this.KMBM=0x0;this.KVER="17.0.159.0";this.KVS=[];this.gs=function(t,e) {return this.g0(t,e);};this.gs=function(t,e) {return this.g0(t,e);};this.g0=function(t,e) {var k=KeymanWeb,r=0,m=0;return r;};} \ No newline at end of file diff --git a/developer/src/test/auto/keyboard-package-versions/test-2.0/test.kmn b/developer/src/kmc-package/test/fixtures/versioning/test-2.0/test.kmn similarity index 100% rename from developer/src/test/auto/keyboard-package-versions/test-2.0/test.kmn rename to developer/src/kmc-package/test/fixtures/versioning/test-2.0/test.kmn diff --git a/developer/src/kmc-package/test/fixtures/versioning/test-2.0/test.kmx b/developer/src/kmc-package/test/fixtures/versioning/test-2.0/test.kmx new file mode 100644 index 0000000000000000000000000000000000000000..0efeffe974381d8411569d8e7d6b39d67935eb92 GIT binary patch literal 370 zcmZvYy$%6U5QWcH=oEfhg(w9fB2h?er%>34=m-gkzw8Rxr_gvOZ=}%h&AJNWBs24! zd+*G>yMswEQbroyvKJxG5=s%qJz@$x5vZ&s6uN`?x7C$eaD1m09Y3fx%ao?4{6;n5 zisLSvbL_)?g<5K+BYB~c&RWAOXuwLWEqgnhk2?_??RB7rteFoL(Xmg?)YVp1HKMMT qItdG}uUQ{Ar)x&P-8%l66yPJ?AvN3-dqs@@e}{e0=PwzXJmLl3Gb;7~ literal 0 HcmV?d00001 diff --git a/developer/src/test/auto/keyboard-package-versions/test-keyboard-1-vs-package-2.kps b/developer/src/kmc-package/test/fixtures/versioning/test-keyboard-1-vs-package-2.kps similarity index 100% rename from developer/src/test/auto/keyboard-package-versions/test-keyboard-1-vs-package-2.kps rename to developer/src/kmc-package/test/fixtures/versioning/test-keyboard-1-vs-package-2.kps diff --git a/developer/src/test/auto/keyboard-package-versions/test-package-1-vs-keyboard-2.kps b/developer/src/kmc-package/test/fixtures/versioning/test-package-1-vs-keyboard-2.kps similarity index 100% rename from developer/src/test/auto/keyboard-package-versions/test-package-1-vs-keyboard-2.kps rename to developer/src/kmc-package/test/fixtures/versioning/test-package-1-vs-keyboard-2.kps diff --git a/developer/src/test/auto/keyboard-package-versions/test1-2.kps b/developer/src/kmc-package/test/fixtures/versioning/test1-2.kps similarity index 100% rename from developer/src/test/auto/keyboard-package-versions/test1-2.kps rename to developer/src/kmc-package/test/fixtures/versioning/test1-2.kps diff --git a/developer/src/test/auto/keyboard-package-versions/test1.kps b/developer/src/kmc-package/test/fixtures/versioning/test1.kps similarity index 100% rename from developer/src/test/auto/keyboard-package-versions/test1.kps rename to developer/src/kmc-package/test/fixtures/versioning/test1.kps diff --git a/developer/src/test/auto/keyboard-package-versions/test2-1.kps b/developer/src/kmc-package/test/fixtures/versioning/test2-1.kps similarity index 100% rename from developer/src/test/auto/keyboard-package-versions/test2-1.kps rename to developer/src/kmc-package/test/fixtures/versioning/test2-1.kps diff --git a/developer/src/test/auto/keyboard-package-versions/test2.kps b/developer/src/kmc-package/test/fixtures/versioning/test2.kps similarity index 100% rename from developer/src/test/auto/keyboard-package-versions/test2.kps rename to developer/src/kmc-package/test/fixtures/versioning/test2.kps diff --git a/developer/src/kmc-package/test/test-versioning.ts b/developer/src/kmc-package/test/test-versioning.ts new file mode 100644 index 00000000000..e9771a369ab --- /dev/null +++ b/developer/src/kmc-package/test/test-versioning.ts @@ -0,0 +1,42 @@ +import 'mocha'; +import { assert } from 'chai'; +import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; +import { makePathToFixture } from './helpers/index.js'; +import { KmpCompiler } from '../src/compiler/kmp-compiler.js'; +import { KmpJsonFile } from '@keymanapp/common-types'; + +// This unit test was translated from a Delphi test +// Keyman.Test.System.CompilePackageVersioningTest, but note the difference in +// test results documented below. + +describe('package versioning', function () { + + const cases: [string,string][] = [ + ['test-single-version-1-package', 'test1.kps'], + ['test-single-version-2-package', 'test2.kps'], + + // The test result for the following two packages has changed in Keyman 17, + // in commit 92c8c6497e987a0583c62c91515884e6e36ece23, to 'shouldPass': + // + // `WARN_KeyboardVersionsDoNotMatchPackageVersion` has been removed, because + // it did not really make sense; if 'FollowKeyboardVersion' is set, it could + // not be raised, and otherwise, the author may wish to have separate + // keyboard + package versions anyway. + + ['test-version-2-1-mismatch', 'test2-1.kps'], + ['test-version-1-2-mismatch', 'test1-2.kps'], + + ['test-keyboard-1-package-2', 'test-keyboard-1-vs-package-2.kps'], + ['test-package-1-keyboard-2', 'test-package-1-vs-keyboard-2.kps'], + ]; + + for(const [ caseTitle, filename ] of cases) { + it(caseTitle, async function () { + const callbacks = new TestCompilerCallbacks(); + const kmpCompiler = new KmpCompiler(callbacks); + const kpsPath = makePathToFixture('versioning', filename); + const kmpJson: KmpJsonFile.KmpJsonFile = kmpCompiler.transformKpsToKmpObject(kpsPath); + assert.isTrue(kmpJson !== null); + }); + } +}); diff --git a/developer/src/test/auto/Makefile b/developer/src/test/auto/Makefile index 68108dde1fe..8f815f3b7b7 100644 --- a/developer/src/test/auto/Makefile +++ b/developer/src/test/auto/Makefile @@ -16,7 +16,6 @@ test: developer-tests: \ compile-supplementary-support \ keyboard-js-info \ - keyboard-package-versions \ kmcomp \ kmcomp-x64-structures \ kmconvert \ @@ -44,10 +43,6 @@ kmx-file-languages: .virtual cd $(DEVELOPER_ROOT)\src\test\auto\kmx-file-languages $(MAKE) $(TARGET) -keyboard-package-versions: .virtual - cd $(DEVELOPER_ROOT)\src\test\auto\keyboard-package-versions - $(MAKE) $(TARGET) - kmcomp: .virtual cd $(DEVELOPER_ROOT)\src\test\auto\kmcomp $(MAKE) $(TARGET) diff --git a/developer/src/test/auto/developer-test-auto.groupproj b/developer/src/test/auto/developer-test-auto.groupproj index cf31a8f8ced..b680dfb6aec 100644 --- a/developer/src/test/auto/developer-test-auto.groupproj +++ b/developer/src/test/auto/developer-test-auto.groupproj @@ -6,9 +6,6 @@ - - - @@ -41,15 +38,6 @@ - - - - - - - - - @@ -96,13 +84,13 @@ - + - + - + diff --git a/developer/src/test/auto/keyboard-package-versions/.gitignore b/developer/src/test/auto/keyboard-package-versions/.gitignore deleted file mode 100644 index 09bf1459b58..00000000000 --- a/developer/src/test/auto/keyboard-package-versions/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.kmp -test-?.0/*.js -test-?.0/*.kmx diff --git a/developer/src/test/auto/keyboard-package-versions/KeyboardPackageVersionsTestSuite.dpr b/developer/src/test/auto/keyboard-package-versions/KeyboardPackageVersionsTestSuite.dpr deleted file mode 100644 index d3645dc38f6..00000000000 --- a/developer/src/test/auto/keyboard-package-versions/KeyboardPackageVersionsTestSuite.dpr +++ /dev/null @@ -1,142 +0,0 @@ -program KeyboardPackageVersionsTestSuite; - -{$IFNDEF TESTINSIGHT} -{$APPTYPE CONSOLE} -{$ENDIF}{$STRONGLINKTYPES ON} -uses - System.SysUtils, - {$IFDEF TESTINSIGHT} - TestInsight.DUnitX, - {$ENDIF } - DUnitX.Loggers.Console, - DUnitX.Loggers.Xml.NUnit, - DUnitX.TestFramework, - Keyman.Test.System.CompilePackageVersioningTest in 'Keyman.Test.System.CompilePackageVersioningTest.pas', - CompilePackage in '..\..\..\common\delphi\compiler\CompilePackage.pas', - VisualKeyboard in '..\..\..\..\..\common\windows\delphi\visualkeyboard\VisualKeyboard.pas', - kmpinffile in '..\..\..\..\..\common\windows\delphi\packages\kmpinffile.pas', - kpsfile in '..\..\..\common\delphi\packages\kpsfile.pas', - PackageFileFormats in '..\..\..\..\..\common\windows\delphi\packages\PackageFileFormats.pas', - PackageInfo in '..\..\..\..\..\common\windows\delphi\packages\PackageInfo.pas', - utilfiletypes in '..\..\..\..\..\common\windows\delphi\general\utilfiletypes.pas', - StockFileNames in '..\..\..\..\..\common\windows\delphi\general\StockFileNames.pas', - utilstr in '..\..\..\..\..\common\windows\delphi\general\utilstr.pas', - Unicode in '..\..\..\..\..\common\windows\delphi\general\Unicode.pas', - JsonUtil in '..\..\..\..\..\common\windows\delphi\general\JsonUtil.pas', - KeymanVersion in '..\..\..\..\..\common\windows\delphi\general\KeymanVersion.pas', - utildir in '..\..\..\..\..\common\windows\delphi\general\utildir.pas', - utilsystem in '..\..\..\..\..\common\windows\delphi\general\utilsystem.pas', - RegistryKeys in '..\..\..\..\..\common\windows\delphi\general\RegistryKeys.pas', - utilexecute in '..\..\..\..\..\common\windows\delphi\general\utilexecute.pas', - GetOsVersion in '..\..\..\..\..\common\windows\delphi\general\GetOsVersion.pas', - VersionInfo in '..\..\..\..\..\common\windows\delphi\general\VersionInfo.pas', - ExtShiftState in '..\..\..\..\..\common\windows\delphi\visualkeyboard\ExtShiftState.pas', - VisualKeyboardLoaderBinary in '..\..\..\..\..\common\windows\delphi\visualkeyboard\VisualKeyboardLoaderBinary.pas', - VisualKeyboardLoaderXML in '..\..\..\..\..\common\windows\delphi\visualkeyboard\VisualKeyboardLoaderXML.pas', - VisualKeyboardSaverBinary in '..\..\..\..\..\common\windows\delphi\visualkeyboard\VisualKeyboardSaverBinary.pas', - VisualKeyboardSaverXML in '..\..\..\..\..\common\windows\delphi\visualkeyboard\VisualKeyboardSaverXML.pas', - VKeyChars in '..\..\..\..\..\common\windows\delphi\general\VKeyChars.pas', - VKeys in '..\..\..\..\..\common\windows\delphi\general\VKeys.pas', - ErrorControlledRegistry in '..\..\..\..\..\common\windows\delphi\vcl\ErrorControlledRegistry.pas', - kmxfile in '..\..\..\..\..\common\windows\delphi\keyboards\kmxfile.pas', - KeyNames in '..\..\..\..\..\common\windows\delphi\general\KeyNames.pas', - KeymanDeveloperOptions in '..\..\..\tike\main\KeymanDeveloperOptions.pas', - Keyman.System.PackageInfoRefreshKeyboards in '..\..\..\common\delphi\packages\Keyman.System.PackageInfoRefreshKeyboards.pas', - Keyman.System.KeyboardJSInfo in '..\..\..\common\delphi\keyboards\Keyman.System.KeyboardJSInfo.pas', - Keyman.System.KeyboardUtils in '..\..\..\common\delphi\keyboards\Keyman.System.KeyboardUtils.pas', - Keyman.System.KMXFileLanguages in '..\..\..\common\delphi\keyboards\Keyman.System.KMXFileLanguages.pas', - Keyman.System.Standards.ISO6393ToBCP47Registry in '..\..\..\..\..\common\windows\delphi\standards\Keyman.System.Standards.ISO6393ToBCP47Registry.pas', - Keyman.System.Standards.LCIDToBCP47Registry in '..\..\..\..\..\common\windows\delphi\standards\Keyman.System.Standards.LCIDToBCP47Registry.pas', - TempFileManager in '..\..\..\..\..\common\windows\delphi\general\TempFileManager.pas', - RedistFiles in '..\..\..\tike\main\RedistFiles.pas', - DebugPaths in '..\..\..\..\..\common\windows\delphi\general\DebugPaths.pas', - Upload_Settings in '..\..\..\..\..\common\windows\delphi\general\Upload_Settings.pas', - klog in '..\..\..\..\..\common\windows\delphi\general\klog.pas', - compile in '..\..\..\common\delphi\compiler\compile.pas', - Keyman.Developer.System.Project.kmnProjectFile in '..\..\..\tike\project\Keyman.Developer.System.Project.kmnProjectFile.pas', - Keyman.Developer.System.Project.kmnProjectFileAction in '..\..\..\tike\project\Keyman.Developer.System.Project.kmnProjectFileAction.pas', - Keyman.Developer.System.Project.Project in '..\..\..\tike\project\Keyman.Developer.System.Project.Project.pas', - Keyman.Developer.System.Project.ProjectFile in '..\..\..\tike\project\Keyman.Developer.System.Project.ProjectFile.pas', - Keyman.Developer.System.Project.ProjectFiles in '..\..\..\tike\project\Keyman.Developer.System.Project.ProjectFiles.pas', - Keyman.Developer.System.Project.ProjectFileType in '..\..\..\tike\project\Keyman.Developer.System.Project.ProjectFileType.pas', - mrulist in '..\..\..\tike\main\mrulist.pas', - kmxfileconsts in '..\..\..\..\..\common\windows\delphi\keyboards\kmxfileconsts.pas', - Keyman.Developer.System.Project.ProjectLoader in '..\..\..\tike\project\Keyman.Developer.System.Project.ProjectLoader.pas', - Keyman.Developer.System.Project.ProjectLog in '..\..\..\tike\project\Keyman.Developer.System.Project.ProjectLog.pas', - Keyman.Developer.System.Project.ProjectSaver in '..\..\..\tike\project\Keyman.Developer.System.Project.ProjectSaver.pas', - UKeymanTargets in '..\..\..\common\delphi\general\UKeymanTargets.pas', - CompileErrorCodes in '..\..\..\common\delphi\compiler\CompileErrorCodes.pas', - KeyboardParser in '..\..\..\tike\main\KeyboardParser.pas', - WindowsLanguages in '..\..\..\common\delphi\general\WindowsLanguages.pas', - KeymanWebKeyCodes in '..\..\..\tike\compile\KeymanWebKeyCodes.pas', - kmxfileutils in '..\..\..\..\..\common\windows\delphi\keyboards\kmxfileutils.pas', - TouchLayoutDefinitions in '..\..\..\tike\oskbuilder\TouchLayoutDefinitions.pas', - TouchLayout in '..\..\..\tike\oskbuilder\TouchLayout.pas', - KeyboardFonts in '..\..\..\common\delphi\general\KeyboardFonts.pas', - Keyman.Developer.System.Project.kpsProjectFile in '..\..\..\tike\project\Keyman.Developer.System.Project.kpsProjectFile.pas', - Keyman.Developer.System.Project.kpsProjectFileAction in '..\..\..\tike\project\Keyman.Developer.System.Project.kpsProjectFileAction.pas', - CompilePackageInstaller in '..\..\..\common\delphi\compiler\CompilePackageInstaller.pas', - utilhttp in '..\..\..\..\..\common\windows\delphi\general\utilhttp.pas', - Keyman.System.LanguageCodeUtils in '..\..\..\..\..\common\windows\delphi\general\Keyman.System.LanguageCodeUtils.pas', - Keyman.System.RegExGroupHelperRSP19902 in '..\..\..\..\..\common\windows\delphi\vcl\Keyman.System.RegExGroupHelperRSP19902.pas', - DUnitX.Loggers.TeamCity in '..\..\..\..\..\common\windows\delphi\general\DUnitX.Loggers.TeamCity.pas', - BCP47Tag in '..\..\..\..\..\common\windows\delphi\general\BCP47Tag.pas', - Keyman.System.Standards.BCP47SubtagRegistry in '..\..\..\..\..\common\windows\delphi\standards\Keyman.System.Standards.BCP47SubtagRegistry.pas', - Keyman.System.Standards.BCP47SuppressScriptRegistry in '..\..\..\..\..\common\windows\delphi\standards\Keyman.System.Standards.BCP47SuppressScriptRegistry.pas', - Keyman.System.CanonicalLanguageCodeUtils in '..\..\..\..\..\common\windows\delphi\general\Keyman.System.CanonicalLanguageCodeUtils.pas', - TextFileFormat in '..\..\..\common\delphi\general\TextFileFormat.pas', - Keyman.System.LexicalModelUtils in '..\..\..\common\delphi\lexicalmodels\Keyman.System.LexicalModelUtils.pas', - Keyman.System.PackageInfoRefreshLexicalModels in '..\..\..\common\delphi\packages\Keyman.System.PackageInfoRefreshLexicalModels.pas', - Keyman.System.Standards.LangTagsRegistry in '..\..\..\..\..\common\windows\delphi\standards\Keyman.System.Standards.LangTagsRegistry.pas', - Keyman.Developer.System.Project.UrlRenderer in '..\..\..\tike\project\Keyman.Developer.System.Project.UrlRenderer.pas', - KeymanPaths in '..\..\..\..\..\common\windows\delphi\general\KeymanPaths.pas', - Keyman.Developer.System.ValidateKpsFile in '..\..\..\common\delphi\compiler\Keyman.Developer.System.ValidateKpsFile.pas', - Keyman.Developer.System.KeymanDeveloperPaths in '..\..\..\tike\main\Keyman.Developer.System.KeymanDeveloperPaths.pas', - Keyman.Developer.System.KmcWrapper in '..\..\..\tike\compile\Keyman.Developer.System.KmcWrapper.pas'; - -var - runner : ITestRunner; - results : IRunResults; - logger : ITestLogger; - nunitLogger : ITestLogger; -begin -{$IFDEF TESTINSIGHT} - TestInsight.DUnitX.RunRegisteredTests; - exit; -{$ENDIF} - try - //Check command line options, will exit if invalid - TDUnitX.CheckCommandLine; - //Create the test runner - runner := TDUnitX.CreateRunner; - //Tell the runner to use RTTI to find Fixtures - runner.UseRTTI := True; - //tell the runner how we will log things - //Log to the console window - logger := TDUnitXConsoleLogger.Create(true); - runner.AddLogger(logger); - //Generate an NUnit compatible XML File - nunitLogger := TDUnitXXMLNUnitFileLogger.Create(TDUnitX.Options.XMLOutputFile); - runner.AddLogger(nunitLogger); - runner.FailsOnNoAsserts := False; //When true, Assertions must be made during tests; - - //Run tests - results := runner.Execute; - if not results.AllPassed then - System.ExitCode := EXIT_ERRORS; - - {$IFNDEF CI} - //We don't want this happening when running under CI. - if TDUnitX.Options.ExitBehavior = TDUnitXExitBehavior.Pause then - begin - System.Write('Done.. press key to quit.'); - System.Readln; - end; - {$ENDIF} - - DUnitX.Loggers.TeamCity.ReportToTeamCity; - except - on E: Exception do - System.Writeln(E.ClassName, ': ', E.Message); - end; -end. diff --git a/developer/src/test/auto/keyboard-package-versions/KeyboardPackageVersionsTestSuite.dproj b/developer/src/test/auto/keyboard-package-versions/KeyboardPackageVersionsTestSuite.dproj deleted file mode 100644 index 1ebd5a77344..00000000000 --- a/developer/src/test/auto/keyboard-package-versions/KeyboardPackageVersionsTestSuite.dproj +++ /dev/null @@ -1,1034 +0,0 @@ - - - {7A8E88E4-B407-442B-9A53-DE6F43F1C0F1} - 18.8 - VCL - KeyboardPackageVersionsTestSuite.dpr - True - Debug - Win32 - 1 - Console - - - true - - - true - Base - true - - - true - Base - true - - - true - Base - true - - - true - Cfg_1 - true - true - - - true - Base - true - - - .\obj\$(Platform)\$(Config) - .\bin\$(Platform)\$(Config) - false - false - false - false - false - RESTComponents;FireDAC;FireDACSqliteDriver;soaprtl;FireDACIBDriver;soapmidas;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;$(DCC_UsePackage) - System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) - true - $(BDS)\bin\delphi_PROJECTICON.ico - $(BDS)\bin\delphi_PROJECTICNS.icns - $(DUnitX);$(DCC_UnitSearchPath) - KeyboardPackageVersionsTestSuite - $(CI);$(DCC_Define) - 3081 - CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= - - - DBXSqliteDriver;bindcompdbx;IndyIPCommon;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;svnui;mbColorLibD10;dsnapcon;FireDACADSDriver;scFontCombo;DCPdelphi2009;FireDACMSAccDriver;fmxFireDAC;vclimg;Jcl;vcltouch;JvCore;vcldb;bindcompfmx;svn;FireDACPgDriver;inetdb;DbxCommonDriver;fmx;fmxdae;xmlrtl;fmxobj;vclwinx;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;IndyIPClient;bindcompvcl;EmbeddedWebBrowser_XE;VCLRESTComponents;dbxcds;VclSmp;JvDocking;adortl;JclVcl;vclie;bindengine;DBXMySQLDriver;dsnapxml;FireDACMySQLDriver;dbrtl;inetdbxpress;IndyProtocols;keyman_components;FireDACCommonODBC;fmxase;$(DCC_UsePackage) - Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) - Debug - CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= - 1033 - - - DBXSqliteDriver;bindcompdbx;IndyIPCommon;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;Jcl;vcltouch;vcldb;bindcompfmx;FireDACPgDriver;inetdb;DbxCommonDriver;fmx;fmxdae;xmlrtl;fmxobj;vclwinx;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;IndyIPClient;bindcompvcl;VCLRESTComponents;dbxcds;VclSmp;adortl;JclVcl;vclie;bindengine;DBXMySQLDriver;dsnapxml;FireDACMySQLDriver;dbrtl;inetdbxpress;IndyProtocols;FireDACCommonODBC;fmxase;$(DCC_UsePackage) - - - DEBUG;$(DCC_Define) - true - false - true - true - true - - - false - -l:Information - 1033 - (None) - - - false - RELEASE;$(DCC_Define) - 0 - 0 - - - - MainSource - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cfg_2 - Base - - - Base - - - Cfg_1 - Base - - - - Delphi.Personality.12 - Console - - - - KeyboardPackageVersionsTestSuite.dpr - - - Microsoft Office 2000 Sample Automation Server Wrapper Components - Microsoft Office XP Sample Automation Server Wrapper Components - - - - - - true - - - - - true - - - - - true - - - - - true - - - - - KeyboardPackageVersionsTestSuite.exe - true - - - - - 1 - - - 0 - - - - - classes - 1 - - - classes - 1 - - - - - res\xml - 1 - - - res\xml - 1 - - - - - library\lib\armeabi-v7a - 1 - - - - - library\lib\armeabi - 1 - - - library\lib\armeabi - 1 - - - - - library\lib\armeabi-v7a - 1 - - - - - library\lib\mips - 1 - - - library\lib\mips - 1 - - - - - library\lib\armeabi-v7a - 1 - - - library\lib\arm64-v8a - 1 - - - - - library\lib\armeabi-v7a - 1 - - - - - res\drawable - 1 - - - res\drawable - 1 - - - - - res\values - 1 - - - res\values - 1 - - - - - res\values-v21 - 1 - - - res\values-v21 - 1 - - - - - res\values - 1 - - - res\values - 1 - - - - - res\drawable - 1 - - - res\drawable - 1 - - - - - res\drawable-xxhdpi - 1 - - - res\drawable-xxhdpi - 1 - - - - - res\drawable-ldpi - 1 - - - res\drawable-ldpi - 1 - - - - - res\drawable-mdpi - 1 - - - res\drawable-mdpi - 1 - - - - - res\drawable-hdpi - 1 - - - res\drawable-hdpi - 1 - - - - - res\drawable-xhdpi - 1 - - - res\drawable-xhdpi - 1 - - - - - res\drawable-mdpi - 1 - - - res\drawable-mdpi - 1 - - - - - res\drawable-hdpi - 1 - - - res\drawable-hdpi - 1 - - - - - res\drawable-xhdpi - 1 - - - res\drawable-xhdpi - 1 - - - - - res\drawable-xxhdpi - 1 - - - res\drawable-xxhdpi - 1 - - - - - res\drawable-xxxhdpi - 1 - - - res\drawable-xxxhdpi - 1 - - - - - res\drawable-small - 1 - - - res\drawable-small - 1 - - - - - res\drawable-normal - 1 - - - res\drawable-normal - 1 - - - - - res\drawable-large - 1 - - - res\drawable-large - 1 - - - - - res\drawable-xlarge - 1 - - - res\drawable-xlarge - 1 - - - - - res\values - 1 - - - res\values - 1 - - - - - 1 - - - 1 - - - 0 - - - - - 1 - .framework - - - 1 - .framework - - - 0 - - - - - 1 - .dylib - - - 1 - .dylib - - - 0 - .dll;.bpl - - - - - 1 - .dylib - - - 1 - .dylib - - - 1 - .dylib - - - 1 - .dylib - - - 1 - .dylib - - - 0 - .bpl - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - - - - - - 1 - - - 1 - - - 1 - - - - - - - - Contents\Resources - 1 - - - Contents\Resources - 1 - - - - - library\lib\armeabi-v7a - 1 - - - library\lib\arm64-v8a - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 0 - - - - - library\lib\armeabi-v7a - 1 - - - - - 1 - - - 1 - - - - - Assets - 1 - - - Assets - 1 - - - - - Assets - 1 - - - Assets - 1 - - - - - - - - - - - - - - - True - False - - - 12 - - - - - diff --git a/developer/src/test/auto/keyboard-package-versions/KeyboardPackageVersionsTestSuite.res b/developer/src/test/auto/keyboard-package-versions/KeyboardPackageVersionsTestSuite.res deleted file mode 100644 index 6876088a6648ed90b09c480197508e4404c57dbc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57140 zcmce82S8N0_V-W(L{uzmS5QGfrHY6R5J3S&5ClQ06j7w9G^I-urAhBaI!N!mH|f3i zs`TDw=6=brliVaHxyi{XzkouaP}CqI$YunOe+o~D@#RF|9Rge# zCFORIyBX*~LJ1-@hy=KQ!NV^Eaj^%K273DH+8P>hin6kmin4N*;5qiCj?PnF-kZDs zt_fRf8&yAV?`ijs9})X^F31bbkH`xRXXL$&Gveathb8PY;+aE@;7z2wviB9jm^o-8kdleBu|V_ zP%SGiK@=XfBU;Z!0gY3LtJ5T+sxXY)xYCQbIZq<&=euw;nHzmY#Rwx9WBlhiBs*gPvA3N-dVAJzbu-cykg!iPh{lr?6W=zF8St$5Xz2Ug_<3Yv zVj?1Pq9P(oyxh~j*N5~>a*N9PN<)zlwKnbzu`?D$uo6RlP<=CM0kTG}bpf=;`c4 zJ_XcZ#qV|@Vs{6A8pVaXvEZHc)~04mMOnE3tcwqw?HvZggM-+T;ts6Vvs&!E+g-@L z+x@@CZtM$iE^y_}rf@B9H@ zZx-z6eo_>wfCz;$-((~BqMxSl9r!M+1M9xqzR6<{1o9z5T%8~J&>@h^0^&d6Lt8uF zwQColn3y<+ijwjhMS1xUX~~BPj~+@TJeF7Z^jPt+p@4t@J0S>L>-@^|>C?1Cdb)ZF z?`_|;I@sAE=ElZ|wz@i^BrlJPTHx9A%^SeKY_aAhrj07fDv!2rCkLbd_d!kV*$Kd7 zio!pIAijXFxj8!{KAwTdThlPCo=!AY7eot_5UjVmAC5PAy19Wp;)z(ATjbomD}40t zdN4G2&E)LhIO^}?g9HZzBK|&kh>Aih!b0EreShNl70gqXYXbdbV1xbrks!b)KRP)L z$jd7*{H%{RZ;X$-Iy;Ygy1F7!;W3D=b|V(@8+?0zmBM#kJg>n`(4t12!cw1&NK0MgZSWAtECB{@wk2{iKr< z5|F%{T*TmID~_lASpQdk>uNV(%S%cCkIhBizO}js2f)h8Opub4TwenCPD)}cjtBor zTR(dT&Q)qs3l{J#$iqrN^8}urK1}(bzsj<58#UfLaXyh(`KavH`p^XhJA_aIpGhHWATeFNTfipmm zw-47oGhGX|va||Y2Ik4z%SS0XGRi0Z^JnB!VCnaHhwY~&&wu~M5+Vc0+8P$g&0a*V zvG*Y3V;e|s_ZsfZL_jbx9RL0<98<7gAqLVM8vMyVG9u!0WLOyD^uFXT+rP-zjg*%z zAq(>ugrBPyF?={B15VJR5k@a;f_-4ys&kiGl1M9eRyQp9hHx76{GM)LO4{z7>jpVpEBs?V4 zHaRKzSvHufoXmVIGhGv|4@m#?6dI|nT1Hx$S8=q$@B2by6!%>q-Hz`kaDBmVF$La* z-w4vrbfy`Tk&=OiZH5GgNPqquM_XD{gslLwj=WSA7Sd5#yoA(Nuizr28Fy9#xkpoN z1gQaiLV4uTgF#$`=Q(`W*K-Q+sV;EdSFD%h=OcxAdFv)7rZ_%PSyoouSW|;Uhm~Sk z&$i*_9M1bcjqHr=*zn+j_3H9+1jrXjcm`BlR3g~g)P%HwsG(Mb5xdim8!sI5uSRj< z0U(PNtu}$Z+tS#GiH(it#J3OAriR9t?)G-1tr_rL`C^PXkR|>}RC`>p+E~|sX>Vyk zs=j>j-r6>N24mRM)zR73-_ry3PA_6)P=pZ`>PAF``u|Pr!I~RathKkcW14~N*;rry z#oODL{Kxj;@4CABW4+zoEkK?D>t_ndNUy~{e^QJQzSRQc8oW%inF`--#ppb*+{npn z*ccfaMmkzsk(Q?B%FK+c{Xc6PpI2X3zk6tKFl2gi3cIkdfIyk2x2GSQmC=NW3~xk7 zMKqyvvRXF=`iC$J^Yh5$!~`-tG=%Bw=~rw6&YnIgJ6I>=KM zRphap9HJyAkD~?VnE~3~+t}b_L!cXDbzkYG^6=b%s{20;1bVvq+FtJNEAR{p^z}uc z{O0cBiiC$o0r@fs$eMZB*Lo$`*Sf`6Gou`=vwb`^EI1tW{SkrsI@G=Wy}c19dxwR` zkCmPP0)A;OsHmuj%uUTbq5KMEOE~t3kT7s2l>t4d9m{sE37jWC*U2w{G7YsBY;Zsx zHY6w*2>^9r8@^uNSRHMh4}gY$Cu#=XxjcHOW@Ds zpQmleQ{_f%Ty#3n?*ec%1b{hw^-}lU-_3)Kwe52-=ZF{RJJ>$}oOiVd*QI|h)8c93 z=4`=6hLvEU&JYq9hy?iuU^O+gFx-NLu_|KWoJM^;7#uB^7Y7J2@p?Ym5cZ{xpB;d%h)JCI|lfNY$%0eIMVeJLjT zb6`IT!<9q7a*dd_s@ifMW`jm#{>B_8HtIk27PbpruhDc0sZ(ng>wyUZg?3T>I2s< z_8{NBZs2Huwk|kUXy1at&wEpM!q51$4CyA=#jCWd*?rUvI4(p6Emgez+W@;NKRrkxO952kij#pnz$*0jV# z#KYb5Ra8XO$MDclBswAjoGn%Vwto($ZbV0Y6xRp*9#DRRHo@eCd0Za+XJrM8%ir2B z{@F;cXd@Z$fdnvKUvFR2sK_Yi2yn(kherS#T_pzp-q!KM^?UPLFOcy!b*6Wg-!}UP z>k+;OV<@ok;lnpzpS%k6L3~?V(>JdQHWESKP>=HS@imE#inff2j08L?3i)93hpvh5 zAL=m=MF)XxVd#5=Ivfm82ZH%<9Y8%4hOgtB-@c@93E^bfT=!f1w=&IHPmYa6l0fwF z_SK609QQZ{*cf2^6j1Ol>kryms`ZTz&>AT zjp6ienBnOe49_cm$hK>R$@*5S8@YvAKY*SjGh;Y_)iSwPRr1iDiZ!g{t2w+8Uz zhkIxq=)W+c(VJt0Z9^R&+JqD1=HO49UijqkFfK1RU~_#gFJS;L9r@0mSm^7}xfxkF z9WW;&10yRdcSKoPnGonyqou$OQdU$9>`oQ9H30ixUdC>T7@RGks&W~zeftfk0~+a% zB1dPPLVl zNZpq&NK{x6;J+<6Tf5YKpet^TKzD>TYkb7%k-wMY^YH1`vRhnz$T^x;Y-mu227DRnfpSs>7--ji2-^N%M7VbzJ;+~%dQyDZYF9@G0>=){-qn

Kh8r_W0MZhm6875US#6yS72*t#Hv5Z#E1xVA)gBG8T1d0x0$Tivt) z+kt(zHaDY-i;AUw?C)p4+uGVR`+IuPa1NlpJ_TZ8LJ8)XY9{z5HCW+WeTXnP@BbY8 zfDBNF)_z{FmXY>leSB;T_-6)jbKc(Cx>8wD`S53b{Z(E^N9V24;gM0Or_asJfqlM+ z)9Jgrdw`#+9PQ~=g0{0M+IVkUyy5LxzMh_1z24u~kA}Ma%=9$i!{fl-HGuSVcXxgH zQpNFC{rp`%sJCZ)Y}^_2zXJOQIzQm^Yv7#SKrnzY;`M&`ys^Fx&b<|2E8Oh=+t;u2 zeZ74a5fM?pY+Lv%T7VDc@Z{vA5ul@C6&O{2+CQLaWqBD5zE#EO=%^0x&FuNB_Wqmv z!ouPMqoZT|QXKfjC%@Uef~C(=)fb4g=SD6>@*ifR^x+TD*r zk-}I27*zv;`FLGQ3{tby6H+U66RECjj*DN?RL8t16&>)6OD?z-LJROD!$L7`$U`VS&Ipz{iHsP}gX^bLZ|W3JQw9 zwNw5tMhN_j6iQ0UMmE+qQ_!veFcJvxu>mZ?AM`^S)t@{;lob>ZMHv|cU@w4drGU$O zp{a=&>gwYBlXlkDK<}^zJ`)$j#mNcL*E1Lq7QUwg{E|EV7qtG+2C$_`a+#T$H$yuE zv@Jp39kh2qJcm8-nQqR%A+WK%L|*IZBfw7z@+{yS1N)W5A87sYCy~0khJmxA(@IEC5RenYkWi398xgeG zK!2>Cw=eK>Wg!W16Az(R$%* zW*)${2I=<$?FE4E3FA8(+qrx9M4kdd{+-?GM_T{%`}}!EG6Mrcf47e=IGY%>Nx^xC zv;*51(0x;ptn_9;TL<>q#X9U+ApdUFS$_5mZ4}oyYJu&q6`P#!1q=L9VD7ze^auWK zcZ0S!4_7w~@C|<;At53C6H&kTgN22a6s(s>Xj6nXNF2?;w&(-;ivJvkF!9qP0(!Di;zOYZ8sJU<3wvFT$$;Q7%Xl`cV1NRor zrU>YVYbC(P4`5g-0k)&RSM+f7oLD#IPWk*8#M3@0vkgs@Ndw8 z3+?!M;peWy78lfDp-mRzAd-N6HWAn@tSqfF0Z!sC_X4n|>cmFJ;A~pZrkk0T0d$}C z-`C9F&l|q)|5Yj>Qj4wmQj0Cj%Lh1)9GsmI;4ZLoa`Mt!=N$ih@1E$+$cV`Cj8w=I z({VQ8`kH#g7VOn?zuN}?SG4_FJ00MhtH(6d)&ae}0)aRZ7{U5z0kY!1$V|YdqXliL z`CzQYz@}VP@daQQ1^}OF_@D8aU!(hv@5~JNQel1@2HKvX?YFMF8YwO;LcqBofuDDn z0!$21bkyf&Xs0g*_Mk826-Y-Lu;(gl;t&35zyHhkmE`I$J)K<$^!G#iIgGBZ?%9Cs z?`QMdx7HW4GqW&|{!(D)fpcF{)DQUNA9D{eHePO1{}Q3?*c@OQAkGltWAL;?Yy-qp z;Op2}{DINIzk^RN09+`xIM%|L3aY5-pC4_^qh!$J(n-vwxg?(bU%^6?+o8%wjVf2yLVGq#1UKgQ}0 z?B)0XZH-E@!+(0u@Kr6k4cKuSYHM+82(Ax3Jp(m7{n1e|CD4wU1J*yZ?*nWCumjiP z?3r*LeuaK~|1gDiUbeHFHuQqr#qUKB`^pDwYJbdaCk}H1ZKe3&=k>3)|H~JuF>TE) z*jiwRgFXltU0vLw0R05uY$i{Li=RzTNdbPER3O*n0DjeuJ$vd8`QS(Tp?&wM(g-eU zJsrh;`{AKKf1mJ>862Gua|G?;_)rWmKzP5=C1zl60^bZD{>pa%Wxmv;%8g23zl8e} zV%I`Gg>(QuL}F=aeI_YB0m!~_xU&NKbbLITfi3qBU+s_dYXX|L&LMn;{)OD%eL9dH z0I5J8+}p$uL9Fi9Ikq(2T;C8Ej1SNjECOs~Kemhi?fAZIqZsVZyzFcw53Ca)LoU+N zp83tq&4WK4oNY0{4-gjm(i6@KX{Ju|V}c8x#~G32Bc6SoG+~2qZH#9eJkG_#e>^ z`}G7o3LiS!S8-#9`4D^F-L>g&z?b7wi21{>sh`mf^Au$&)^otwn)16WkqYD*1qH>+ z;o*^wqJR%7EF=UcD`lpoBl6O9|Cs(uz~=(7dUgP}jt>jKPbDukh>OsN1pPG-7q>M) ztQy=Se?>Pw|Ka_LwXCEhoc{`9Mw5YGTTM-!3(^mLXyL!ppOKmd`m6mV`k|lh7Iz;a z1AG^cWrlFk{o~|!@*w^Y`a|$#8fqgr9N+gBz(ai<^nd=rOY!vnm`aM4uVw;S4*I_! z{m?J}^r`ywPoF}?KZD=6^#jHMaQKLt(%;js4elrKUGD|HsZGBeq!AyJ;{WgmLjM%> zli|zoKFY21!)Fh`&!CU>N1C_(mX|77%>eX6{~`35CIg=H__6XuZ*M>DgxEOX!`<}d z!S7o@d2(WgO_6nJHU-@rFrYK zhFbm#q#yeKpezmM9}VyjryLxdPNXCzVPPJWnc=>0b|?q*|26+~wx7hEJ9xY&OyPM@ zSF?gA3Fi~me=&x8@1^D_&R>Qvgm_@Mrn)-+*w66%fIdZteceho{@Kbbb0rJ#o>b^F z2Yy7L_fMZadv@3B*G42MNh#wvz68oM)6$TH*fI>msrv8j{K!8u(-&~}IN)850Dv=w zzu_H|tsyRE4(I!X^WW06`n_o48yc+75nS18-SO}KSNK8}XlGN7`tw?Xe!cME)Rk;N z8$4%W3hvBQgYy@s6Q?AnrouA;FF%);lp^3A8Dq!ckIUqe4M z^hd)O8=Z$?I`ah!dBXp~AN^0-fH)3D+FEo>c;+(n(boXFp%1&d@(aeq#GLg<`t|i+ z6IGN~G(oHtjL@gu1a#*Yn#pLUGi^9o@~`f4{a@r?IM<12K24m1YXM@>f5&+v>1i1d zNB&dWbXI1LFwirxIG;7pcRGRJy0WYSxqTxAEpVe3kpS}W|BonqyARl#(iVW8g~s`i zAwB@m0`9l1+S@xY|2X&f-xd}Y1XW+EVmpB^AJPu->(Hm3k(!UaaV--qezzZa0Q~g- zml0wB__*?yb21B8A?5(;jgX$M_6|7rc6eIe{KAi80oeYVU7ej9 zJzZV6`5yxGe*=E;tc(JT#Qg-cs8H{JglqUaEQF{~A0jK2xmcK2x;oI;hr@f|cnR2x z0NXGF?g%jaNax@EuCA_80eA>BZVcd#!q~_Nkj*AxTiBOcVd#4Tb=Y6QMEu%2O=x4o z#KqQ@7BsjU0M<(TCLe@+q@{H!At90f?`Zw2vikZ4oj!o4=mpT=! zBGFN47&++}wD7IQf4K_*v30)^g>ScDR1{KHQj-f-;rxsa4ujDs1H7kJcxd!(EY#)cq0Cz|i7UtnSQaBE@nsVrd5PvrM4qqFDOsX=}tUJz}8?E!Ce!0mlon=V4EXgZu-GD?gMKT?7eDmx8%&fqwAlP=jG+^8ypz) z1A73ym41j#ff3+CfNs0~9isxVA}|j|G})xpYXZzM8h!(OfX`rj8(^$sQ&ZD<02^fk#(%@j&5i8; zn7n`7d`L(bNpf=PZ)Ihbw1EGf1$WTS78aJA{`@(9pM!(r{~R}iAO%FNZTwLqZyBL#RRfLKDI`e6z@=lHY${stZg zd}o>`CI71|L%wRc>2M3@Z-Xd7e9Xde1NIJ&CmDwDge!b zOaubBUE& z*Hrt(<=WVaZ(nV1=BqJ}1+FoZz;uG8`&2*qf9}ztP}3c?8^QVp21b3e>ut6&ot?Z~ z`S~ZuS1zr;EetA=;&Gu7zQ13%k==UFsXHz-na8bm+_>As&RDxsyv_9%n>YK;)4{%@ z#=83Y`fv30)wMv>RZ$t8Qw#7uapHs{!8;<#rQ4#U=Ic`3g-qF#NjAQ5xoNqv+1c4A z_dhyJZtby=gAJ1pjJVm9azJ>2_`1B4f(uQ{&|J~b9FGUBs8FF7@t3Ei++~crs@MuI z+dlSsS3dNvT$zR9rc?RgLM5Lu#{s86$J+8+qam*_;^N{aL$0oL;ApzXwbU$rnsoOG zKVs+4+-X-(&E<#5Hm1`1dXru+jJhA!)I56XV?{U*O9m4q+4+?X45I~4!9H@^;AcnZ z!{XN~U)FvUpkcXi-61nGa}~fMSG&7qXBL~A2gFaGHWJyjbE+>3}U+Cv-2p^vuB#QpAr-2=0!Pk&g>^o<+y#Sd1l3ua;2PxZ>iHDQCZ^U zwUg%Pc+V^8YiqClP8{8LLA*&>yh;3aSy`F^K(qdP$vLjwgK!>oI^^A)zKqIKWcy4aZ-$V|HX8FUMZo1J5%D@y*O81 zboG&t5%M;gy)r9j7ruM%-r(Z+_~dFy$$)rqG4tZm()Fd`CXpHA@nG9~ge>2ZLw2DK z4mxu!M3`kgsj=DFmYSN@yVs5{jXgarEtT&Pb*0Nq{{xh7v&kP_J{eC!TuY4dL%Hp~ z^%YrIsYFwp46-t(Bo|7~*F18j?4Hx($>#C)il~qNbQ|j@`qltjk?;rf-(j z*l8i=^E#}2a`HSt`Y4?~eL5SQ(o|hbMLV3(RhRM-BX*JKp*Xe6%DJ&~0aeVoiw?*A z{nOJ^)3v3OLc1mwHrU=ONgp6SNJ)9Pkoinb3)x!cE>uT6=Z%xwNJ>Zu&m>l7@`v2_ zo177$*hMjUrMGJ%8GK^&z{X5ILjA4R8j$^bC~G2aNB+?9nT%ky()TMV2D;rDx?dY@ z6zSchM;NQlN_{=IXI+UG`^^`XN`R_u+UV+{r#&3Y;}UAG&vNyGWp7@dx2uUs*UEIq zLV-yiW;)*S*k!f{fv>?QmMB+1mnwYD9{=>AH&^3pqk%r7bW&Pw?s2z9`+|ewGYTJ2 z{b`I;C_kPXWP$_)M9Rw_UO9gJxMy)?>G)N{@p?p~FAsy&HrwdRo_KWQII4EkId8s{ zIWJFbs&ls zEBDf$e8;cMsgG_)H-y|aTWegXGuxO!2B-p1EOLPXdMGKk#23mjGa*!%Zq4iGB+*(c zjbUv}a#{9lf^Sv5cNM17y<)gw5=&_AyIqt4#hHGg4798w{gy_MMR=b{Zth@vqH~hu;&=pOT)gZs|LLbu^ZDHGnkE)z|VF4 z;L9}__DskhT=m~=GH!A`M$$yLC0b&__w*i_noEpQ-Djny4jx6-PH~zG5d_U9s}oSi z99OA)Am|cA&!!?xa*{YgB(N;llGJIsJ9UCPZ!wG+Gge<;uV`|sjUeb#qDBYX)CDu_ z*o=JYo27Eec)9GT%*?}nue`!lvuBCp4KK=*p&m?(${3^QPi&Jq$6VlzGH-JKMojqS zP#I`AFV|>yUW#&gzS;CbAY#gX=o4h+=Iw`YJ5+cR!K zcfF#jIn7TUPZuLKPrgm)L2AyfsDmO-I)6jrH~RO4LJapD{EB*Wjr6Z$n#C0`UHKc? z2myOQ?H=tY3;`Xx9eyT znv07InAyJCVMSSyL?J95OixZm_QuF4(P-tI)AjZGn+oVM@U5OV_t?g3qB0h0uXbtY z&6SD7NoOzDO2kNR90H6Qv|BW|7R|*&R#TGhDKl~ogT5;(OLimDWy)!E?HJ68>`V{j=jb1zh1ASIY>i>63u`=)1xnNUCqYA*HY z&iwXJZmG<1c~|M+0T;pJHjjtN%&uhD?2@59cpl~V>fAnpvo-qqeRaDo9^frtp`g(_ z?ooP@)h2D3BQqjGZNX+~LR+S#>GTP+K|AGyn4>KO{k&9xm})f+OeG!n+S0lBoO$u* zt#O*6Zl|K?KHlv-YbM$LO8k+3SJM}9u0z8+I+QXA4w9p47nt3j$Zp*4nen@fdgnJ~ z)$Z+48M;fZ?WC1?c+|Lj7JG_u$Gl8j-ugGj_cS}Fd(ySXQ^R-WJV6D;#8fS$#v6|e z#b=NDXlr#Osftq{;$w?C?JZEmLSgG8B7`y*pZ!2opj1xawsHPo7bIFCSg7Y_ zCXuEPmnM2uF>)Jff82V}(gixw8)QL8Nn9#vILDk-4+9SS?Th>MHjSRF5xu1If!)~# zGyTtR9L=Z~p#tTmalUfoeQF~=hz zQSqKo+M|E&sp$R|$1K;8WA&A{#=?q&?(8!iL8Duo%{%hH4$Zoe@~Ds%PA;Pbct4)a zQ_9};8^2B8jBR;{#Vbb>qm`QLbF1-r=&#w+>uRV7W)R% za4cgiBg@@=c6@uYvOC`7>wEuyAubb!1BK`B2I)*2aJ8@Ijkr&yILJ_UUF54md(+MJ7W{Mt{`a8hQyNK;(oHq0nvB2e0&9;%ba`mT$7)s(O!{- zj6d<_tEs(1pCUKnyuwAJj@C2Or;+rNkW6>-a8X9Sf2+uX5^hpFM53R!I5=yWzgntb zGFPR5n%%|ja=X3R>$}M4D^1pUQLEyESv`gwd`mPO7fDOzNJ_#u2jwTq*kz6=qW%Qk&nqU-^UQd1_w8EHMfWI z`}l-8E^~DD^f)*=>a(+31=9PVU?&an0 zJ7CAxZ7)(sQ{8d+W`L8J$ayAf*DIQoiZ^&^xK&+5JnTFLMQKT_*#z8pPtlwn-cQ^- zP+C!ut7Eo)3bS`vVHd%!qsKlsSM?veGA1B(K*@t)^n8_{wZPrIG;}nAfi3&5PtQq_ z5r-;foUHF`{PtX1)7?{_IqaO|`I|;YSB<%}ZQSc#?%hFZu1hWY=xD_@)O6PR7}W*; z&Z(t0l;k8qk>ufLA`&oBQzEADEE#qc;aZ!wR@y5|iJG;pGsF5+rE6iz!tXH4ovva7 zeC|^N=lKs2RvDD2BwmpP$@N7epYrIY_sXcouAW9K&EPRFU*Gcneo99wZbz&u9oP+p z%5#UDYHMj~Dl0>;UAS$T$oZU&qLt#5HI4MHFKlzH+s`VCioIpBFyGV8tEI5h@52T! zRYJwa^YZrXI*;#|yEh)9ILQ{oQpH&P$b;)1pN3n*s#i3P5?6fb+Z(Z$8;^X`&|YDh zn0^u?8C&K;E0Uh!gAL-AJ0$Xr_bc+BbVWTm9|W)kR(2yLY_;I$lT72B^fE zH&a)>lyb3Ca0wD4FFiSVJ~uidljvdFLFt@rUk3K=cRWa{xSe1h2lXLdYAs8GGu8r* zV%57V&+9)D*E>h4D9jie9OqbD@P6c6sNVB7a8B+!;Y7;Y-fJ%eWIh?^DxzU^qI*n5 z!aFKjxHMRT+)f>uEuLAi5PO?zv{Gh@O%61fp231k%$HEfV;9K$>QK~hum%dIYa@a3 zX}Sy-@9s;KA_Pp`s&RktsO;RUhXyh%$xqB{QuejA^a)}|Hu@F_3Nl?-%D`DvR(5Y_ zykUs*%_99h2miqaDYx?QaF@Zwj6Gid%2R?j)r0RobD=rlqGCvIEkv*K*6m85Tt}T} zq4=mJElQkhoR^w`^OK*l%d6-1k47c)h~b=hG6?;d3!&j~%&jC823PX(10P>3nc}yvQ|l z#c2c^C1UdJ73!Aw87T9YWh}MISQ;4j6Df2hsa9?H`uGOZ>G6fIj@yh-ugtfsOs1ve z29ls6uChENqL&4iEjz-t(+DvP&T+19km~gJ-&kB(`4Hv(EWj)9!cs$nm6^It8l7&G zgJ_tY;CULsSuyh8N+c&L*XU;533-oD?Dac+hWO03^jnAgCmxP;h@W5-JX(|&=NMNe zaqeN%LAex*^Kx0l(a}Zhv3}tU)<<{_5R+d=Wj-=jwR7{S+rep${&G`#Phxsh^jjTH zG6@M*RxU?{>&xwR*l&P64+A^l3)GY2r~|K!7elC~GS+O4PWL1&z4y)KVs>E|xWpK6 zFn9DokEaN+n5TPw#!R2^D*qch0nBvw59W6_>U6X?Dz;9o*t8ZckOXa zYQq8nb*_+_rG~(EgTU-5=EifT%M}LNIEkh*p+!!+znW`}RF? z-S4tz)$%<}h?h;0&O55GZ5N`yCcoQ*S)sS3r^lqG8C)41%FP{<;B9zKgfi$eS)q;3 z$F5V!fgN{npAfL7?D;?|dxDGMowotu4gHpg%g9(6V8v5`-ZW7XW>4ObWb5a?rAy~_ zz}PM?*v;KP&Ba2wdvR&uqHEK)H+Kvr1(KRiR)yYo=~tsTn|K&~ERT!vomTwIK;~ih z-Nb4mBUXe*DO7la!V3yS7@iICP6>?%w;C3eD>tkuN8B#owR@M>P0O1;0qjpX_rJZp zu%AqW=}CBCm;eDG!!%MoOHdTnOE8~xxTD`ifaV5Ikos8HrJn-Q-m+`7j z-x?v|*ftcprpG`5lcm{pB4gO)jwBCR$q+}!*pr(5B>ls2>-SJPGHX+sYej+CVwAir zmkyRrKU^OC8WC8Ay-8X!yy_LT;%{%eE~3=a?3X6bBXfq~vvATwqur{`;@Gt}hr5T1&cCRdx}|Y3r#a*t3M$^^7Pt?8Gj#6J>94EhfW-BIPcnIW5e=5qB2G1+=C~L zoq;;l9|t9M5^piRzNPTQlvek+xp_3bRFaBdWK8k`NmbIDm8mX+L1Su?j@Q)awmhw_ zG%Bs`l&GpCF=^wh`);)rq^Pb@HKrIY#;?n-$n!7oo{yq?Fm(!tu*X_jj`L4>Xh0za{)k`*AV-*3b=?yCqH{ z!hTmcu4(w6xEd?ya`)zdXta@Y#eK4u7YQN?Jiq9CuC}6!8uMw^(_sn{*n8#bRg7kA z>?NI(>&w$UM#shs3+gZLM44@*n;9)kq-kyp*nD8tO69zLD){Cl`y{{c3vTH;EfL=B z<}bO-P7)ic+erBh4OiZ{wosjHs9JaKP#~w~*W%*sbsv>SeJT%Y#!`RVD;>T^@Rqrt zC>7Fp9&=o{9=mSLwU>feLr;G8TKrB1^-~#jr!R?^cd2$hv5!02|MsQ} zjjpclo35@$+Na!hP50(*RAf#b=Tsx;2O3!3vX5q$sbPc7&YJGQcXYa5;nIbj7RU6s z9`--8_!g)~FdF^g*+7JqqPjZCRs9^R<5%SiX2;2#92{ufi^~^(izpkpC~N2;D5PGR zZmBO7^;`a-fzdO~VOAO420|9LU9b1=TNE3UC+`-LQx4l0CL$0dBH%Z-l@g&CXbl(vS6eUQfbC-7qYNLSE~0 z*K`E@hLz3Zp+0&{>ByN~$FIDP2s9<3Tfg@%^Q&O-HDmUM7H)yIZ{cd0G=i~rZ#gH< zzg3{Rcwu)^FVTDR(h-lR=a1RbwTtTNuePrmYA6{OMbMM)v@MF-uRdVNl*xMBx=Z%6 zsm0!&z?V0uUjFNpd6|B;LruLWi?MNpj{)q884JQ zpGoV-a>cx4qHRmPElxO-w|-T^jG&!Q?Cd3DC8fP}*H;MjXI^h}y&x_*I9zFk^qXrLf*6kMur5xsDSv%q{vj9H@Lr1!cdm((^m6pABm@E5j{xk(Vk)0cx`TuL`aaCB?THQ^Eh8M8gym}6(co)zr~GOV;x?yCu5_tgO2{~ zxoVff$HHF^@@W^P8^ud`vR}U*eI{Lqjj*}4BxVQp^5{isVz#h)GV8!snY2fqt0ZQa zKGj#(QF$Z8q1V*Z-cH6Zc}%r$#{~Cq{Jd7U#XjPfg**k)Hyb%*wyD?!CnsNM?{0iq z8eD8^VDI4I5O9uK=N_s+_)^dQH!D~B)^e+u`;vAtu$875wiNBA4w=6&dJi2oF@Cw2 zn?O-V=TIHj!m)LdbxL11zb;qK0I&4mQ); z_GQLIuP)pyS347u`1Bej8F6IaOqH%)EwibQ_QutX9V!F69A(XzX&@c`{Br?v2Ou z_C|H=mvt3GEYA(bdz_ zOG!;-G+Q084J2Vf)GZ5QcA*e#JhGk{`%rey3~h?Ml{6hA58OHb_%Z>v04w^d$Nf3O zV^ToAG{8b=l19jZ|fyU*L~5H!n57t+x>=)-iD^u z#=UO_E9nBQdp-)}oFVA{pnx7EP1ovK2Y)2*fSCWR>)ZW(x}EX9QzB$F4`Naczoc_t zb~q?+NPr>22$Y39S!@$2m)S)n!I75oCX1bUyBLY}sEhH32C)fQ^(Kip--g%QP+zSr zP~@o=L3>KN*r|3T+z^w_^N!jMWS63%NaV?IZ`S?eJ2q^4t>V^kAC}&OZ{N|c@5|L&x#$s zD13NPZS7Z;smqm`6TdfAnUv7JQd2N@t+}9JwUBSot@O1r3#E#D;3fAn)vwfVWjrI$ zqIv9d==?*D+NAR=yp+3a1;v${S~D{{dT-k9rrM?mEQ|fMS7#>krq?H^q|zUo*gkud zkP&$Z>&IaxxvF`T$#rl-XRYIPU&p$3Zmx;p+K8N&L(O)~Fi-btWnImQrg^y(6^7?- zG*6qEvL&bvMn;%Z8q(OMyWaJuOT^GPYwtejyS1Hx3+IuUNiCe=ygwp4!`EL{m z@2kl26IU%GyAeuz>e59HdDHRPf#V?|A*T(0`?Rg@3JRQxhBIjYzRa1%JIuLka!FC| zQ@IyJ{a&NLx_EunWFOg{a6aJddcjG~@{b|q31*0V$zq1UG0sD!B2@dIUyL`?ToF5> zL?IN7mNb!Vr>5RRDC|;yw({hQ9M4?#i>6W!Rq`J$Jq;FRiHH(xeLhUHZ9%3ilmBV< zh^LCU-8K~O_Rh}Ex55LnoeIdjXO~`;4_8-czci`2*=o^2?6>(UrVZz4b$#mt0~9Gd zf)eMRuVlAO-nLmyF6L&`(F)Trv$#pRd#Iw}rof>qA~_isgs6<&Vs~F!m1LF^BD7b1 zfK3u)3R^7bc8$ems|wjYTzs7w8YC2_d2-|7`o_r1--P50!uapLAHF5ZOHCk3yS?Uw zlfw1hF|!xCt31^)l_#VZY1R$BJVDrg56z?bWL}aN{Njgv5f;))5Qd@ zx}Qk*nP5ye3(KF$)9}diY&pQnK)`3!o=Uo3`j%^3#M=7$QT?3(*Vqrv7RE#di$)R< zmkJD5aYK~;%NXmGmv6f%WwshxS`+dZ?zb)Adb525%aDd*p~^Yrnk)D=_~CkLBHF{t0<^xHvruTGqaRqD`h zUUx`FNse63JV!u4=4fL>a)jKL`Lh0G`yJp!ys7qKH>b>k0;br>49(4<*{N%N+~naQ zJ&En842fkukF_*wg;1-$0^t2&WoIMP@|Ii-zWu55)z#*uLgzHywU>q$Q?+K=NE<0! zKGBm!NAEv!NTcI=y_pKfvBvAstxriQK0fI8q93pDi_aZBak=f7fOcH?7!4i^aEGc$ zI^CJfqSfPo0t=M33ma*s#gP zK3ZBwiOK9z)A;T+_l=!m!*ooV&4Ua;82kTcAMgzjuHy{bqJTK#CT8#$hqI^2a^!fhrHuEb;sD0+YGxlW`Gi4 z;-E?xN6l6`nP@DyKa|rGxqaLAiMM3HtfvCT-}{kuiNc$aF>n2Q9?u3==adg!zDS|v zeQiD2_S5_V^Rwr<@~JVYzhMPR8U$_KyhB4Lhog+=-8USB@@2@Wh5V^%c_;al?khsrKR}FH@)Vllv)D&)(>wb{-|3&m~&x zJoiGnx_@sv4|T@2__hy>b@RRwPd+xg zA<2y`*(Y+uhSiS$^GQI9PFn;w#;(Rw3!Ct{qMw>aB8FRb;j@3Xl!a$ zu)C1|ec{31tnMA`#H_Vgv2_Y&vF+sa@jV?I9X^mb7GQLOM=9~H1wWCwlgXsAr);9? z#3h-oM;EL1nx8gK*X>YEAN9=~|EhuVW*TO_a^-ztuxr9Q9(0u2*b*s~hvaj4k!+gN z_07bYQ4FQcK{*PUjafz`R!MtVBEtjZ!}>)XoN|0-_7l;&5ws|+#5DGuKX_YIUFLGa z*_Q}yJn8uZwrxo?bzkSo{F}r{n;p}53MN)Ui*2^mwW#nnoQW;5KB{v`fh@S+W1Fz} z9x~$A-Mc9!C%9kFa~@!LV3>&F!C?9}a<$|760oOgH3yhi5}GnQrm0b6H`rcayvv*! z1_HhOiVAqR&z}mK={WkK7df3ICYkI1o;*LAcWM&#SkG3$&t;jEFZc|)RLbNmoJkUuFLAQwnl$1VA4{M(-5f~ZcfirX52Gt@canc zipPPE=Vswcn@1+ix3TYuKSc%s9YyZ8Ijd8zkyvkh(#^u~@H9p03Kc;@s~%^XbM={1 zU*4T*6O{hWKc#=tc)`*-0vfI@+79W{7mnBwX?~j;9Tuo7}kKdgj;%>Hqh1bEauL0;& z=TbMobn3+BLdubak51^CGKZtui9_GQqBZWMFA7GSaemfcvF*IpV?#sAhLUUV;$$Lb zGMT5ZULK#C+xFCpwSw3D;-zfxC#5yeLK@{l&o>^LkztrEp{eG)5-+fOg_ zV)uxllTdB&UgsE(asrIl;Wltodu>^iXSHTd&1qY5$e63|i+D%~ zDe&GqeX_|UOm*9}21G=(XX^7dt%UQtc*D-dR5`o&m>(ZeYl;JU#Ubz~vOm(&1ekDf ztuzHDpNJQE?yeH)_Eu-tkzE!SIYJc=hYd-Ye^WL(8zo|UHvQpIwVTn`Za1&WR!z<5 z@4jD{>9OAH?I)h8?EWU4k~)ck>k_GwkD?oos{NM;x+D5@O14E+9vtf?ru-i6ITsz> z9;o}ZSidX`p54*Swr7{EcZt--X(z6AVsoFcooy5->^d_t&*;mcl~pydwC4srS=40x zbZpL!>%?C@x+_B+8yfDL6ATWUb1gd<)$HOmx%1$+6JNyUFvMaq=iY_yr&GOOXmvhq zchr%lvt7F$9DMfSY~4p3u?lCEyxsQjxly)S@7G{Bcul(GG^&_5(CO{oY_=3nvCA)B z@?1Z#NTvDondZWVF}s|B*gGNZB%P<_nU(y{TrW+no#LgYB-1TZP7KD7?wSSiX{&c?>KN40Y1(sSjtccVu98c^8r5GoTST-cZE z6TQ&c{s=Z%hFY5^OEe#|PQE3&&~)J)-6)T$;N4y%Br#(a-%9i0$2-P(9SpNs}2Q?$o@OprLv2t~M=W#+}5DmIJ|& zt=mTQ9b0U^1PCTNyc~OAFBiX@UN`L1Q=8j3rW5|S>@w30^5FkR(^ZB=^?ltt!vI4M zAth4MNVjweBHbt{DM&~+LxUhG-3W*vjUZhrAl=f<(A_cf&hP&`@8|h)=bn4cUVH7e z*4cxNl`dw%JV{A1_!@3bIwMscTXmc4UDp)S~qS z=CK~q7v~ciEF{r<&qle>W6|rrBjjNuPy6+nI8*fOFS?4YgkLEHL-ZD9ijCH;su~(# zRX}HAx>Ne$O)X#Uv8My=+R(oTqavFMuBQDUp^940cV;H9E7%Fyeus5ryQCNte{`<; zgK2P>JzVt2yLd)-2r(rUX@8V6FRTJ^ciP(U=jr^*gh#@x3p?`StF~$1qG#&=mmrv`irS!f>+ZYeE+x5^3bq6jf*@JfFv+1yiZ_%Kn|pQi2@lc)v|%dM&q&J+s+@w(vX;)tfv)hr6RMz- zkDQfIw4m+$>LD2T38QK>oNN!kYa77pp+WlQDSLytcbf-tC`xj)z)mguA@h>?h zq)a8)vmdx->rpW}!K4eS-Mo$_?fp{YBf99jGE509UH=hTnqC^KNqj>NP2muhQwf&IJkVH%D=-o=;AdI^~ygKFyB+mIXG_n&B=RTG1e`Ut!*og%k z0+7eh+WGf7S#QYoFV5YUJ?9-8!N=?PU!D$=0rkZuCLI*G;rpI%K0nGgX1`k|fQ(c0 z>a4bxykks^lGT2+vXS7kOFUHpg&$F z6@324t4d+RV^&-vwQC6q6wubs_y25>QRKbJ+8~lkP4{^GlL8BWb-jM}g9D!U2rRVe zwajys(bP!2as#vW59@yhK;Gm}faxkT)M09BDm+CS#i>~BFVyQ(@UDv@q^BMqYBB57 zLE*JKhJjryJoKuqSQm9$8ei87{=C@30Wk5}ymK~w9Kk1IQnp8#r2YZr9vQ?A@>W?-V{n~J~qfVnG2&=O#9B( zZtGP~m_tp)Par9dGC`kys~VvgJeFAh7DArA`f2xYyC+vL%Ard|srv}H|AVe`WYG$~ zKdo)=tq-V7wI96Zo~y&E$0PTcd%w=9OCZbHF^mxluF#GwD*99EPf?6E za8d~6&);K@dxlp)1B?(Mv#TA)yCv;6k5;A$oq7yvODh! zds-5+TvxaZFIhJl#P~_Cm;3kE&FlQe~=skl@~QOd#6tC zKnSI1T8n!Q3a5q#K;O_BJTnVC$rN%B29MgKMd}r1s4VnQ*~*9<@WtB5I}7l<(8wZ6 zwU*Pej#7}rM{d|Q=kYP?4(&SA(a4G5mIE_pRc!{;5PN@B3tiJVo-devwcp#1wa>24 zHz+CepJVaz;0$xAzu4F$afxg?;Kh)!Fe0CupO=_#hCuYiL2^StRpQB|RkLA{@?shq9(V#lTQTK2bpHt7tjAJ6*yAbS|@ebC~XZ3q3 z%AqY}>bf0fgtaX;?#$N)m?u_hK>Y&sP8P;r%MA3{4b*(i6QgW87;=P!h=nh)Q#knp z2%wl|ILW8!U5_wTX&Lo&m5Cn#TpjqTB|BUF5m*VOyI=WD@aa>U^+PlE*PAMH>^!#xHl&{A6;^Z%RhSkUZ?2 z9Fxbf9htuq?erl2^`zkU45Q;4pQs{2sFN)Zf5XoZCWu{U{L1{2rN-`S*jh<=Q=TMr z@7%k@c)DCz6#K*u+J<3lmQ4bI zz~3|JL4n}k5}>|SNcP`Pj?@XU{5%jP1Fx%(|IL+Z9cC(fgfQSj<@$?rlmE6?Q!!z) zKd>`hu7xMk4$1D{zv0PsID>*-;E=^*?HTgWEjJ~jYy4Su!Lr$}b^5Sw)Z<3@Z7U-C z9f#@!R%rjrbor;Fes}qF;vh?N*z|e5+FKRvgMkcEu!9YGJ{eMENxQD6HiGw0$F*KU z2#LP!O*=JK$k9C)WEt6z`DEg`WZWzr63S$){n3h~Td;h3p-8t-Q^z@IpvJ&-r)A?~ zdAA(wwK0ZE8EW>b$s}TYG5Xz$CGpUos?r#}w zse{4HM*5PYK~LkEwL;JZB&sZz`Q6BGY70uunJUF&$Hpl#O%~+NvU#qQqb;Bfrv1cN z9B<(93|E{xf3f!7FE=ptq`Xo^laPnUP|!^XZpYJ+=mW#aUHj9lKs?C_?A(30TxRbH5y{QShHCW7={GqQH z>>6=dQ~j*k9O&{|aB9Sm*1)>(ruXvfbek zX=oQtTqie;@0KY%_Yr5M!+X19*WoT%;}}XS&NQ;-XSF^f>{!W&5-E;a$V)wo!zEj0 zCH4MKcrYYB5wAG5Aq`@WJ`?L8NzLwl`>5ao6+pWxzJ%RWF~qIX)G3P1_-ZtswrB7v z$WUA$zXr5Q)Y|AP{F8_V~pKV?ny6c*XfZ||*3`qR%k@TO|^v5bB znO|+Fv2p{P;#39)KeqL;2j{hay6HYjHAvR6f000+=(V4Y-k|h3+ZxZ|_gNp`s&*3OV^in5eoi$rPw{2f zN3m|o%A~tD9U6w;f3)Jb(V4t9YF7Pq8-q)d3GsRt7~~-W@zo5TX`XMlqaQ z_PR+j%XMaE8dc8=ACTZ*5(u8tNlCn*>{kv@cQ*%78NMI$!0T!}Qd9D~D;pjjPGL)a ztVsg==hqM;!)^Gd7%kO{+TEuJTeJdOMdDFRg*AM?J2c@6<~7 zrYHB)Pbj?JA`6t<1_HIvyVu$~JzSfD+S=|T>;1a8X?;2)RanCNjSiO)T=yC9&z9EW zL3pb2ub_T3PiFBInk)c@E9*?`VIa*-jVxEGKmGDKd?}`}6s;-ogUFIBvqX+5`R#W9 zK?EaTzY_ayn?L8{zq@*NHv`g2+c_Q9^QE?(1TZ~C_d9_osS~TA;Q_bb`qxgaODqHA zLx&;--%Z0;4u0r7RP?`8U3AM^ROhaGl_JDvQHK(u`ZFQNz5?|uG;a2g6<>D3t(Xui!O*1{|K4e@I3%h2b zYVTSd?M&=RR!z!g;PWXDY{vpVm$7A6l;iNKj7`lp(RvosH`xQ;18>Y;_BX9O)p4h%P?#0Xi6j2hu3iQVI0lEmDZlT$Q+?2t4*R@5keyjUN~S8u1uHOrLRp z6m3D4;Prp4e6<2qSg45TDT*%rOHd$QwN_ zuXNvRtw3e@?)Ojljn@SDZ~vR-SZ^K6FU_7k5f{}@*Oc{u(aD9@Da2V5`lh6oHpFjG z2*MZJN-^R)+seAm+qF)H>qp@n_1s9jC)%$dLqWH_n)+2L%)fO(;H21D>_Gg7?V8LS zjcduHu-2k-;mmL}*BBcijua_v6fW!F#a9hDGc^flRM*E-fn+*$?|G}eIvXE z2#2psqxHx{`-)lGALA}BQ-I8v6QI(d(Q&>(KX0aGZc9l4vpgueL1{QZ6uTHg8;=V! zw?S|xXRw@UM)>xRP}_qOp_x)hZ1dHGA=9+&p0ql()B-xm2sE7WI#3NB5bi-mJZ5nJ z(kyJO&Oaeo@ZC6g#d(T*4BZLxZUvqvtBMMKIAw{@($St=#LtHYE8iCM;OeChQ*xEv zQt&Vg$2{vaQY-vcQ1Fx_+PzSD9X4Z?A2VHfaAKEvfI_(JEM%3J6givArkYD_CS8{0D2iRIe!#CJTme! zX=Ch(O_n(21{PFolUw>GuE(<@Ql24b=@xVPW(m#FiZk0iV^W@4?M6lQcb+FZCtf&@}s!NNaI-TTPj1*R+khJn9OzD zmBsy0M^s4bw2CgOaRKXMjXl64{xdQFmf?l{D=o7x;r2le z4p$wS?VK@%6)gmjd|wK58XDrS>c#Wqwnu%NN+?wsVhN36&A+;km-Ymo#Un|ynZO69 zL&uB9zHFSSJb$gxkXe}NicaCQZ)|Y)%~C{yIU#}NmN+W>kMy;&+OT}fImz{s3+Yx6 zQd2#`r2o!3Ga-#f{`d*HM4*e6+<9WJad@7RB`+4%$nbf{q9PkC#7geh0kxc ztj<_a7;Nxp*_mYEEv?Fk$z8{^&?XyZA`?svQ;W<{M<+e#*dq2}6Ty3`Gd%MlrL+;u5!Wha}zlrqi@JpdGFC!YoK_?V)@VJRTj#gX|vU5EW$iNibG)=lB+t&-ihb5x;1V&UJM16pjf zLgq?hR#Bg_R6-JY)%sqgP3vCd1>Mg?NuFhMQoPNUz;STh{Z1jmOg~B)D&aXN9^mV5 z>IqA_agss&%?k)?;(u)z+CxZvdiM}qSy|~Rq9N1uNQp7Am^NOCRIZbQYHlEA3xn(@ zuFo8*3a&!(>tA{`3+p$fx8@#KX1Oo&>5=Qp*Hu@%oyd2H6N7w!b`Gz8g=bjxStRC*}MJB;TOaNL>G0;XE{{&?B z2)ErNOJe!5ZwkvbApKiN1R=m1`64VunfDX_sPBD8`C=uVc-#q(f4@zUgCKg1iKZuY zJ!~E)G7T=FEVp|#CT-U4{GmZB0mAGVW={-eR$Fdf*rmNMBRH|AOm9a>9qY=Ie^b%eN8P3Dy>w2`y>#=fm?3o^*)7Q#Yo|{efv|RpOvO zo%DmNs|Lj)^4vr+D;T9xf`z^2b*;e(XlzM}N8z++}o!T;)bCO5oK$DK;c^>d9t z#EM-DJhU&+DB(xOy=herXMP{7pUGcjNwaQSp7zt*-CV!A9DlZOUN!W}cTztQXAN8a z!vqf3N;tvcB9CEaif%f`lra^ir;(7=Cp?p7d@L=qa&`B3C5h}a1~9-#jGjslft7`h zpADi$YU3m{B-!7ia`d(60YxntW-Q|Pn14GT*hrr48)L&=1GW|#DCQgI0zC*X9*3E4 zVPDNVl~Kb!%{_XWgFau@!L@ju-hL(SnVd+C@6qFX?c7AA?I$jGbX$=r+5BIL zUq|nP?H)=63BrfI8pW4KCcMPTY(+PvG&vbBRlb>57|V@(TBYDV?R9HUc52510`quQ zPP{|<@Q?#dq~#*-p#!xvs=WZ&o<*)h=*ClB3n@4pUf7o(3leba&dmFYD~S$c#cbT4 zdb(&=Pbs5YTah%P0w+pjN)MG!586MWo?WJBX&m9uGZGEpuC=P$McstXWq=zysMPYV zLo>q_d%ar2w!d`Lngo9C&dioO9VI?)x^Yvv7Vs1)*0kjF34F`QK9Iy_ymN*li{OZl zJw}9tDhn;uEIX9#zO%QtXTt%4OG*+LU$&o9xCQ-_#Llm-_;9=Y9tJChe6;sM5l>9O zPDHiXFeK9+0WtE@zJry}GY+BCLEE)29sUd48f}^a`4x|}4G>gUl=NjEx2y6L_IGR@ z>Tt2Zn!fteTQzE`=C|!fC9cAd*kIXhrTEzo*oc*|r`1ov);(5Z6JIOpSvx(nNL)Y| zKl|Q#emTJ1&=gW5zzQuEg3Hj4b~3#jqKAHXvvVe!U)|WGtS3f6D6W*s3{$aC)4+3j zt;@KvPy$3B$c@M6p;;DZ0Yuf-ZWra?7~d~5?{6%<+B4r9j0!RTRZcA5RAv6*c(!ni zNJm~?ndj0*j(RY~(}atO>Y{0>h9N+XJ}b3IL!Fp~ZxsT3WnVEgiE-Z`Ib5jBA(g=h zmSMvLemw&GGs#n}XGP!uiNx)n=%_FZ@I#Av|FDMfa=Ds%1KRY~adC`3 zE1C^5zsiL&ptAe32%!BqY5s3!Za9eA^3vY#$cucTqE!Fs?XP5X!H_@`ModIB;JjQh zR=q$2S|ERV|CwbH6I(GRr;n41W3NVBUDqx|c;?c-7D6c8k6^3{nw?4(olRAx>8xO|;r( zz1{b|3AdKk-J+m6XG0?6WEN5zmNYfWz&;{;(vxPJ9 zLAevsGgrf4-S9I`EPA1vp)o%6zYX)T7YuhgAB>W1bP{Eb>ik>@MH6{G+sEA%@RAp! zF4es8^-1KGJ`2D0AEYCe=C5{%8~T~lQ5VaMm)(RdJR4%2v$_KqePNy1S0^Q?=mvHVzidXmgSz@Ky*)X%QlTtcUq#N5|*fN;nw`g%4)ZfM#rlDa$XkHL00IZZ&N>IbINh<1&!*Ia{qO~6Z-hYZU*(PsP zzi`S%88^~@!T-z;LtE$RFfqkC8~_{Y7sK+>?qs*CUuIKmYgp-vJ;y#$|6A0v#U^ig zQX9L`C7=FqqA_y&CF;lXxm+HcV zLamHaUxDGz23#|P2jgXjm1q#H?7X1UQb2{BjT!#if+;ya%$Sl79tQm47EF|If!-!s zdXB$T(WKa9Wk>hHddd0p)02jEw1Em*yjN$~i3=^L?~8#_0--e>_cRI;A51In)gk$i z{1REUVF4W3L(le7I5yiPC6pn7`Q?j#V?gdb0J~AOwCGJ*m{jO}*^~`fl7(qQhb?wq zK0e?sVq2NqsAFMCkno10|F&mfQ^3il_-g7J=4qoAE^T~Irm1%uK#iaJ{;6pkQU5ZF zDxS_&;8&I!+?3dpple)`yGx4H3n>&CAkI0>TZ*Qo9V1$buTw<`PUSAT>hNkD-;5Sg z1I!A4>)GWP`VnME{|b5x!oE+6>Ig8YoJ<%XqNW*wCxF970MXGw<+UBfC6_lJJ>2+aI%Y*?$XHz~Yc##mD%LCHF$U;H_cZ9OVgSkszs21fO8+h9nWq*{d9%HFl=J z4?K1RN}+j%FnW3x*4Q(#*A95PyN@*gPA*nGvU*HX?1lkkx65liFM>rr%zE_s++cr) znFoecRKD?7SeZ0w&^%Eke_hTEQ`dR~`tgAYM12=OQ;CkAQYy|{~*iHW#syGl1vN6op7 zor>gD?yQXchGK~_X0}#$BoYOoqQ9V|*{`mXCF~!umXlp#gOqEEfM0~DXq`;dh)#YO zFk;m?@h<&~C4Hc@9TWby0+1j{1IO&?iMcJGH}XjGREzGTx&P`*ffSn0gnG$zE9^qT zv=alA4|VZqqcV$C(AD>;l?~k!3}q6AurBJa%Gs@*zS!)az%a6}kVmo6e|;O|`V4Z9 z0yh_K86A$c+PsU58OXS(9jIZl!~|?Vge%#=y^npxxU)6Ms*Q*3^%(~8(bg6=e0CBn z94s!s#gcu6R2dAVj-7CeNf!L{8DwTe#MQ#<33e&Hj`4NbyC-IUjw=^=Eho!qh*Icd}c)=t^8v%@ zn6$N!enfa*kX?XY$#wP{sStOp_h2|vu(u>V60oBOsBuFeae)dAnv+c+b8g4H8Mati zN)~Sp%w;j#g4M-Fn#NaKM$<73Jg6ssr0;H$ml)U}z)P&e(q9=a*|;Bq;X25V_yyTHJhF3x&LCdpxdA;@=GDr#wgKG*w z6*2QNKsb>O{9KW?b-#}|4#ZN3xcF=`a0kP9@zDd9QIEZXchg5@xYYQCXLl%G6jhke z>qM``kcF7XiPxKL`9i>NQuJNJ-d3xLlG<80hyWL#OEug|aRyN+F>?t#8T9k!Ck)Jj z_&)h^1q>v+>5#2m7JD$>uowM8zO{{=lNHB(ntz55htCuIjeaJ7d560gvbP7d6GrIE z$4{qzK`J|rnA(YZ21D+DH*0l)oIbfmKEQ6U&WeSta+!CZzdpR?_qWaSk>gg|qd$B<-!uf{6olap~M6rj3t$ZtL`XbBIyQhg`<^u)y`MBMgZLnh>N?*^PaNgE5*j z*G}K(GVH>$48%2l<^%rW%Rzz9Bvs2qoYk6<@Tad!aF%ydgg*H1MBaAkupcXsNMvAX zeC-l2IyNSh)8pbANq?FZ)=U>BQ%cR)xDd7-Ddp159X+`ab}8OrUqck=ddNA9sm#X2 zWK`IiZ})Pn=@90c7NDULp4W_uBePDRiimEC2&K*}aT_)<(^O$KUNMjHY5x#$h8Ls7 z2zI)nDEi#Jyr3Gs!nzmm8q!b*M-5TXJRs6p22VZ=)F^+m9v+%X&Mzb#3$y*rUmviE z$0|V~?LEtEhm462aoBz7tpQ?zNF+kjN)^Oxxo_A*fDdrc2T6qfKNk$hckboa!~ll? z5XzV0=7d)lv)4q}ZS4j7T!viJxs>HgmUSUye0kjXLwi{9Wt&C7kk?n`Ro;*^WB+q% z*2FL|J|ih^2T-pZ)5nIY0325XMBz_~p}bqskTf&j?!QU#3lKo{ZYc!zS9J^K57%D% zOYyWQsX~Jj{RGz}qV7GT2rHn(VncPJz9YT45aje%_Ty+0O1n4h%jnUFC&abo>$Nvi@R;z6e=xC=rE*D8eKsP0$T3Hr_?5AV6Z*ZW9&-!(wbeCfmKDnTq z?7Fj#0LXZO(Fmv;#hRY^V%Xo}uMR=p2K}r!HMtqo++8 zJk1Up;_L49fky!; z+2^4*anIfli`j|BUbZ+@&7PZDuiL1i)`=WEE2y3Qq|slW)uvcBBt}*ytrTq*3gJ_y zT<5-Vdye{RB3NIRm!DsXlfUzPe8=5J9q2LvE zkPoUe`qh5(%B0*zRtZV#R35Vd#nRJ_|s>+h#gFy2#AelkY?IS7f{< zkfjpA6#Wx9B%K$etbKxRR3-#-)xJ&ugJl3L=66zaiFL)G^lm=MAO1zeuB@IReMc#v>Zrs-#O3`t-M~bd~*xZ{nV^bhKR4)Pq-|x{nI>s^rf{ zq_peYVo)1q1x~YAnjim}EQ4cu9Zs8EZCU5qFPUM{Z}}Xk2S9yY;K1q8r9(co7vG~Y z-dtvPn{eza7JOxf%i!6BmX-N(WT;~BmVsr0f`a5`F6uE0i=I*BCwYy%e8`cWkg%U! zWtN{{5RD|mNmh1v?EZ(QO=Wk_rM_j;S<3O^xV-Bx^3ceO<+z{|hM#^HXs9DexYUxu87d?{&pi|7yGIaLe+*(ccv6Gk^=eoAy zD-+d%eXaAOZzop#?*sr{2z+*S7Cqt>0Az4}yzxpTxeFcCxYOwk1)3|33OZ%rf|u?( z$$U=Jj_@AmgzS*M7H7pCKc@0ze;o*>i?4pa7FX?!rZ05pbcS+(&pU0+uwBdx{ff6HLSDyo!<( zD=wZLN3CvSfp-)R`rAnXtBU23C~*BxO+CTDI$E_CWux4AHsF~HsY6rEq z%lFt0hjLsCphW2N!{)`ZoRyf7?G5m#Xz0SC_1{`mkHu&nl38>ppj z=V0`sK@vnjWneh^OH)E0JCs1hJu{|KUJOzP_PXeyn9YVVViO91i8^93e8x4I`~=_a zuIj0C$7v2cH!1gXR+G}D_c+49tBnqK>hzkZDj~s@AKhDAOOdZ-c6`Sp-Lwlk8!!!Il|sk66@lZp`cZ`=JDg7RA5X5O=cM=R{n5@p?%AyGM&ZH1ZhH@ zi6FaPt|ym7Jvbldxaq4&`&}-h2CUua^pQdYLwWb2V2X}nn_k%6w3o#>5zSJfGJ8qK zgCu2WkI;?%+DZOFT$Rk>J}~$@k(mvk%@{&s>8#>_rn=C~iQ zsY{Rj%>rUe=X^v7{ORqDtegFgCH{EyCVV<={3BsU;SiCCxCwo z&xgg{2&?LBJG%g|5}X3ImGdXgc9iM&PJTfc~sVp1CtBb*oy?_}A3JRq8UxPub1~ z1?Y7NjJ4?TF|=O^Fdq41HzRK%w@tjHGm-ZiaT&)BEm!7Stf*RGw<>>CvT?e;!s`@q zMSnIapfvd_Oqs+`BJP`bhminJ`{elhn#WaFVG&p!T?G&f8-x$yrK$+K<@c3I&WjGc z;U4z*8-#q6zCubUUqt`6Z!dv5;4im1vqmi6llUWjbjdQWwl~xIN;+diYwU!gkW313 zEB%PuMY&P@O4-f1N_l^oXktCM75ex&Nqp}d(>U=lsfuhXt!4+EwhrkAv*dAw5dkV| zy4!1bHer4~PI9cziuYnuypxn2w!8|GK?A6A{lbfZAhWtw495|vL4Q;pd8)UrFP*=X zmDxY|Eb2;H=CI4ri{ z*v=_5@yr>LM0ZzN%JHK2PXwq)GYLbJ0Qhy?*LP^e-`~@fuc%B|N0kjWBZizF5rb8@ zv4=&ABCy5-kXakwOj>>(Qn=T6czzvY^F<=0-(yb_Lqip0{iR0#^PfCNI+lma>}M^@ zI-RB7{D3w32{$aBJnD0-_#p;S>zRDA47_5Bn@f{vGyR3yF@v@4lU&c_>Ljl_AScaa zW`9!s{iD{~mcdQ|7MlpGw=X9C_~PLt+Aus$s<5b;oS8+YI3NSe(7)B?fmM?lzuEdZ9L+|ix&|Vo51nSHQ=&6T5zJkKijLQ)iYv(r@2=A?0|5? z8?AL#(*Y%S`7Mbt!9JlgAxk4M92%3Zq@ps=*~YC;jO8X^t=n97$U(E|eag=>4UEVU zloZc|C9(ug@wa3s{UI%=YS#94*f=zGeL+T{Qw62>xO;1SfIGFxV$>fiUwl%kV-!6) z20GKH+#KGbvy)Vc|ClQRzghu6hC@pHuDM{3`DA>TL2B(7t9c?^>phA66$`ow=!eEI zOV;o0*D34Igll2L=b$JIB8%N}FY@}WRXu5J$M*_%GacyWb9(R!*0TP1rO9|GD_lE| zs19|Rrzz}IIcxhu`W&R-)PC|)2(}8-L=!+>8Dl?uQ_S=P-(KACL|m!tIc@2{5vssi zY}cqqY+M{6Mii*j+jZ(Nj*n0H^7Zo^Zf{aVCD`5JmLJA;3B`~}7_h1Ehik%23``iP zBDzw1O**xzerW{7edAejy5ZVl_wME$y=}}3KiZ$OelmQ&omb$r82H}zTnD$ZEWP>6 z=~%bfCU4gBj$+lQ{ro2{NC#S!fwP=7Ja!+PUsPt#kUafJQr;&?qh>fS^#Zex6}HLx z!J3~6ow`N`PLK(Qb{Yflw!5ni+W6kO@UV~`K*onM;qwLS2rE9j7(ufW5c|~qhWR)` z&Zfi(i$<(i5MLG5bH#h{!`U#_F}LBnre2tHD`-r*xx%J5DZm1Q1a(no`Mf&WyKU5T zIXHvvp~xnW-OHo!;F70_b&cjrv0GgINUvXI6Lq&$QVG=~+(1nRP!z2xAr45OqCL09 zaBzF?NE*rsHs^-^CvBU{Q)MA~O$e2;jWA<2lj*Wp&8D!UAjv3smjNolIm#5OUmp}m z826YQfe*$P1(`T>2thAXCI}19;<6H;8o;-MCKu0`a6XP0cJ&Z2 zm*qS=7obG0C?%jd!B^|U2HX2gahLNQ(59Ahn_hv3MLL<~M%1;{4DnlQ$|WC>f2yrE zbn~}OBb`?zKYG8r|04slPr$Fb&wiLQF|vzcrrbK|CW)|K@Hn*DW?|fH(Dm^0it>&U znbXKrmR$%?=ulD72C^qA{|jZDwfF)8RG#CuXnaq2rhxM~8{AVp2tS@OAaUmXHQu`Q zI_&?o0I>y2%yzU{cJFDD&8|8ANS{!lQ4tnF}tPbejkOz4g5t@t!^op+Y+$%^^oI+l{Jy`iT-3q5HmSOYitXQNq2lj_aZHANVF5ik@)8`GZ*AsxN zwO5b;`d`w0HL5c>0I<vCc^yiHE&=cfBSLcNI!hW&WeaO zX2DKpX|>H(Ps?`We(5mxxLwpvy-V#Y-yI$5Q^D0z#Ky?c57lx^n}0YakwFJdb`SF- z(_{%~z#jQm1ZfxwUyk1hAYy#DP8PaTMPWM2oqcs!mI(v(Q9d6``MNW}-P&2jPR*yL zU#JlN%7(mIP!B{5CM6~P8!R7r2~yUtLlI#E=-cf@VOhC>CQu84=nHZY3aalds~QJ^z$)k#qGI9xzZnx1xnoFAOgfqw<=s@ zxGGJ?m8u`~rGDSs0AVm*cLEx4XlUrueyiGLPvG<^7yx$0PEM9>-Nb`U5VWF8SvZPMb2He|gm zdt}O1!OB`HnC#DuD?>wX&QF@*j%AMTdZgXFJ6B#DTZR+f@gXPp&k8K*Y9W41`av{e z=?k-jTw;5Yt^Oi+BkrKvQTng(@IWv6 z$j42)hcyJ3S*I2_h8>cWiRIgM^LnN%Wyx3=drP~tRQUlx2cjR{-~RpU7i9j2-xc9J zGH)VIY$1*$OT>98;Ovvgq3P1RUoh->6r1*lg!WKYbSfb^IRyQ{YFui^*R6IwR}~3# zzWrANiSkj;qaP8LF!0*NbcyySzCIHZyN|YEqnMvr(P7Dl;b#x5QojEg5gFXO&bShdZ zpTL7zTQl@zzEcb%W#g%*_Gg(Vf_jSFY4TrYVmcKm#;p-;(L|1m9IxeQU4H@e5N{T2 z+QFRs_H}(8pi4BYQr?c*n*~o;0K<&~%hCmk7EqicL6lFwnAhPzd(e0UW>ncEg9C8o zJuq#=5gxy<6rMyOt_;sG?_<8kCHK`%z1ZJde$gu(IAAZv9Y<@JDgBVv=ji+B&*(96 zh8Yd`ok{42KRa`~<;%Mhk3La0Ysm)w?cGdi|C%&NEN8w=ttuZ`R`#zh2t^C@RL{X< zzF-1wGlz>EerGp`Ap4tI)4X@v$A5F57Ah1$Ag7NscC4rql_7#846o2^)xrEd$Ey!4 zckI7IctncLGw@$XpK8I3o?C=sE3{KZRfd+AVM3bG0Wc<;ioi<_+y_4QeByZQI@FEM zAQGYBVDmJKlvIf8{97@5Lcrk_W%C75g~RKZvlOOdUEB@m9#QGbYm)jrdBT*KT>1VSZYbge%v&hTFHb+G5(h^>V z1sqasPE-#AcPH{_0w9&dfsOn!j*!~eV*=+dIpqe_CtVB*-@-Z*jopVWVqTd5fgmxp6ft=vWwcTIV_nXq=f8e5t4B zcU}3z;CqimwP?w_OT3&TNnx*KMj;%V`1e=Tz#+O#>WDimw;Yg z4&UYDQCH!zn#VHas6K^3We)A0a-uo9@oSOx-{Vqw8(+?&ZXpTlhVudZ-$mvw44)y& z-QuWBlzN6l?9>hpf+q)`iBgaQ{}?rm?vj1}N(Yy5^146ySh(Uba3dm0cS~fxRBP=t z*Z%OWCOR6wfUKnQ$&>3Axsd6XXvY{DR8q1~FFmNwEi4Y%;6Hg@Ws5mE)88ZtuYX6s zIAxK0S3uOytID1>V8q^1nV%twTPv3^U?l_X8r?3fv7T?30XD>eFZuxe<>9{?2P=2? zrwE#e%1}2?QR!^OJH@d-ACQM&3@~Lxv^zgR7iH@}TCxxwGQX&l;}xE%27Xx;n&Hj1 ze1R6y?O^?=@cPD@)ep}YEKcLf=nIwc2$InodQaVFEwCbIzT6%VAW-v<+i+D{Uk3mZ z7Q9wEn|Hivd;$XJ`A><`P!sBE&mNWl=n~PD~&%+6lkE#po%qeYFfJ$@03iYXU#s` zx$9Tfu3lLDAuhe7;KZcS?#V#fK!)xgjzBlN_BAAeTP8hd#wSkoIi?)+_V$hx9nj|g zsFP`H^+B2hK&xi_tAor}KIrLnW#CK*s)Pj~Rr47Oae{RjL5sXVkHT4`l#ICk_Z6K? ztcqdq?jDm7zKr%vg3+91_Em=zV~=35`*TMElN#(b^6)m@Yee}&g{*jHC7LdOKi}XO zS@Q1A+y^yVgZ^XaZvJwv=jr;o7!16qE}6Y26VrW&1^SbI(R}s*xT`5WPpr4WK6g)^ zkVYaVCp`qZC=J`*$OLemri|RiWU$PkwuLK-TLzNVODwiaHcynaLNTUNR{d#rbV*>H zqkT~|J5vT`SiIo!JD#{l!12L+qw^C=8sibM(06v``^S=#9KisB=KJ4%RvXe$k0)|7 zW9LZegw&23In{Ep#Pth{wTmBpKRRIPdXGvG+25)jMzI5o1?)I7A^>CR_HCl|20EF+ zft$3Tc#Cb#S}K>}8cW2mJQ``tn=_**dr1HY{MTMpN8s{?ZtNRsKdIr)H5>{aF!nnB zGgNEn9A#$Qufgwn?bME)@A4kVn8Ru_e2dKkxLgnNtnqb79&t*Y@YV5Ar;tWN+$Z30 z7g3a`sBMFUxq97C>W7h{iIr?i4sz0}_Y2pI@Ib>Ks5L`0XsEW$3%G1T-)%a>0Kr$| z8ojxZ!j0-ZQJ29F05Aj9LDR?h06k}8ygi=8&uVJL#ob%^GfQ9ip24qb#gP|rx`!& z>6taR`(pPe0*+ko5B{&Hvw(`~iyHl%VSu4WLK+688$krAp`<$%N$FO)hYk^u?k+(A z2|_6cs-PxC^`-HtThQl#7(RSE+`R0I`i8TlbiY*dsLqwQ z|Ez8zgCxFGdF^P&xv;4X30qnfLE!e&-yOW?8{8z;Gn@hwZ&_lffsKYNJFw}0x1auP zRDlgZ5(|V~pzIR+_0i=;lDh978;&C!tpGoO1Pb;!1 zDJU)o&=@IJTTWlWRr6mx)0=4Uytj6?Y|RHl7`@7}P)rC`zbw*&ntJ697z6B+JO$&D z+`pP}-n-s6oOT_ zteZ&n-JI%MJ{~!5_6OJ@t!KNlBrV<-%f`Ijf*2`6#8&||08(4$SIzetnPeUV_rgg! z4B5{DEP20H$(`d%&6+|=OWwfWk}~!G7{Ra zYoQW1SsVIQog#vwQPZB#pajq&mMT4UDSCYO-lF}7Jyuxhqfhcn%W`yH-p-yEeEJLb zJEIwLTn)?z;0o`13MR&ngRNT_BjVr4L3{2c$0a6vWso8Y1$#G56O@a9iu3#%QXNBl zFgu83`60NcMF!Kn)P&heF=z$zr zLwvDd7wK{wZv+PXNV+Fvsn?=9Lhz~NBh*qx_2&R)?yF}GK|6=BsCjyIsY`abQ_ zkp(5^?Ka%@VRFWsp}#_w6zWwraE40%jh z`m`^D53N2MsYi$P<=?FbRGRK7$1e))D&gKLb2nl_7{c#3)ckDIO5ff+Da<_8bL$e+ z4)Bv0U`1qPT1{eWvJ#hp8?UN5`JamhffC~V{*hT)WA#+A=(XG3j6|{m1hGL+VRAn2 zv3T33y+sN5>7#z#AA;*+=?w{q*1Vx1hj%i!m|PMg%litdqcRxarHed5s@GuPa>NfI zNeMyHfuy6;<54n>-VKr#3(AgIsW|OnqLPX znANUsCt&+ig#$z;bY$^H)89=cG#3mnqHXaz>ibIl%&D2Eb-QxRzsn2*fV5_0q){0+ z`(CQh($bo?y^P$&NM5PX%!@s?GGfiCbb-nrei42nUp!`Q>lh@LcaYtjCPPidcX7fm z^*9I2jnc*ryee%o12l^QB`u@&DtsjymxvZt#>Xfdoc6^x8kWa)LSyuFV1CUr#?FLH z$(T&Aiv6ii%^;%2zi9gkOP@C2!>de#uRbit%FOZbaH-}(rKF!vDR6_{a*&NFdboSw z^e0O_yoIr11PAdKws(?(m>_c(YX=7iCZgfMmr4+y@1Py4&7#Z*RVsqHy=^ThfR45? z)7O&eV38;?yy{c)jI>eo@z|Gso*0I74!@?rSQ*3(Pv$l57NQ_2zq*gose+C?#gyU& z?=GS>j`QOnm9zz`5>K~9g7ZH?=DxJlw!F%r`?{u}*a|0<>I5 zG$s%tW*v-R6~=7H%`Ys(l!41|H>G&@u*lro8K6Yz{#FE|{AfcDtSCFwx$%Y__9rVY zj>tv*KXUFa`T*aiYQz#AFAfKFn9~&XwY{_nXz}G4R7?%nV-^M#RZBD_J8a$4v?DBV z@n-GWJ;subK3j|ZHw*wf=O3ws6mJxG_k{haz{>ml+^+hpO zW0U|&ON%5zX4Lujs`idVE4IgeV9yGJxF$Gluj<9pSMVQC<9CWI<{EpQPZowb>x;YQ z5Iye5|MP;ptIBBH9OSn}^Zg_7%Q$OEglk9MHTuBd3?^H+j8gx>BUX~n7X#FoGySnz zB`1(O9-`oIfsFYHkQp*F*J$2na3h}W_DRUTCyO7aL{n3yu#^_53ad z8(i{hxzgcSU`aF{FvwyvCqe%tBH8X-le*;H5Smqhpzq@XiE1_kW@+^o4#TjH0ITgu z*1UGZQxpImyriE?U(NXIy(|{bP1P*R~?)%YmYah9A(dVL3O+II28{%&s zu3EW!*jwp+8EY~SB+5_Iisgq}q5#js)nqw(qq@CfsfZ7iX?|%ve|T}ihP>C$<6H2Ecga`3k- zXST&^T6LK3xJ+2;lmJye0UQ$}mWo<_pjMB><=jZTK0u;`09up9qHfIUeJxi-X+7Ee zyZ%USktI`X{++!UZiSN{ZCYtC9{Md-eEO0gkiuLoc73TL|Juh(T+1IoIb%)rN%MR$ zUcBFU^YNAxm32kkb2L}D;^tRu_U#jsnAju;oeYJ4dl6*7B%KGfMCdu9YG2t5c`+<( z?KEONGD%@BDmJsWx0ey3fPIjW-*(f}a-7B=fd-Ca z6*qSt;6>FaDl8u9VDMd9L%^A|)_;M>B5jZ^)?ltUL|xBx_C~t^2*FWgbKjjy{qaAN zv}DVrMC04A8MpvV`plm&17C~Fw$sA8UnuT$!Zl7CBD{XduZJd>LW{*v07X&Y=SUox zM-OD$O-D=+Unh;_RzKT_S6XnSFg}ndJgr%Nw(%qs)vtPVczfv3o#?U1R4edw;LYPV zQ&%&BC25vAXK&XwR)*V@@$jSYlhBB*nZ{#&C(KqA`2-Vt-`AoSOTjI4G<5!?Ns|%~ zn(MX69y|aBxL8|TgB9s_H}vM&q#FUjv!9pRycpg^$qbD(yWuG24C zDi>TxnjgkfPMpHAaZC>oCj#bROep5`t`#-WZ=0(hr~`18p3($|WRnm8URtQxfTh;9 z@}VKT#)ig5i^!n&ngKv6iDX&RUO$Pm41&`o_{}?Cs8PivJ4n45Ei2C%P15DNY4^_3 z*4c{xij{x*yj{!ZB~#NM;NvF~G*9Dk*;QBeMGDKtsUr3{ef#&X6&;)>M-|LB<+Pi` zcVi97?~1d3=?Y_nCO*Gu4GD#j-)JTgD+rQ+k` z6GCjJhDA)sf_!UOX{KMTp@n-!p@%F0l+WXkj^QU?H;YZGp8oPDJotbX~PuO-P=`fe; zR_=6@vJEJO&&_P8E26lXQGm008;Z5-j8;VRd?DaoO=n;FEgyR`)P0W~N_S$+QjQ_|c~z?ZBgaS~NLl?Ejw+$Sj4Q?s6)dQqO;zTGPs-E(B6srdfa|Kh2i z{k-@K>b%`=BhGmQf!;-Wi+zwyGV{t{5+pd6A9#xbu$Tk~4Mp}8eA%8Hgeo%%^trtV zlS2-~>8L8B!;b&N?QNHby{pV70@J$UHUEA)#@uScQltCo1P?68eIu{aTJBfoKl(8M zJzmi;w#|gRKHKS7`%odJL8f%P-gsI+Gx}Ti0+S!r3X+zyeD;3$eH6R92*B{f(e>du zl`-Vlge`)(E#uF4E9<^~-3^L~iBWx-^yQ#Lzy4sowxtUe(V-BpM$LUiX%dbjyiP$) zD=nBVYv7aq)UV`gqU*djKhBk}ndi8j=%)eAzAQ0yD-4#vKkNAMKRCOk82%hywg_@J z-VVHz^GN=(N@_oI!S234^M>iur=K5tNBa#Ts5Jf4_ugS3@S|ORp7e7(Ci-e{ZXErM zTs^q?jzt6{pyzITo4HzVm>Bq67dkjNsKlB7zT)~P{%WwZ#4g1T}}1oO7p@Q=w6)@a9SD!=uYx|VH+v0pQvAwyYHQB z-quxX-A)AYEZ^=z$@#MU%VC?fAFvZq^5t zobID0=4ZD}!xW4bn=#S_o1C$=OrgQKKhP=+hr4u|-#Yj9tsrL(b zZQ!ZLO#LIJ%Kre;w2)QGdE`x@?oGQ?8{_=G=EFvx`0*8Y_d49FmtfC72}vt!@G2rV zxSmmy-!3%@t%PkiNmeAQs&rQ_hbB93EHRXs|IE=|a>k|SSbo-)N+`v8wmYBhchH8t zpPG{9P1EWQj0=U4`LjF*NKq!G{hW9sY)#ebvu7&TNqEXyux~<*=Xsgy06xaWfpVA@kZF#7=t5y z-KY2(g<*p=RNllu_|;VncED*Fc34=LzXRSqEJnjBTMHAw1tf%pg-clb?Ul5~3spXR zFhUv&%a>UP3@ROy`1D5%D6{4UL%Vh)71=<82i7%qtYQ)3gWw~?f%K8L!gwh8Na211 zX0yCZ^#1IyRgqPM0&A`ybqR)~1Exf-9fj7rl+8^u+Uy&=Y`{ol>}e%bIws$L>rXVHe?dT2RE~xUO)OT3fz}YB)ARF+V4WrYFcQ*j ziD@9mdAO&i=Q{qg_80IH{aaMTED=Hg4be3R5;WzW#4`Q+<5I&ZlM;}rf6{s@$@&8S z$f6J0I(Q-g_8klg%2Uw*w=ccRyf#fYnhhs^Jle@|BS-zNr<8rer~rlu)kmcmZ4ah{ zX`t-nDZjO&KjZ$LH~ez?Ccx6j_x#yL>2}3&h%`ef8~cB&%kg~t5dcsUDac4_^Ei28 zlEiCOIyp!l;1wD5d47&kcq7Mf6IR|jqJvO;TUnvz1tQ$(cB(@H@X(`OtT*o|fg^D` zH!wF9nW(Dv0;DfQy~u~e5iKR6(FU_3b~Rjx${UP{+*>6T%sOd#Qk_r?IID8Jsjn+O z$Vo$nMo4=qCd@0gRJzR+bCDD(Jj9pJ zPBHFQpv%cGa(6_smfrFf+t9CLR_v2}$h-O0X0hvUAainb@fny$D0_}qlu=^F9+!rJ zE@$I)BSXTliRcE!!A&+su(b5Ysk8u6bhCcNd0!=U6ELG&VRSo0y?7WSqL=0VD!f*M z6@FSzgI-ldJp)=5jty1hGR5Y+Ol{vvy3F3cY9UdV;;IgG5vUVf$*5g7>9XMfJtDa2 z`X72O|2g?{oZat``<|U<#$~(AkiwCiK1(d8X8G?Nh$u21Tcyccvuhevn-*7R))|#!(^BMdqedR4Dk_?qasL z=X}F87<)=z=Wut}#d*U5R@FjdqwJiV_Gg_M4!cGEd@*XuP{)lGg(GHRNJ4(}Ljk`} zkou>7wQYq%pUYJNR!k_zhl#X+shOE*{-Nh29C}|vhSxc4v1M1QE9^=A&hHhY#m_}~ z#U6(?8I5fmGsrV}F1B96XmtC_yD7#R!Wj8;ztwr3i2QpD^W>Sr1C;VH!7KC87pCl74J0lLmq5-mw{ z{?;V5ceBl_U;Y}TM8d#iedjAmyUME*9ncZW?ZYf0)Y+ZwNqkEr(XQ2auK7}@Fkmr!+pj^-=&)h9G@Qo@#Qw6KU|)5XZwc{ ziJsP|6Vb$(>lB)P#5S!U2P@7btIK~MUNX1Drb&|KuGp*&i;1?8!okEebfdCsxMFWU zTBEkvPJ7C@bgtxem;sWc@BFYwKucz-GFAduq`0C(FjyY}z%>qs%WzwA?LcED0F5d& zTPaex&bruj3i!NzAFf!R_Pb__Q`lk&2@#`%iPBw^z=#-PBf5kia!B`*yk&-^AV!44 zZK-;xu&RK;BGzP8pc z);hc91pS{%R-E}3ek^r-h_JSOXv>Wu1t*S#{c)PA-2Ab4ebIge#NGRtl5f1^d>XUyKsR|iJ^U3_u#j}%ZwOKi^F3FuJ`Oy>tnr(zMIO^A zNF;CNa%ngJW6~QI1_xo5VPLh|{Kn$OC4oVn4qi`pPnpg-`>u^+p2}2**+@P??os8W z3xN2*b1B*4f)R&KYL_m|d6hbLg>|Eyd&*3zl@$8?jk*d+l#LVvniA*j%y>uedPdjt z@}C)JuU#KFY;1;2Zgat#Y|=p0wWAFqoL4|7M41@_0aeJWbn(Dr(Q%(w(){`HAuyL> z_Dx!m?LP~=)`$*ff@ZXua>}si`P@Djf_KIH<#SUwP*4efcfH68#7dkY(R(h#;@3@j zhF+_SoCe>&1Ov#pXcJcG^h#~jl|4&Nqi!n!pc;?nYepgvL(I;YSSEFeK>&?7W;X?E zp|zuJd)4Yd<-1iy5Ea(8ecYfL0~z6`%%Y}~G+TG%`*x}GaPbG;RWB=9HBO{0l_<26 zMd=|@{)uP;>U;HrLf@WOQ=hducdJW!O`@_sJwnd7HzI)G-;JaHXt3UZ0rB0G0?-uk z7Q`s+q%=K)w$4cHyMB$M=pV|typEGx}jCzz1fuU3p!_2LzXt^W? zr3t>pHm`*CtjDH!0&EqBtoNxj4*(&FV1ANmWoVJ<kk?J^5Uy^LAsNRgU!^TDeIz8=|5DC~_4q;dV+gv6b41u0U9^^C9tQv_lZRI^w83g( zw{s1yq3K=|keqr^AkF-x`1$Un@x7iM2t52_Eue_GesCEKe{gKtBt^`}TsDSeCDzuC$pTb{!n_t6XtF`|0Sy zC$i0BNc)?n{ui+3ry5KU!^bGM7J-}$d(j`hdiILsjrT|NXt72>o|bj#KIE` zp4iDF6BSKu-{E$2JO+2*U9R?2KQf>QR1%}Q0(XH^K60YQT#1+*&zbp9Uh}kn_y;8C z3H+aArY24XzxlXAi7jD*Cg_lkQUS5=cehukL@qzp5jl*`Uj4^uikmyX+Tx?$@yCWG&arX^;HZ4Aj2 zB^klt-LA&@#JZ+RzMAnkzV8v;$2afHh{1ZwDJdzP_M(J38f~Fy&c0Z4oH*K42vZlS zjTFk-hM)ZJOzKbp_qy0Xuo=@s6uWtpE(XNvZ*uN-Zvlx(5!0-6M@Q;nh4KAFmY7c# zI&p5?3QVroMx<$R-81f!Z*1)B_-@zg8Q*T|l<8*fpI;+kh$w-aTn1c)I9h5uM}QUg zi?edDTQ&L!k>?^K-~kD(q*hz2ZCM(kbDe9$k6JRJD%zDNjkUn>Z=nZSjMk2hFO-z{ zLCD$&g@cTi7Abg{Kmq`x>^kODM=3CKfKXN=c7QDX@UH8YX-GxexabQ5>A8BWEew%;qY}BQ4 zOW8q#=k)y`2wMcny+#1&qj|NjV7K4$06@0<1k!*Ew_i^uZ>DElhP;do4AQe*2toFf zwF^g3n=?a_F#*6yus(#ypoXnsp~r^Vtpj{6LY87i*YkRDg~$o-gMa5Qn0FmcTvBfy zdLxydfKJ&PfBK(B^i))j;8++SZY4(>n#lTS**TX$@LSXTrfZSO9tEhl6eCj=!GQCU z(kOdD>~7_aFq?HTg!;=Wm|+}>31?z2NBQ$_tw4mWSaM5qjM>-reJ=+?<^$&oyCvN1 zHRE(@V9gQ|nn5U)W5+)B8KyjLyTteOsfGQ_&&w`7K}TPFUGaPW^rLMd%%^Lg8%i9A zIbXWX*gSjfy;(^ApXZLMq6fUUJtEK$sI8GY^OQvP3u*{|B_~u9=efYnK&q?W%i_ql zVglSQc_ZNqS1;i#tWy%R(QVM^zd|+b*AA5?gRTMG0F=_hCDYi;G!nUFIis7xA zplJ+DnVb>G0w%cTF3mXNupysQA{B7BY;TBj-S{zHjZNm()TWD6^JiZf8V=}rT&z;J zTaGLItFpm^u`Gd&alzLDUneD zH(ZJ%xGhIc=UuPmcx(wQd(n7G{&!6z8F~3hqt=R^Nc2&*VTY1>TvSGdrAt!HLtpqG zRnAk6f9Zzs2;x!|E&>%cMs~?K>p&d&1gSW4`MA>x&e`wYf$igF42iU202`UWx{G6G z9MNRr>So@%`);$5#nj*GX)VSAY#I2uRKF^2L;_3AKSiraYq=mpOuW5c1soQFgwCVQ z;($+z#R1@A3a)H8i_+4OSG53oc}P&Y@CV!b`-^nxX;cT7zVo21FPJz;nH?glv2=R1 zbb8rOfp)n|zg~RTR-Q%=XkSEc0qP~noDdi{J1KYK-D?xBpPuGFFGSf-ItK>Q&~L(m zxZbv##*;T~IV=9eqc}41(ZGb2jh`OHW>tHZ)pX}ih?Y36lV3|{DVlCj5m%4*7Q~~M z)CC9{&vz(&kNQ{wYOVGc!gnE=K0v1`CQkq@5Y>pnh)q*ryzt_H< zl_%Dj#_<7-{Vz2c$&}EPGR#J;smuvlZd>Dp+&-?#)#>y^muKvDem$aKWgS%(KI-hS z(lr!{H(kE+D;Vq+u(esdPfJ7Pjo->l`sVtIS^>FW4J?^qM3u(S2|1f6iPF)ZcsK2~ znN&(AF&4z(6lmfAFmU`r)RWQA8zacpA4ZfWEDDd!-OelntvC-8yVa7FMc5DJ5^Qg8 zu9bep=K+zAc3D<;tJw=R8b5mr!?n#Ig-2VY=C2M!5|Z9($-U9@AVe_%52TRsstn>J z(%i{d0Bcm#?e#g4==Gcnk<)DRt)4sPqN;xNrK*iV3n8%jzAb9=zl72@a2d6fmTW~& zZtvn_LRDnoj3m|a#c@F3E^7iVgP71G>_lEm?j-e@P-||0^%O55NQJFe8=Tx)_d+qF zG_m#XO_^E#Ti$A)`C}7=F%)nzc`P7~fy1*GzZ*n!q6ib{S`g4wWh(w}Yy(5#=v-MGi+TCQB9+;3OpEnD#>8|RFVt-Q zu*&w?Yu4vHBmJ_~bo)JC%_raK?m1BZE2suxX7=Cp2HqmSzhe-nn4G0Nz?OQ=%SeI) z&S}bENY4t_1i5w;y#8||D?bK1PJqUe(k~$4g!jvrLyll58wONLz0F5eDdfk=kH-P( zio0{Sic-dzXX_tL%kfbiys?VRykcN~p6m2ZWu#;%+xzdHDL+R?9#x z+gA6L&ci>o794T*k&oE2Zh56`JXsIFH*$>)0T_`rnA41l>5G>yFx4?CEh)Okt%kGw zs;>{0kKN0DYw3`gQb;9{Y1=)Wpyt|WkbD#^nG#3xSXQ|2Z3;WP*?V-JGQ)6He`O9X zuO4N}-JIqKV}B376SO|xezeSgNPIULF}o_QF(CS6CwDyFW8UPLCOr}S_0a3Ma8 zy2FlX`PN*>|F{NC4@yzQl`AeDJBv~L6cZP|oLpXBuFG1d4Vu`y$FF)&+(Yl63f%vy z)sUPB|D&xVcF_~hV!Xe%E4E)V+ZbkwV6&A(^>OCw+U1xhG4zc|5k!1>fs-SRwc!Qr zjYB#)?_ypAN)y{PeWU0*<}~o|N^<997>n)tjxA-SsXqX&&J& zPw@|a!FfFi`Ad<<*!Gs@_2S%XI(phBq36Pv-0+~sfD=k^MIJq@=c@{|M8es@8uxUx zG&H_H?l(q{9qXoz$9yx{5N@mk8SqDrfW?XAWMtOnyY2gj?c z+xaUi0nPrmSD5Hzq}PpI?2#cM*pK^hyF!2!!x}oZdFq{gvwOHwAwDyA^Tp`vcMDlb z(l9g#_)yjyaCUbGNU7VOp&nix)=f^jjoJal_IzN7ZFXDZ_palJK2xcXDtFpVJ71SE$! zeXvfeG2MD%MAUr9?}sR=owq}eJS8A-%-^2phPQgycS$Wgl5xalk;}iKq7h>UXRQ{eMb*p9FtlyER z)Bf?P(f+tMI3g5b_`rh?y1gqr&yd^p#Sd~q+wWlX-!Pwbu&ohfpUpZ(^y1hi8SsBwaqVnLf z8o6U)1iisLMT4Gkvh_R=a}2aS72iHF=>t@A26^gl3A{7c1c}%2N=#YEI*r?nwq!3a;2G>v}f11Z?+~`a_BLf56G=2mSG2`*aRxE+Gf

6fC+Rr2K6~5E2QOp8CEU?c`K(b$hp|w!Ypo8QiAS{WCyG zQes6?OckKdd!IArDVc~x^la<&YR|I5qq6zCySkHryUO^^RzrDIoIF4!TSFOsa{Rts zD&GmBF4#q`k;-?Y2xaZRuYOdp{|L>bQ3+*SmNJBEyRmBAN9MuHx37{c2*Nv-W$)M4 zPL7U_T%V+71Q+Z&mZ$~vptI61z+opfkFCeCu%)d5?7?~tAD;;d($%K_YI^ncyVjFm zF-0~-d8~NjUZbnnSfKS%aCE=;TXW$HRObZKoh>wik{s=4a^&#q{RgejB8VP7-^K9l zh8Tz04ls0Hm;!&O!pU(cti!aborrbG38GASoE4l!(wcqMpd^4!K}ccB^i&#r)%E$R zYuEVOeouhv1J}5~B)*{&d#P=I6{o@kl|H~5^Gz|jWW%={D`!c8b(X=EGbMD>BTQ;Qs%Yi(xWHM z6QeMxMI)y{DyxBz{j`rAxb3qr_;x>UQ`v=WI z25{kd@ArUGbA-aKEr&1EJS~nfQ9y-bv(%O~DvvEHudnKhVjLr05E2J`#4$#oDT+I9 z-l4GbSfel*qB?k^{t894^B(ja_%3EQX03Z?t%sOyXre?gD+n>KG9W&kkYOD3$3;51 z*p$!eaj_eAM@ECn5HP_RzcXg!%w?hUa3<*bL~3 zHDAzMM^Arofr&HMnSOgyL<~AS0R>rAnQ|$UAZ749FZjH_Cj?XgNk9Qm1)tJ@8u@eO z{%ijoft7y1Ujc*mf&XIM?(cB{bwC;XcWvMW_|KYPPqe`!O+XHi1>b?0C;!uUf&bqR I2>8kW0h0=QvH$=8 diff --git a/developer/src/test/auto/keyboard-package-versions/Keyman.Test.System.CompilePackageVersioningTest.pas b/developer/src/test/auto/keyboard-package-versions/Keyman.Test.System.CompilePackageVersioningTest.pas deleted file mode 100644 index 8fd0c993f79..00000000000 --- a/developer/src/test/auto/keyboard-package-versions/Keyman.Test.System.CompilePackageVersioningTest.pas +++ /dev/null @@ -1,155 +0,0 @@ -unit Keyman.Test.System.CompilePackageVersioningTest; - -interface - -uses - DUnitX.TestFramework, - Keyman.Developer.System.Project.ProjectLog; - -type - - [TestFixture] - TCompilePackageVersioningTest = class(TObject) - private - FRoot: string; - procedure PackageMessage(Sender: TObject; msg: string; - State: TProjectLogState); - public - [Setup] - procedure Setup; - [TearDown] - procedure TearDown; - // Sample Methods - // Simple single Test - // Test with TestCase Attribute to supply parameters. - [Test] - [TestCase('test-single-version-1-package', 'test1.kps,False')] - [TestCase('test-single-version-2-package', 'test2.kps,False')] - [TestCase('test-version-2-1-mismatch', 'test2-1.kps,True')] - [TestCase('test-version-1-2-mismatch', 'test1-2.kps,True')] - [TestCase('test-keyboard-1-package-2', 'test-keyboard-1-vs-package-2.kps,False')] - [TestCase('test-package-1-keyboard-2', 'test-package-1-vs-keyboard-2.kps,False')] - procedure TestPackageCompile(Path: string; ExpectError: Boolean); - end; - -implementation - -uses - System.SysUtils, - Winapi.ActiveX, - - compile, - CompilePackage, - Keyman.Developer.System.Project.kmnProjectFileAction, - Keyman.Developer.System.Project.ProjectFile, - kpsfile; - -type - TProjectConsole = class(TProject) - private - FSilent: Boolean; - FFullySilent: Boolean; - public - procedure Log(AState: TProjectLogState; Filename: string; Msg: string; MsgCode, line: Integer); override; // I4706 - function Save: Boolean; override; // I4709 - - property Silent: Boolean read FSilent write FSilent; - property FullySilent: Boolean read FFullySilent write FFullySilent; - end; - -procedure TCompilePackageVersioningTest.Setup; -var - p: TProjectConsole; - i: Integer; -begin - Assert.IgnoreCaseDefault := False; - - FRoot := ExtractFileDir(ExtractFileDir(ExtractFileDir(ExtractFileDir(ParamStr(0))))); - - p := TProjectConsole.Create(ptUnknown, FRoot+'\test-1.0\test-1.0.kpj', False); - try - for i := 0 to p.Files.Count - 1 do - if p.Files[i] is TkmnProjectFileAction then - Assert.IsTrue((p.Files[i] as TkmnProjectFileAction).CompileKeyboard, 'Could not compile keyboard'); - finally - p.Free; - end; - - p := TProjectConsole.Create(ptUnknown, FRoot+'\test-2.0\test-2.0.kpj', False); - try - for i := 0 to p.Files.Count - 1 do - if p.Files[i] is TkmnProjectFileAction then - Assert.IsTrue((p.Files[i] as TkmnProjectFileAction).CompileKeyboard, 'Could not compile keyboard'); - finally - p.Free; - end; -end; - -procedure TCompilePackageVersioningTest.TearDown; -begin -end; - -procedure TCompilePackageVersioningTest.PackageMessage(Sender: TObject; msg: string; State: TProjectLogState); -const - Map: array[TProjectLogState] of TLogLevel = ( - {plsInfo} TLogLevel.Information, - {plsHint} TLogLevel.Information, - {plsWarning} TLogLevel.Warning, - {plsError} TLogLevel.Error, - {plsFatal} TLogLevel.Error, - {plsSuccess} TLogLevel.Information, - {plsFailure} TLogLevel.Error - ); -begin - Log(Map[State], msg); -end; - -procedure TCompilePackageVersioningTest.TestPackageCompile(Path: string; ExpectError: Boolean); -var - pack: TKPSFile; - res: Boolean; -begin - pack := TKPSFile.Create; - try - pack.FileName := FRoot+'\'+Path; - pack.LoadXML; - res := DoCompilePackage(pack, PackageMessage, False, False, FRoot+'\'+ChangeFileExt(Path,'.kmp')); - Assert.AreEqual(not ExpectError, res); - finally - pack.Free; - end; -end; - -procedure TProjectConsole.Log(AState: TProjectLogState; Filename, Msg: string; MsgCode, line: Integer); // I4706 -begin -{$IFDEF DEBUG_PROJECT} - case AState of - plsInfo, - plsSuccess, - plsFailure: - if not FSilent then - writeln(ExtractFileName(Filename)+': '+Msg); - plsWarning: - if not FFullySilent then - writeln(ExtractFileName(Filename)+': Warning: '+Msg); - plsError: - if not FFullySilent then - writeln(ExtractFileName(Filename)+': Error: '+Msg); - plsFatal: - writeln(ExtractFileName(Filename)+': Fatal error: '+Msg); - end; -{$ENDIF} -end; - -function TProjectConsole.Save: Boolean; // I4709 -begin - // We don't modify the project file in the console - Result := True; -end; - -initialization - CoInitializeEx(nil, COINIT_APARTMENTTHREADED); - TDUnitX.RegisterTestFixture(TCompilePackageVersioningTest); -finalization - CoUninitialize; -end. diff --git a/developer/src/test/auto/keyboard-package-versions/Makefile b/developer/src/test/auto/keyboard-package-versions/Makefile deleted file mode 100644 index c07f744018f..00000000000 --- a/developer/src/test/auto/keyboard-package-versions/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# -# Test that package compiler manages keyboard and package versions correctly -# -# NOTE: The .dproj needs $(CI) added to the Delphi Compiler/Conditional defines (All -# configurations - all platforms) section in order for the CI flag to be passed in. -# (It's best to make this change in Delphi IDE). -# - -!include ..\..\..\Defines.mak - -test: build - $(WIN32_TARGET_PATH)\keyboardpackageversionstestsuite.exe -b -exit:continue - -build: - $(DELPHI_MSBUILD) "/p:CI=CI" keyboardpackageversionstestsuite.dproj - -clean: def-clean - -del *.kmp - -del test-1.0\*.kmx - -del test-2.0\*.kmx - -del test-1.0\*.js - -del test-2.0\*.js - -!include ..\..\..\Target.mak From fd9b1313072bdeb31f79e962cb820b7e28dd653b Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 25 Sep 2023 10:27:59 +0700 Subject: [PATCH 5/5] chore(developer): remove Package Installer UI from TIKE --- .../common/delphi/compiler/CompilePackage.pas | 540 ------------------ .../compiler/CompilePackageInstaller.pas | 446 --------------- .../src/tike/child/UfrmPackageEditor.dfm | 96 +--- .../src/tike/child/UfrmPackageEditor.pas | 39 -- ...er.System.Project.kpsProjectFileAction.pas | 57 -- ...man.Developer.UI.Project.ProjectFileUI.pas | 2 +- ...eyman.Developer.UI.Project.UfrmProject.pas | 15 - ....Developer.UI.Project.kpsProjectFileUI.pas | 19 - developer/src/tike/tike.dpr | 2 - developer/src/tike/tike.dproj | 2 - .../src/tike/xml/project/distribution.xsl | 4 - developer/src/tike/xml/project/packages.xsl | 24 +- 12 files changed, 15 insertions(+), 1231 deletions(-) delete mode 100644 developer/src/common/delphi/compiler/CompilePackage.pas delete mode 100644 developer/src/common/delphi/compiler/CompilePackageInstaller.pas diff --git a/developer/src/common/delphi/compiler/CompilePackage.pas b/developer/src/common/delphi/compiler/CompilePackage.pas deleted file mode 100644 index c7c5e071235..00000000000 --- a/developer/src/common/delphi/compiler/CompilePackage.pas +++ /dev/null @@ -1,540 +0,0 @@ -(* - Name: CompilePackage - Copyright: Copyright (C) SIL International. - Documentation: - Description: - Create Date: 20 Jun 2006 - - Modified Date: 11 May 2015 - Authors: mcdurdin - Related Files: - Dependencies: - - Bugs: - Todo: - Notes: - History: 20 Jun 2006 - mcdurdin - Initial version - 04 Dec 2006 - mcdurdin - Add message for missing files when compiling package - 04 Jun 2007 - mcdurdin - Remove unused KeymanPath - 20 Jun 2007 - mcdurdin - Remove unused ActivationManager reference - 19 Nov 2007 - mcdurdin - I1157 - const string parameters - 04 May 2015 - mcdurdin - I4688 - V9.0 - Add build path to project settings - 04 May 2015 - mcdurdin - I4690 - V9.0 - Pull keyboard version into package version when adding a keyboard - 11 May 2015 - mcdurdin - I4706 - V9.0 - Update compile logging for silent and warning-as-error cleanness -*) -unit CompilePackage; - -interface - -uses - kpsfile, - kmpinffile, - PackageInfo, - Keyman.Developer.System.Project.ProjectLog; - -function DoCompilePackage(pack: TKPSFile; AMessageEvent: TCompilePackageMessageEvent; ASilent, ACheckFilenameConventions: Boolean; const AOutputFileName: string): Boolean; // I4688 - -implementation - -uses - Winapi.Windows, - System.Classes, - System.Generics.Collections, - System.SysUtils, - System.IniFiles, - System.Zip, - - VisualKeyboard, - utilfiletypes, - ErrorControlledRegistry, - RegistryKeys, - kmxfile, - KeymanDeveloperOptions, - KeymanVersion, - - Keyman.System.KeyboardUtils, - Keyman.System.LexicalModelUtils, - Keyman.System.CanonicalLanguageCodeUtils, - Keyman.System.PackageInfoRefreshKeyboards, - Keyman.System.PackageInfoRefreshLexicalModels, - - RedistFiles, - TempFileManager, - VersionINfo; - -type - TCompilePackage = class - private - FSilent: Boolean; - FOnMessage: TCompilePackageMessageEvent; - FTempPath: string; - //FRuntimeSourcePath: string; - pack: TKPSFile; - - FOutputFileName: string; - FTempFiles: TTempFiles; - FCheckFilenameConventions: Boolean; - - procedure FatalMessage(const msg: string); - procedure WriteMessage(AState: TProjectLogState; const msg: string); // I4706 - - function BuildKMP: Boolean; - - constructor Create(APack: TKPSFile; AMessageEvent: TCompilePackageMessageEvent; ASilent, ACheckFilenameConventions: Boolean; const AOutputFileName: string); // I4688 - destructor Destroy; override; - function Compile: Boolean; - procedure CheckForDangerousFiles; - procedure CheckKeyboardVersions; - procedure CheckKeyboardLanguages; - procedure CheckFilenameConventions; - function CheckLexicalModels: Boolean; - procedure CheckForDuplicatedLanguages(const resourceType, id: string; languages: TPackageKeyboardLanguageList); - end; - -function DoCompilePackage(pack: TKPSFile; AMessageEvent: TCompilePackageMessageEvent; ASilent, ACheckFilenameConventions: Boolean; const AOutputFileName: string): Boolean; // I4688 -begin - with TCompilePackage.Create(pack, AMessageEvent, ASilent, ACheckFilenameConventions, AOutputFileName) do // I4688 - try - Result := Compile; - finally - Free; - end; -end; - - -constructor TCompilePackage.Create(APack: TKPSFile; AMessageEvent: TCompilePackageMessageEvent; ASilent, ACheckFilenameConventions: Boolean; const AOutputFileName: string); // I4688 -begin - inherited Create; - pack := APack; - FOnMessage := AMessageEvent; - FSilent := ASilent; - FOutputFileName := AOutputFileName; - FTempFiles := TTempFiles.Create; - FCheckFilenameConventions := ACheckFilenameConventions; -end; - -destructor TCompilePackage.Destroy; -begin - FreeAndNil(FTempFiles); - inherited Destroy; -end; - -procedure TCompilePackage.CheckFilenameConventions; -var - i: Integer; -begin - if not FCheckFilenameConventions then - Exit; - - if pack.LexicalModels.Count > 0 then - begin - if not TLexicalModelUtils.DoesPackageFilenameFollowLexicalModelConventions(pack.FileName) then - WriteMessage(plsWarning, Format(TKeyboardUtils.SPackageNameDoesNotFollowLexicalModelConventions_Message, [ExtractFileName(pack.FileName)])); - end - else - begin - if not TKeyboardUtils.DoesKeyboardFilenameFollowConventions(pack.FileName) then - WriteMessage(plsWarning, Format(TKeyboardUtils.SKeyboardNameDoesNotFollowConventions_Message, [ExtractFileName(pack.FileName)])); - end; - - for i := 0 to pack.Files.Count - 1 do - begin - if not TKeyboardUtils.DoesFilenameFollowConventions(pack.Files[i].FileName) then - WriteMessage(plsWarning, Format(TKeyboardUtils.SFilenameDoesNotFollowConventions_Message, [ExtractFileName(pack.Files[i].FileName)])); - end; -end; - -function TCompilePackage.CheckLexicalModels: Boolean; -var - model: TPackageLexicalModel; -begin - if pack.LexicalModels.Count > 0 then - begin - if pack.Keyboards.Count > 0 then - begin - FatalMessage('The package contains both lexical models and keyboards, which is not permitted.'); - Exit(False); - end; - end; - - for model in pack.LexicalModels do - begin - CheckForDuplicatedLanguages('model', model.id, model.Languages); - end; - - - Exit(True); -end; - -function TCompilePackage.Compile: Boolean; -var - buf: array[0..260] of Char; - n: Integer; - b: Boolean; - f: TSearchRec; -begin - Result := False; - - if pack.FileName = '' then - begin - FatalMessage('You need to save the package before building.'); - Exit; - end; - - WriteMessage(plsInfo, 'Compiling package ' + ExtractFileName(pack.FileName) + '...'); - - if Trim(pack.Info.Desc[PackageInfo_Name]) = '' then - begin - FatalMessage('You need to fill in the package name before building.'); - Exit; - end; - - CheckFilenameConventions; - CheckForDangerousFiles; - CheckKeyboardVersions; - CheckKeyboardLanguages; - if not CheckLexicalModels then Exit; - - GetTempPath(260, buf); - FTempPath := buf; - - GetTempFileName(PChar(FTempPath), 'kmn', 0, buf); - FTempPath := buf + '.dir'; - b := CreateDir(FTempPath); - if not b then - begin - FatalMessage('Unable to create temp folder '+FTempPath); - if FileExists(buf) then DeleteFile(buf); - Exit; - end; - - try - Result := BuildKMP; - finally - n := FindFirst(FTempPath + '\*.*', 0, f); - if n = 0 then - begin - while n = 0 do - begin - DeleteFile(FTempPath + '\' + f.Name); - n := FindNext(f); - end; - FindClose(f); - end; - RemoveDirectory(PChar(FTempPath)); - if FileExists(buf) then DeleteFile(buf); - end; -end; - - -function TCompilePackage.BuildKMP: Boolean; -var - kmpinf: TKMPInfFile; - psf: TPackageContentFile; - FPackageVersion: string; - i: Integer; - f: TTempFile; -begin - Result := False; - - kmpinf := TKMPInfFile.Create; - try - { Create KMP.INF and KMP.JSON } - - kmpinf.Assign(pack); - - // Add keyboard information to the package 'for free' - // Note: this does not get us very far for mobile keyboards as - // they still require the .js to be added by the developer at this stage. - // But it ensures that all keyboards in the package are listed in the - // {Keyboards} section - - with TPackageInfoRefreshKeyboards.Create(kmpinf) do - try - OnError := Self.FOnMessage; - if not Execute then - begin - WriteMessage(plsError, 'The package build was not successful.'); - Exit; - end; - finally - Free; - end; - - with TPackageInfoRefreshLexicalModels.Create(kmpinf) do - try - OnError := Self.FOnMessage; - if not Execute then - begin - WriteMessage(plsError, 'The package build was not successful.'); - Exit; - end; - finally - Free; - end; - - // - // Update the package version to the current compiled - // keyboard version. - // - - if pack.KPSOptions.FollowKeyboardVersion then - begin - if kmpinf.Keyboards.Count = 0 then - begin - FatalMessage('The option "Follow Keyboard Version" is set but there are no keyboards in the package.'); - Exit; - end; - - FPackageVersion := kmpinf.Keyboards[0].Version; - for i := 1 to kmpinf.Keyboards.Count - 1 do - if kmpinf.Keyboards[i].Version <> FPackageVersion then - begin - FatalMessage( - 'The option "Follow Keyboard Version" is set but the package contains more than one keyboard, '+ - 'and the keyboards have mismatching versions.'); - Exit; - end; - - kmpinf.Info.Desc[PackageInfo_Version] := FPackageVersion; - end; - - kmpinf.RemoveFilePaths; - - // - // Find the minimum package version based on keyboard version - // See also MergeKeyboardInfo.pas - // - - if kmpinf.LexicalModels.Count = 0 then - begin - kmpinf.Options.FileVersion := SKeymanVersion70; - - for i := 0 to kmpinf.Keyboards.Count - 1 do - begin - if CompareVersions(kmpinf.Options.FileVersion, kmpinf.Keyboards[i].MinKeymanVersion) > 0 then - begin - // Keyman for Windows 14 and earlier only accepted version 7.0 for keyboard - // packages, so we must not write any other version in order to allow - // earlier versions of Keyman to load the package. - if CompareVersions(kmpinf.Keyboards[i].MinKeymanVersion, SKeymanVersion150) <= 0 then - begin - kmpinf.Options.FileVersion := kmpinf.Keyboards[i].MinKeymanVersion; - end; - end; - end; - - psf := TPackageContentFile.Create(kmpinf); - psf.FileName := 'kmp.inf'; - psf.Description := 'Package information'; - psf.CopyLocation := pfclPackage; - - kmpinf.Files.Add(psf); - end - else - begin - // TODO: min model version is always 12.0 currently - // but we may need to support this in future - kmpinf.Options.FileVersion := SKeymanVersion120; - end; - - // - // Prepare and save - // - - psf := TPackageContentFile.Create(kmpinf); - psf.FileName := 'kmp.json'; - psf.Description := 'Package information (JSON)'; - psf.CopyLocation := pfclPackage; - - kmpinf.Files.Add(psf); - - kmpinf.FileName := FTempPath + '\kmp.inf'; - kmpinf.SaveIni; - - kmpinf.FileName := FTempPath + '\kmp.json'; - kmpinf.SaveJSON; - finally - kmpinf.Free; - end; - - try - ForceDirectories(ExtractFileDir(FOutputFilename)); - if FileExists(FOutputFilename) then - DeleteFile(FOutputFilename); - - { Create output file } - - try - - if FileExists(FOutputFilename) then DeleteFile(FOutputFilename); - - with TZipFile.Create do - try - Open(FOutputFilename, TZipMode.zmWrite); - Add(FTempPath + '\kmp.inf'); - Add(FTempPath + '\kmp.json'); - for i := 0 to pack.Files.Count - 1 do - begin - if not FileExists(pack.Files[i].FileName) then - WriteMessage(plsWarning, 'File '+pack.Files[i].FileName+' does not exist.') - else - begin - // When compiling the package, save the kvk keyboard into binary for delivery - if pack.Files[i].FileType = ftVisualKeyboard then - begin - f := TTempFileManager.Get('.kvk'); - FTempFiles.Add(f); - with TVisualKeyboard.Create do - try - try - LoadFromFile(pack.Files[i].FileName); - except - on E:EVisualKeyboardLoader do - begin - WriteMessage(plsError, pack.Files[i].FileName+' is invalid: '+E.Message); - Continue; - end; - end; - SaveToFile(f.Name, kvksfBinary); - finally - Free; - end; - Add(f.Name, ExtractFileName(pack.Files[i].FileName)); - end - else - Add(pack.Files[i].FileName); - end; - end; - if FileCount < pack.Files.Count + 2 then - WriteMessage(plsError, 'The build was not successful. Some files were skipped.') - else - begin - Result := True; - end; - Close; - finally - Free; - end; - except - on E:EZipException do - begin - WriteMessage(plsError, E.Message); - end; - end; - finally - if not Result then - if FileExists(FOutputFilename) then DeleteFile(FOutputFilename); - end; -end; - -procedure TCompilePackage.FatalMessage(const msg: string); -begin - FOnMessage(Self, msg, plsFatal); // I4706 -end; - -procedure TCompilePackage.WriteMessage(AState: TProjectLogState; const msg: string); // I4706 -begin - FOnMessage(Self, msg, AState); // I4706 -end; - -const - SKKeymanRedistFileShouldNotBeInPackage = 'The Keyman system file ''%0:s'' should not be compiled into the package. Use a redistributable installer instead.'; - SKDocFilesDangerous = 'Microsoft Word .doc or .docx files (''%0:s'') are not portable. You should instead use HTML or PDF format.'; - -procedure TCompilePackage.CheckForDangerousFiles; -var - i, j: Integer; - s: string; -begin - for i := 0 to pack.Files.Count - 1 do - begin - s := LowerCase(ExtractFileName(pack.Files[i].FileName)); - for j := Low(CRedistFiles) to High(CRedistFiles) do - if s = CRedistFiles[j].FileName then - WriteMessage(plsWarning, Format(SKKeymanRedistFileShouldNotBeInPackage, [s])); - for j := Low(CRuntimeFiles) to High(CRuntimeFiles) do - if s = CRuntimeFiles[j].FileName then - WriteMessage(plsWarning, Format(SKKeymanRedistFileShouldNotBeInPackage, [s])); - if (ExtractFileExt(s) = '.doc') or (ExtractFileExt(s) = '.docx') then WriteMessage(plsWarning, Format(SKDocFilesDangerous, [s])); - end; -end; - -const - SKKeyboardPackageVersionMismatch = 'The keyboard %0:s has version %1:s, which differs from the package version %2:s.'; - -procedure TCompilePackage.CheckKeyboardVersions; // I4690 -var - n, i: Integer; - ki: TKeyboardInfo; -begin - n := 0; - - // The version information is checked separately if we use - // 'follow keyboard version' - if pack.KPSOptions.FollowKeyboardVersion then - Exit; - - for i := 0 to pack.Files.Count - 1 do - if pack.Files[i].FileType = ftKeymanFile then Inc(n); - - // We only test for keyboard <> package version if 1 keyboard in package - // For multi-keyboard packages, it isn't sensible to do the same - if n <> 1 then - Exit; - - for i := 0 to pack.Files.Count - 1 do - begin - if pack.Files[i].FileType <> ftKeymanFile then Continue; - if not FileExists(pack.Files[i].FileName) then Continue; - - GetKeyboardInfo(pack.Files[i].FileName, True, ki); - if ki.KeyboardVersion <> pack.Info.Desc[PackageInfo_Version] then - WriteMessage(plsWarning, Format(SKKeyboardPackageVersionMismatch, - [ExtractFileName(pack.Files[i].FileName), ki.KeyboardVersion, pack.Info.Desc[PackageInfo_Version]])); - ki.MemoryDump.Free; - end; -end; - -const - SKKeyboardPackageLanguageNonCanonical = 'The keyboard %0:s has a non-canonical language tag "%1:s" (%2:s), should be "%3:s".'; - SKKeyboardShouldHaveAtLeastOneLanguage = 'The keyboard %0:s has no language tags. It should have at least one language tag.'; - SKPackageShouldNotRepeatLanguages = 'The %0:s %1:s has a repeated language "%2:s".'; - -procedure TCompilePackage.CheckKeyboardLanguages; -var - k: TPackageKeyboard; -begin - for k in pack.Keyboards do - begin - if k.Languages.Count = 0 then - WriteMessage(plsWarning, Format(SKKeyboardShouldHaveAtLeastOneLanguage, [k.ID])); - CheckForDuplicatedLanguages('keyboard', k.ID, k.Languages); - end; -end; - -procedure TCompilePackage.CheckForDuplicatedLanguages(const resourceType, id: string; languages: TPackageKeyboardLanguageList); -var - tags: TDictionary; - lang: TPackageKeyboardLanguage; -begin - tags := TDictionary.Create; - try - for lang in languages do - begin - if tags.ContainsKey(lang.ID.ToLower) then - begin - WriteMessage(plsWarning, Format(SKPackageShouldNotRepeatLanguages, [resourceType, id, lang.ID])); - end - else - begin - tags.Add(lang.ID.ToLower, 0); - end; - end; - finally - tags.Free; - end; -end; - -end. - diff --git a/developer/src/common/delphi/compiler/CompilePackageInstaller.pas b/developer/src/common/delphi/compiler/CompilePackageInstaller.pas deleted file mode 100644 index aae46e6732e..00000000000 --- a/developer/src/common/delphi/compiler/CompilePackageInstaller.pas +++ /dev/null @@ -1,446 +0,0 @@ -(* - Name: CompilePackageInstaller - Copyright: Copyright (C) SIL International. - Documentation: - Description: - Create Date: 4 Jun 2007 - - Modified Date: 6 Jun 2015 - Authors: mcdurdin - Related Files: - Dependencies: - - Bugs: - Todo: - Notes: - History: 04 Jun 2007 - mcdurdin - Initial version - 05 Jun 2007 - mcdurdin - I817 - Fix Unicode .inf file (not available on 9x) - 19 Jun 2007 - mcdurdin - I817 - Use Unicode .inf file again - 20 Jun 2007 - mcdurdin - Support compiling package installer from a .kmp file - 23 Aug 2007 - mcdurdin - Support building an exe installer without any embedded kmp files - 19 Nov 2007 - mcdurdin - I1157 - const string parameters - 28 Jul 2008 - mcdurdin - I1558 - Embed graphic file into setup.exe - 28 Jul 2008 - mcdurdin - I1559 - Support custom setup.exe strings - 05 Aug 2008 - mcdurdin - Don't crash if FPack is not assigned - 30 Dec 2010 - mcdurdin - I2562 - EULA as part of setup bootstrapper - 04 Nov 2011 - mcdurdin - I3126 - Add flag to allow install with full msi UI - 04 May 2012 - mcdurdin - I3306 - V9.0 - Remove TntControls + Win9x support - 08 Jun 2012 - mcdurdin - I3337 - V9.0 - Review of input/output for Unicode - 06 Feb 2012 - mcdurdin - I2971 - TIKE maintains an open handle to .msi when compiling package installer - 04 Nov 2012 - mcdurdin - I3543 - V9.0 - Merge of I2971 - TIKE maintains an open handle to .msi when compiling package installer - 23 Feb 2015 - mcdurdin - I4598 - V9.0 - Keyman installer does not show EULA when bundled with a keyboard - 04 May 2015 - mcdurdin - I4688 - V9.0 - Add build path to project settings - 11 May 2015 - mcdurdin - I4706 - V9.0 - Update compile logging for silent and warning-as-error cleanness - 06 Jun 2015 - mcdurdin - I4741 - Package installer compiler references wrong path for compiled package file -*) -unit CompilePackageInstaller; // I3306 - -interface - -uses Windows, kpsfile, kmpinffile, PackageInfo, CompilePackage, - Keyman.Developer.System.Project.Projectlog, - jwaMsi, jwaMsiQuery, SysUtils; - -function DoCompilePackageInstaller(pack: TKPSFile; FMessageEvent: TCompilePackageMessageEvent; FSilent: Boolean; - AInstallerMSI, AOutputFilename, ARedistSetupPath: string; - AUpdateInstaller: Boolean; ABuildPackage: Boolean; ALicense, ATitleImage, AAppName: string; - AStartDisabled, AStartWithConfiguration: Boolean): Boolean; // I4598 // I4688 -function DoCompileMSIInstaller(FMessageEvent: TCompilePackageMessageEvent; FSilent: Boolean; - AInstallerMSI, AOutputFilename, ARedistSetupPath, ALicense, ATitleImage, AAppName: string; - AStartDisabled, AStartWithConfiguration: Boolean): Boolean; // I2562 - -implementation - -uses - System.Classes, - System.Zip, - RedistFiles, - utildir, - utilsystem; - -type - ECompilePackageInstaller = class(Exception); - - TCompilePackageInstaller = class - private - FOnMessage: TCompilePackageMessageEvent; - FPack: TKPSFile; - FSilent: Boolean; - FVersion: WideString; - FTempPath: WideString; - FProductName: WideString; - FRedistSetupPath: string; - FInstallerMSI: WideString; - FUpdateInstaller: Boolean; - FBuildPackage: Boolean; - FOutputFilename: string; - FLicense: string; // I2562 - FTitleImage: string; - FAppName: string; - FStartDisabled: Boolean; - FStartWithConfiguration: Boolean; - procedure FatalMessage(msg: string); - procedure WriteMessage(msg: string); - function GetMSIOnlineProductID: Boolean; - public - constructor Create(APack: TKPSFile; ASilent: Boolean; AInstallerMSI: string; AUpdateInstaller, ABuildPackage: Boolean; AOutputFilename, ARedistSetupPath, ALicense, ATitleImage, AAppName: string; AStartDisabled, AStartWithConfiguration: Boolean); // I2562 - procedure Run; - property OnMessage: TCompilePackageMessageEvent read FOnMessage write FOnMessage; - end; - -function DoCompilePackageInstaller(pack: TKPSFile; FMessageEvent: TCompilePackageMessageEvent; FSilent: Boolean; - AInstallerMSI, AOutputFilename, ARedistSetupPath: string; AUpdateInstaller: Boolean; ABuildPackage: Boolean; - ALicense, ATitleImage, AAppName: string; AStartDisabled, AStartWithConfiguration: Boolean): Boolean; // I4598 // I4688 -begin - with TCompilePackageInstaller.Create(pack, FSilent, AInstallerMSI, AUpdateInstaller, ABuildPackage, - AOutputFilename, ARedistSetupPath, ALicense, ATitleImage, AAppName, - AStartDisabled, AStartWithConfiguration) do // I2562 // I4598 // I4688 - try - OnMessage := FMessageEvent; - Run; - Result := True; - finally - Free; - end; -end; - -function DoCompileMSIInstaller(FMessageEvent: TCompilePackageMessageEvent; FSilent: Boolean; AInstallerMSI: string; - AOutputFilename, ARedistSetupPath, ALicense, ATitleImage, AAppName: string; - AStartDisabled, AStartWithConfiguration: Boolean): Boolean; // I2562 -begin - with TCompilePackageInstaller.Create(nil, FSilent, AInstallerMSI, False, False, AOutputFileName, ARedistSetupPath, - ALicense, ATitleImage, AAppName, AStartDisabled, AStartWithConfiguration) do // I2562 - try - OnMessage := FMessageEvent; - Run; - Result := True; - finally - Free; - end; -end; - -{ TCompilePackageInstaller } - -constructor TCompilePackageInstaller.Create(APack: TKPSFile; ASilent: Boolean; AInstallerMSI: string; AUpdateInstaller, ABuildPackage: Boolean; AOutputFileName, ARedistSetupPath, ALicense, ATitleImage, AAppName: string; AStartDisabled, AStartWithConfiguration: Boolean); // I2562 -begin - inherited Create; - FPack := APack; - FSilent := ASilent; - FInstallerMSI := AInstallerMSI; - FUpdateInstaller := AUpdateInstaller; - FBuildPackage := ABuildPackage; - FOutputFilename := AOutputFilename; - FRedistSetupPath := ARedistSetupPath; - FLicense := ALicense; // I2562 - FTitleImage := ATitleImage; - FAppName := AAppName; - FStartDisabled := AStartDisabled; - FStartWithConfiguration := AStartWithConfiguration; - - if (FLicense <> '') and not FileExists(FLicense) then - raise ECompilePackageInstaller.CreateFmt('License file %s could not be found.', [FLicense]); - - if (FTitleImage <> '') and not FileExists(FTitleImage) then - raise ECompilePackageInstaller.CreateFmt('Title iamge file %s could not be found.', [FTitleImage]); - - if not Assigned(FPack) then - begin - if (FInstallerMSI = '') or (FUpdateInstaller) or (FBuildPackage) or (FOutputFilename = '') then - raise ECompilePackageInstaller.Create('Invalid arguments - if Pack is nil then FUpdateInstaller, FBuildPackage must be false and FInstallerMSI and FOutputFilename must not be empty.'); - end - else if FOutputFilename = '' then // I4688 - raise ECompilePackageInstaller.Create('Invalid arguments - if Pack is not nil then FOutputFilename must not be empty.'); -end; - -procedure TCompilePackageInstaller.FatalMessage(msg: string); -begin - FOnMessage(Self, msg, plsFatal); // I4706 -end; - -function TCompilePackageInstaller.GetMSIOnlineProductID: Boolean; -var - hDatabase: MSIHANDLE; - - procedure CheckResult(v: UINT); - begin - if v <> ERROR_SUCCESS then RaiseLastOSError; - end; - - function GetMSIProperty(PropertyName: WideString): WideString; - const - SQLPropertyQuery: WideString = 'SELECT Value FROM Property WHERE Property = ''%0:s'''; - var - hView, hRecord: MSIHANDLE; - buf: array[0..260] of WideChar; - sz: Cardinal; - FResult: Cardinal; - begin - CheckResult(MsiDatabaseOpenViewW(hDatabase, PWideChar(WideFormat(SQLPropertyQuery, [PropertyName])), hView)); - - try - CheckResult(MsiViewExecute(hView, 0)); - try - hRecord := 0; - FResult := MsiViewFetch(hView, hRecord); // I2971 // I3543 - try - case FResult of - ERROR_NO_MORE_ITEMS: - begin - Result := ''; - end; - ERROR_SUCCESS: - begin - sz := 260; - CheckResult(MsiRecordGetStringW(hRecord, 1, buf, sz)); - Result := Copy(buf,1,sz); - end; - else - RaiseLastOSError; - end; - finally - if hRecord <> 0 then MsiCloseHandle(hRecord); // I2971 // I3543 - end; - finally - MsiViewClose(hView); - end; - finally - MsiCloseHandle(hView); // I2971 // I3543 - end; - end; - -begin - Result := False; - CheckResult(MsiOpenDatabaseW(PWideChar(FInstallerMSI), nil, hDatabase)); - - try - FVersion := GetMSIProperty('ProductVersion'); - if FVersion = '' then - begin - FatalMessage('No ProductVersion found in the MSI file.'); - Exit; - end; - - FProductName := GetMSIProperty('ProductName'); - if FProductName = '' then - begin - FatalMessage('No ProductName found in the MSI file.'); - Exit; - end; - - Result := True; - finally - MsiCloseHandle(hDatabase); - end; -end; - -procedure TCompilePackageInstaller.Run; -var - FDestFileName: WideString; - fs: TFileStream; - s: WideString; - i: Integer; - FMSIOptions: WideString; - FRedistSetupFile, FPackageOutputFileName: string; // I3126 -begin - { Check that the .msi is setup for the package } - - FTempPath := CreateTempPath; - try - try - if Assigned(FPack) then - begin - if (FPack.FileName = '') and FBuildPackage then - begin - FatalMessage('You need to save the package before building.'); - Exit; - end; - - WriteMessage('Compiling package ' + ExtractFileName(FPack.FileName) + '...'); - - if FPack.Info.Desc['Name'] = '' then - begin - FatalMessage('You need to fill in the package name before building.'); - Exit; - end; - - if FInstallerMSI <> '' then - FPack.KPSOptions.MSIFileName := ExpandFileName(FInstallerMSI); - - FInstallerMSI := FPack.KPSOptions.MSIFileName; - FMSIOptions := FPack.KPSOptions.MSIOptions; // I3126 - -// FOutputFileName := FPack.InstallerFileName; - end - else - begin - WriteMessage('Compiling installer '+ExtractFileName(FOutputFileName)+'...'); - FInstallerMSI := ExpandFileName(FInstallerMSI); - FMSIOptions := ''; // I3126 - end; - - if not FileExists(FInstallerMSI) then - begin - FatalMessage('The installer could not be built because the MSI file was missing.'); - Exit; - end; - - if (FInstallerMSI <> '') and FUpdateInstaller and Assigned(FPack) then - FPack.SaveXML; - - if FRedistSetupPath = '' then - begin - FRedistSetupPath := GetRedistSetupPath; - WriteMessage('Redist path not specified, loading default ('+FRedistSetupPath+')'); - end; - - if not FileExists(FRedistSetupPath + 'setup.exe') and - not FileExists(FRedistSetupPath + 'setup-redist.exe') then - begin - FatalMessage('Neither setup.exe nor setup-redist.exe are present in redist ('+FRedistSetupPath+').'); - Exit; - end; - - { Check the product ID for the package } - if not GetMSIOnlineProductID then Exit; - - { TODO: if the package consists of *only* kmp files, then just add those to the installer } - - { Build the package } - if Assigned(FPack) then - begin - FPackageOutputFileName := ExtractFilePath(FOutputFilename) + ChangeFileExt(ExtractFileName(FPack.FileName), '.kmp'); // I4741 - if FBuildPackage then - begin - if not DoCompilePackage(FPack, FOnMessage, True, False, FPackageOutputFileName) then Exit; - end - else if not FileExists(FPackageOutputFileName) then - begin - FatalMessage('The package file '+FPackageOutputFileName+' does not exist'); - Exit; - end; - - { Test if the keyboards in the package need to be encrypted for the installer } - - FDestFileName := FPackageOutputFileName; - end - else - FDestFileName := ''; - - { Build setup.inf } - with TStringList.Create do - try - s := '[Setup]'#13#10 + - 'Version=' + FVersion + #13#10 + - 'MSIFileName='+ExtractFileName(FInstallerMSI) + #13#10 + - 'MSIOptions='+FMSIOptions + #13#10; // I3126 - - if FAppName <> '' then - s := s + 'AppName='+FAppName + #13#10; - - if FLicense <> '' then // I2562 - s := s + 'License='+ExtractFileName(FLicense) + #13#10; - - if FTitleImage <> '' then - s := s + 'TitleImage='+ExtractFileName(FTitleImage) + #13#10; - - - if Assigned(FPack) and (FPack.KPSOptions.GraphicFile <> nil) and - SameText(ExtractFileExt(FPack.KPSOptions.GraphicFile.FileName), '.bmp') then - begin - s := s + 'BitmapFileName='+ExtractFileName(FPack.KPSOptions.GraphicFile.FileName); - end; - - if FStartDisabled then - s := s + 'StartDisabled=True'#13#10; - - if FStartWithConfiguration then - s := s + 'StartWithConfiguration=True'#13#10; - - s := s + #13#10 + - '[Packages]'#13#10; - - if Assigned(FPack) then - s := s + ExtractFileName(FDestFileName)+'='+FPack.Info.Desc[PackageInfo_Name]; - - { Iterate through the strings } - - if Assigned(FPack) then - begin - s := s + #13#10#13#10'[Strings]'#13#10; - for i := 0 to FPack.Strings.Count - 1 do - s := s + FPack.Strings[i] + #13#10; - end; - - Text := s; - - SaveToFile(FTempPath + '\setup.inf', TEncoding.UTF8); // We want UTF-8 so Title can be Unicode // I3337 - finally - Free; - end; - - { Build zip file } - - try - with TZipFile.Create do - try - Open(FTempPath + '\setup.zip', TZipMode.zmWrite); - Add(FTempPath + '\setup.inf'); - Add(FInstallerMSI); - if FLicense <> '' then Add(FLicense); // I2562 - if FTitleImage <> '' then Add(FTitleImage); - if Assigned(FPack) and (FPack.KPSOptions.GraphicFile <> nil) and - SameText(ExtractFileExt(FPack.KPSOptions.GraphicFile.FileName), '.bmp') then - Add(FPack.KPSOptions.GraphicFile.FileName); - if FDestFileName <> '' then Add(FDestFileName); - Close; - finally - Free; - end; - except - on E:EZipException do - begin - FatalMessage(E.Message); - Exit; - end; - end; - - { Create the self-extracting archive } - - with TFileStream.Create(FOutputFileName, fmCreate) do - try - // A separate version of setup.exe which doesn't include a digital signature - // is included here, so that it can be bundled with a zip and the result signed. - if FileExists(FRedistSetupPath + 'setup-redist.exe') - then FRedistSetupFile := FRedistSetupPath + 'setup-redist.exe' - else FRedistSetupFile := FRedistSetupPath + 'setup.exe'; - fs := TFileStream.Create(FRedistSetupFile, fmOpenRead or fmShareDenyWrite); - try - CopyFrom(fs, 0); - finally - fs.Free; - end; - - fs := TFileStream.Create(FTempPath + '\setup.zip', fmOpenRead or fmShareDenyWrite); - try - CopyFrom(fs, 0); - finally - fs.Free; - end; - finally - Free; - end; - except - on E:EOSError do - FatalMessage(E.Message); - end; - finally - DeleteTempPath(FTempPath); - end; -end; - -procedure TCompilePackageInstaller.WriteMessage(msg: string); -begin - FOnMessage(Self, msg, plsInfo); // I4706 -end; - -end. diff --git a/developer/src/tike/child/UfrmPackageEditor.dfm b/developer/src/tike/child/UfrmPackageEditor.dfm index 4c6967d4618..07567cfa6fd 100644 --- a/developer/src/tike/child/UfrmPackageEditor.dfm +++ b/developer/src/tike/child/UfrmPackageEditor.dfm @@ -1134,7 +1134,6 @@ inherited frmPackageEditor: TfrmPackageEditor Anchors = [akLeft, akTop, akRight] TabOrder = 2 OnClick = cbLicenseClick - ExplicitWidth = 482 end end end @@ -1351,7 +1350,7 @@ inherited frmPackageEditor: TfrmPackageEditor BevelOuter = bvNone Color = 15921906 ParentBackground = False - TabOrder = 4 + TabOrder = 3 object lblDebugHostCaption: TLabel Left = 12 Top = 70 @@ -1438,7 +1437,7 @@ inherited frmPackageEditor: TfrmPackageEditor Left = 15 Top = 274 Width = 295 - Height = 124 + Height = 276 BevelOuter = bvNone Color = 15921906 ParentBackground = False @@ -1484,74 +1483,6 @@ inherited frmPackageEditor: TfrmPackageEditor OnClick = cmdUninstallClick end end - object panBuildWindowsInstaller: TPanel - Left = 15 - Top = 418 - Width = 295 - Height = 132 - BevelOuter = bvNone - Color = 15921906 - ParentBackground = False - TabOrder = 3 - object Label9: TLabel - Left = 9 - Top = 6 - Width = 124 - Height = 17 - Caption = 'Windows Installer' - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -14 - Font.Name = 'Tahoma' - Font.Style = [fsBold] - ParentFont = False - end - object lblBootstrapMSI: TLabel - Left = 9 - Top = 69 - Width = 64 - Height = 13 - Caption = 'Keyman MSI:' - FocusControl = editBootstrapMSI - end - object lblInstallerOutputFilename: TLabel - Left = 9 - Top = 37 - Width = 82 - Height = 13 - Caption = 'Target filename:' - FocusControl = editInstallerOutputFilename - end - object editBootstrapMSI: TEdit - Left = 125 - Top = 66 - Width = 156 - Height = 21 - TabStop = False - ParentColor = True - ReadOnly = True - TabOrder = 1 - end - object editInstallerOutputFilename: TEdit - Left = 125 - Top = 34 - Width = 156 - Height = 21 - TabStop = False - ParentColor = True - ReadOnly = True - TabOrder = 0 - end - object cmdInstallWith: TButton - Left = 125 - Top = 96 - Width = 156 - Height = 25 - Caption = 'Find Keyman MSI...' - TabOrder = 2 - OnClick = cmdInstallWithClick - end - end object panOpenInExplorer: TPanel Left = 15 Top = 187 @@ -1641,22 +1572,13 @@ inherited frmPackageEditor: TfrmPackageEditor ReadOnly = True TabOrder = 0 end - object cmdCompileInstaller: TButton - Left = 148 - Top = 32 - Width = 133 - Height = 25 - Caption = 'Compile I&nstaller' - TabOrder = 1 - OnClick = cmdCompileInstallerClick - end object cmdAddToProject: TButton - Left = 287 + Left = 148 Top = 32 Width = 133 Height = 25 Action = modActionsMain.actProjectAddCurrentEditorFile - TabOrder = 2 + TabOrder = 1 end object cmdBuildPackage: TButton Left = 9 @@ -1664,7 +1586,7 @@ inherited frmPackageEditor: TfrmPackageEditor Width = 133 Height = 25 Caption = 'Compile &Package' - TabOrder = 3 + TabOrder = 2 OnClick = cmdBuildPackageClick end end @@ -1685,12 +1607,4 @@ inherited frmPackageEditor: TfrmPackageEditor Left = 32 Top = 532 end - object dlgOpenProductInstaller: TOpenDialog - DefaultExt = 'msi' - Filter = 'Product Installer Files (*.msi)|*.msi|All Files (*.*)|*.*' - Options = [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing] - Title = 'Select Product Installer' - Left = 32 - Top = 456 - end end diff --git a/developer/src/tike/child/UfrmPackageEditor.pas b/developer/src/tike/child/UfrmPackageEditor.pas index d11cee99abe..7d4faabe90c 100644 --- a/developer/src/tike/child/UfrmPackageEditor.pas +++ b/developer/src/tike/child/UfrmPackageEditor.pas @@ -69,7 +69,6 @@ interface TfrmPackageEditor = class(TfrmTikeEditor) // I4689 dlgFiles: TOpenDialog; dlgNewCustomisation: TSaveDialog; - dlgOpenProductInstaller: TOpenDialog; pages: TLeftTabbedPageControl; pageFiles: TTabSheet; pageDetails: TTabSheet; @@ -169,13 +168,6 @@ TfrmPackageEditor = class(TfrmTikeEditor) // I4689 lblCompileTargetHeader: TLabel; cmdInstall: TButton; cmdUninstall: TButton; - panBuildWindowsInstaller: TPanel; - Label9: TLabel; - lblBootstrapMSI: TLabel; - lblInstallerOutputFilename: TLabel; - editBootstrapMSI: TEdit; - editInstallerOutputFilename: TEdit; - cmdInstallWith: TButton; pageLexicalModels: TTabSheet; panLexicalModels: TPanel; lblLexlicalModels: TLabel; @@ -200,7 +192,6 @@ TfrmPackageEditor = class(TfrmTikeEditor) // I4689 panFileActions: TPanel; lblFileActions: TLabel; editOutPath: TEdit; - cmdCompileInstaller: TButton; cmdAddToProject: TButton; cmdBuildPackage: TButton; Label5: TLabel; @@ -256,8 +247,6 @@ TfrmPackageEditor = class(TfrmTikeEditor) // I4689 procedure cmdUninstallClick(Sender: TObject); procedure cmdOpenContainingFolderClick(Sender: TObject); procedure cmdOpenFileClick(Sender: TObject); - procedure cmdCompileInstallerClick(Sender: TObject); - procedure cmdInstallWithClick(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure pagesChanging(Sender: TObject; var AllowChange: Boolean); @@ -395,7 +384,6 @@ implementation CharMapDropTool, CharMapInsertMode, - CompilePackageInstaller, Keyman.Developer.System.Project.kpsProjectFile, Keyman.Developer.System.Project.kpsProjectFileAction, Keyman.Developer.System.ServerAPI, @@ -492,17 +480,6 @@ procedure TfrmPackageEditor.SourceChanged(Sender: TObject); Modified := True; end; -procedure TfrmPackageEditor.cmdCompileInstallerClick(Sender: TObject); -begin - if Untitled or Modified then // I2178 - ShowMessage('You must save the package before you can build it.') - else - begin - frmMessages.Clear; - DoAction(pfaCompileInstaller); - end; -end; - procedure TfrmPackageEditor.cmdCopyDebuggerLinkClick(Sender: TObject); begin try @@ -1267,17 +1244,6 @@ procedure TfrmPackageEditor.cmdInstallClick(Sender: TObject); DoAction(pfaInstall); end; -procedure TfrmPackageEditor.cmdInstallWithClick(Sender: TObject); -begin - dlgOpenProductInstaller.FileName := pack.KPSOptions.MSIFileName; - if dlgOpenProductInstaller.Execute then - begin - pack.KPSOptions.MSIFileName := dlgOpenProductInstaller.FileName; - Modified := True; - UpdateData; - end; -end; - {------------------------------------------------------------------------------- - Display refresh routines - -------------------------------------------------------------------------------} @@ -1350,10 +1316,6 @@ procedure TfrmPackageEditor.UpdateData; editStartMenuPath.Text := pack.StartMenu.Path; editOutPath.Text := (ProjectFile as TkpsProjectFile).TargetFilename; // I4688 - editBootstrapMSI.Text := pack.KPSOptions.MSIFileName; - if pack.KPSOptions.MSIFileName = '' - then editInstallerOutputFilename.Text := '' - else editInstallerOutputFilename.Text := (ProjectFile as TkpsProjectFile).TargetInstallerFileName; // I4688 if lbFiles.Items.Count > 0 then lbFiles.ItemIndex := 0; lbFilesClick(lbFiles); @@ -1983,7 +1945,6 @@ procedure TfrmPackageEditor.RefreshTargetPanels; end; panBuildDesktop.Visible := FHasDesktopTarget; - panBuildWindowsInstaller.Visible := FHasDesktopTarget; panBuildMobile.Visible := FHasMobileTarget; end; diff --git a/developer/src/tike/project/Keyman.Developer.System.Project.kpsProjectFileAction.pas b/developer/src/tike/project/Keyman.Developer.System.Project.kpsProjectFileAction.pas index 1f681f28c07..c7a7cafcc5c 100644 --- a/developer/src/tike/project/Keyman.Developer.System.Project.kpsProjectFileAction.pas +++ b/developer/src/tike/project/Keyman.Developer.System.Project.kpsProjectFileAction.pas @@ -15,24 +15,13 @@ interface type TkpsProjectFileAction = class(TkpsProjectFile) - private - procedure SelfMessage(Sender: TObject; msg: string; State: TProjectLogState); // I4706 - public - function CompilePackageInstaller(APack: TKPSFile; FSilent: Boolean): Boolean; function CompilePackage: Boolean; function Clean: Boolean; end; implementation -uses - compile, - CompilePackageInstaller, - Keyman.Developer.System.ValidateKpsFile, - PackageInfo, - utilexecute; - function TkpsProjectFileAction.CompilePackage: Boolean; var w: TKmcWrapper; @@ -46,45 +35,6 @@ function TkpsProjectFileAction.CompilePackage: Boolean; end; end; -function TkpsProjectFileAction.CompilePackageInstaller(APack: TKPSFile; FSilent: Boolean): Boolean; -var - pack: TKPSFile; -begin - HasCompileWarning := False; // I4706 - - if APack = nil then - begin - pack := TKPSFile.Create; - pack.FileName := FileName; - pack.LoadXML; - end - else - pack := APack; - - try - try - Result := DoCompilePackageInstaller(pack, SelfMessage, FSilent, '', TargetInstallerFilename, '', False, True, '', '', '', False, False); - if HasCompileWarning and (WarnAsError or OwnerProject.Options.CompilerWarningsAsErrors) then // I4706 - Result := False; - - if Result - then Log(plsSuccess, '''' + FileName + ''' compiled successfully.', 0, 0) - else Log(plsFailure, '''' + FileName + ''' was not compiled successfully.', 0, 0); - except - on E:Exception do - begin - Log(plsError, E.Message, CERR_ERROR, 0); - Log(plsFailure, '''' + FileName + ''' was not compiled successfully.', 0, 0); - Result := False; - end; - end; - - finally - if APack = nil then - pack.Free; - end; -end; - function TkpsProjectFileAction.Clean: Boolean; begin CleanFile(OutputFileName); @@ -92,13 +42,6 @@ function TkpsProjectFileAction.Clean: Boolean; Result := True; end; -procedure TkpsProjectFileAction.SelfMessage(Sender: TObject; msg: string; State: TProjectLogState); // I4706 -begin - if State = plsWarning then - HasCompileWarning := True; - Log(State, msg, 0, 0); -end; - initialization RegisterProjectFileType('.kps', TkpsProjectFileAction); end. diff --git a/developer/src/tike/project/Keyman.Developer.UI.Project.ProjectFileUI.pas b/developer/src/tike/project/Keyman.Developer.UI.Project.ProjectFileUI.pas index 50321c6bf4c..6026fb2377e 100644 --- a/developer/src/tike/project/Keyman.Developer.UI.Project.ProjectFileUI.pas +++ b/developer/src/tike/project/Keyman.Developer.UI.Project.ProjectFileUI.pas @@ -34,7 +34,7 @@ interface type TProjectFileAction = (pfaCompile, pfaInstall, pfaUninstall, pfaDebug, - pfaTestKeymanWeb, pfaCompileInstaller, pfaFontHelper, pfaFontDialog, pfaClean); // I4057 + pfaTestKeymanWeb, pfaFontHelper, pfaFontDialog, pfaClean); // I4057 TProjectUI = class(TProject) private diff --git a/developer/src/tike/project/Keyman.Developer.UI.Project.UfrmProject.pas b/developer/src/tike/project/Keyman.Developer.UI.Project.UfrmProject.pas index ad0fc42ec32..992a4491c36 100644 --- a/developer/src/tike/project/Keyman.Developer.UI.Project.UfrmProject.pas +++ b/developer/src/tike/project/Keyman.Developer.UI.Project.UfrmProject.pas @@ -549,21 +549,6 @@ procedure TfrmProject.WebCommandProject(Command: WideString; Params: TStringList (FGlobalProject.Files[i].UI as TProjectFileUI).DoAction(pfaCompile, False); end; end - else if Command = 'package_compileallinstallers' then // I4734 - begin - ClearMessages; - for i := 0 to FGlobalProject.Files.Count - 1 do - begin - if FGlobalProject.Files[i] is TkpsProjectFile then - (FGlobalProject.Files[i].UI as TProjectFileUI).DoAction(pfaCompileInstaller, False); - end; - end - else if Command = 'package_compileinstaller' then - begin - ClearMessages; - pf := SelectedProjectFile; - if Assigned(pf) then (pf.UI as TProjectFileUI).DoAction(pfaCompileInstaller, False); - end else if Command = 'package_cleanall' then // I4692 begin ClearMessages; diff --git a/developer/src/tike/project/Keyman.Developer.UI.Project.kpsProjectFileUI.pas b/developer/src/tike/project/Keyman.Developer.UI.Project.kpsProjectFileUI.pas index 672a8c92bfa..410a2727252 100644 --- a/developer/src/tike/project/Keyman.Developer.UI.Project.kpsProjectFileUI.pas +++ b/developer/src/tike/project/Keyman.Developer.UI.Project.kpsProjectFileUI.pas @@ -35,9 +35,7 @@ TkpsProjectFileUI = class(TOpenableProjectFileUI) function InstallPackage: Boolean; function UninstallPackage: Boolean; function CompilePackage: Boolean; - function CompilePackageInstaller(FSilent: Boolean): Boolean; - function GetPack: TKPSFile; function GetProjectFile: TkpsProjectFileAction; function TestPackageState(FCompiledName: string): Boolean; public @@ -83,22 +81,12 @@ function TkpsProjectFileUI.CompilePackage: Boolean; TestPackageOnline; end; -function TkpsProjectFileUI.CompilePackageInstaller(FSilent: Boolean): Boolean; -begin - Result := False; - if ProjectFile.Modified then - if not modActionsMain.actFileSave.Execute then Exit; - - Result := ProjectFile.CompilePackageInstaller(GetPack, FSilent); -end; - function TkpsProjectFileUI.DoAction(action: TProjectFileAction; FSilent: Boolean): Boolean; begin case action of pfaCompile: Result := CompilePackage; pfaInstall: Result := InstallPackage; pfaUninstall: Result := UninstallPackage; - pfaCompileInstaller: Result := CompilePackageInstaller(FSilent); pfaClean: Result := ProjectFile.Clean; pfaTestKeymanWeb: Result := TestPackageOnline; else @@ -106,13 +94,6 @@ function TkpsProjectFileUI.DoAction(action: TProjectFileAction; FSilent: Boolean end; end; -function TkpsProjectFileUI.GetPack: TKPSFile; -begin - if Assigned(MDIChild) - then with MDIChild as TfrmPackageEditor do Result := GetPack - else Result := nil; -end; - function TkpsProjectFileUI.GetProjectFile: TkpsProjectFileAction; begin Result := FOwner as TkpsProjectFileAction; diff --git a/developer/src/tike/tike.dpr b/developer/src/tike/tike.dpr index c3c417a8170..15993827af9 100644 --- a/developer/src/tike/tike.dpr +++ b/developer/src/tike/tike.dpr @@ -16,7 +16,6 @@ uses compile in '..\common\delphi\compiler\compile.pas', KeymanDeveloperOptions in 'main\KeymanDeveloperOptions.pas', UfrmKeyTest in 'debug\UfrmKeyTest.pas' {frmKeyTest}, - CompilePackage in '..\common\delphi\compiler\CompilePackage.pas', KeymanDeveloperUtils in 'main\KeymanDeveloperUtils.pas', UfrmEditor in 'child\UfrmEditor.pas' {frmEditor}, MenuImgList in '..\common\delphi\components\MenuImgList.pas', @@ -138,7 +137,6 @@ uses VisualKeyboardExportPNG in '..\..\..\common\windows\delphi\visualkeyboard\VisualKeyboardExportPNG.pas', MSXML2_TLB in '..\..\..\common\windows\delphi\tlb\MSXML2_TLB.pas', CharacterInfo in 'main\CharacterInfo.pas', - CompilePackageInstaller in '..\common\delphi\compiler\CompilePackageInstaller.pas', UTikeDebugMode in 'main\UTikeDebugMode.pas', kmxfileconsts in '..\..\..\common\windows\delphi\keyboards\kmxfileconsts.pas', kmxfileutils in '..\..\..\common\windows\delphi\keyboards\kmxfileutils.pas', diff --git a/developer/src/tike/tike.dproj b/developer/src/tike/tike.dproj index f1af6898566..1f5ff54b221 100644 --- a/developer/src/tike/tike.dproj +++ b/developer/src/tike/tike.dproj @@ -139,7 +139,6 @@

frmKeyTest -
frmEditor
@@ -319,7 +318,6 @@ - diff --git a/developer/src/tike/xml/project/distribution.xsl b/developer/src/tike/xml/project/distribution.xsl index 6b78ee608f9..998065b8427 100644 --- a/developer/src/tike/xml/project/distribution.xsl +++ b/developer/src/tike/xml/project/distribution.xsl @@ -97,10 +97,6 @@ Build keyman:compilefile?id= - - Build installer - keyman:package_compileinstaller?id= - Clean keyman:cleanfile?id= diff --git a/developer/src/tike/xml/project/packages.xsl b/developer/src/tike/xml/project/packages.xsl index 94d45113ccf..ff5a8e520a6 100644 --- a/developer/src/tike/xml/project/packages.xsl +++ b/developer/src/tike/xml/project/packages.xsl @@ -9,7 +9,7 @@

- +
New package... @@ -90,7 +90,7 @@ auto - +

@@ -106,7 +106,7 @@
- + @@ -121,12 +121,6 @@ Build keyman:compilefile?id=
- - - Build installer - keyman:package_compileinstaller?id= - - Clean keyman:cleanfile?id= @@ -154,7 +148,7 @@ - + @@ -196,5 +190,5 @@
- + \ No newline at end of file