From e2dbbc9aa8bfd8c046e45a533cb30b9dac112bb3 Mon Sep 17 00:00:00 2001 From: mark-sil Date: Wed, 25 Jun 2025 14:23:27 -0400 Subject: [PATCH] LT-21960: Fix COM problem with VwPropertyStore Instead of using COM we added a wrapper class that uses DllImport to create and call methods on the VwPropertyStore object. Change-Id: I8681ad9140a3b5a887b1ba672dae9b58dab55a75 --- .../Controls/Widgets/FontHeightAdjuster.cs | 2 +- .../FwUtilsTests/TestFwStylesheetTests.cs | 4 +- Src/Common/SimpleRootSite/EditingHelper.cs | 2 +- .../ViewsInterfaces/ViewsInterfaces.csproj | 3 +- .../ViewsInterfaces/VwPropertyStoreManaged.cs | 101 ++++++++++++++++++ Src/views/Views.idh | 18 ---- Src/views/VwPropertyStore.cpp | 25 +++++ 7 files changed, 132 insertions(+), 23 deletions(-) create mode 100644 Src/Common/ViewsInterfaces/VwPropertyStoreManaged.cs diff --git a/Src/Common/Controls/Widgets/FontHeightAdjuster.cs b/Src/Common/Controls/Widgets/FontHeightAdjuster.cs index 7f28eb6303..9cd5662fed 100644 --- a/Src/Common/Controls/Widgets/FontHeightAdjuster.cs +++ b/Src/Common/Controls/Widgets/FontHeightAdjuster.cs @@ -165,7 +165,7 @@ public static LgCharRenderProps GetChrpForStyle(string styleName, IVwStylesheet } } - IVwPropertyStore vwps = VwPropertyStoreClass.Create(); + VwPropertyStoreManaged vwps = new VwPropertyStoreManaged(); vwps.Stylesheet = styleSheet; vwps.WritingSystemFactory = writingSystemFactory; diff --git a/Src/Common/FwUtils/FwUtilsTests/TestFwStylesheetTests.cs b/Src/Common/FwUtils/FwUtilsTests/TestFwStylesheetTests.cs index 7319e61d7a..4ecb487a34 100644 --- a/Src/Common/FwUtils/FwUtilsTests/TestFwStylesheetTests.cs +++ b/Src/Common/FwUtils/FwUtilsTests/TestFwStylesheetTests.cs @@ -127,7 +127,7 @@ public void TestOverrideFontForWritingSystem_ForStyleWithNullProps() stylesheet.OverrideFontsForWritingSystems("FirstStyle", fontOverrides); //check results - IVwPropertyStore vwps = VwPropertyStoreClass.Create(); + VwPropertyStoreManaged vwps = new VwPropertyStoreManaged(); vwps.Stylesheet = stylesheet; vwps.WritingSystemFactory = wsf; @@ -190,7 +190,7 @@ public void TestOverrideFontsForWritingSystems_ForStyleWithProps() stylesheet.OverrideFontsForWritingSystems("FirstStyle", fontOverrides); //check results - IVwPropertyStore vwps = VwPropertyStoreClass.Create(); + VwPropertyStoreManaged vwps = new VwPropertyStoreManaged(); vwps.Stylesheet = stylesheet; vwps.WritingSystemFactory = wsf; diff --git a/Src/Common/SimpleRootSite/EditingHelper.cs b/Src/Common/SimpleRootSite/EditingHelper.cs index 1b022df1dd..b033e29dd7 100644 --- a/Src/Common/SimpleRootSite/EditingHelper.cs +++ b/Src/Common/SimpleRootSite/EditingHelper.cs @@ -1536,7 +1536,7 @@ public static Font GetFontForNormalStyle(int hvoWs, IVwStylesheet styleSheet, ttpBldr.SetIntPropValues((int)FwTextPropType.ktptWs, 0, hvoWs); ITsTextProps ttp = ttpBldr.GetTextProps(); - IVwPropertyStore vwps = VwPropertyStoreClass.Create(); + VwPropertyStoreManaged vwps = new VwPropertyStoreManaged(); vwps.Stylesheet = styleSheet; vwps.WritingSystemFactory = wsf; LgCharRenderProps chrps = vwps.get_ChrpFor(ttp); diff --git a/Src/Common/ViewsInterfaces/ViewsInterfaces.csproj b/Src/Common/ViewsInterfaces/ViewsInterfaces.csproj index 312155117d..18fbdb2c0d 100644 --- a/Src/Common/ViewsInterfaces/ViewsInterfaces.csproj +++ b/Src/Common/ViewsInterfaces/ViewsInterfaces.csproj @@ -1,4 +1,4 @@ - + Local @@ -163,6 +163,7 @@ Code + Designer diff --git a/Src/Common/ViewsInterfaces/VwPropertyStoreManaged.cs b/Src/Common/ViewsInterfaces/VwPropertyStoreManaged.cs new file mode 100644 index 0000000000..e61d882624 --- /dev/null +++ b/Src/Common/ViewsInterfaces/VwPropertyStoreManaged.cs @@ -0,0 +1,101 @@ +// Copyright (c) 2002-2025 SIL International +// This software is licensed under the LGPL, version 2.1 or later +// (http://www.gnu.org/licenses/lgpl-2.1.html) + +using System; +using System.Runtime.InteropServices; +using System.Threading; +using SIL.LCModel.Core.KernelInterfaces; + +namespace SIL.FieldWorks.Common.ViewsInterfaces +{ + /// + public sealed class VwPropertyStoreManaged : IDisposable + { + private const string _viewsDllPath = "views.dll"; + private IntPtr pVwPropStore; + + // Detect redundant Dispose() calls in a thread-safe manner. + // _isDisposed == 0 means Dispose(bool) has not been called yet. + // _isDisposed == 1 means Dispose(bool) has already been called. + private int _isDisposed; + + /// + public VwPropertyStoreManaged() + { + pVwPropStore = VwPropertyStore_Create(); + } + + /// + public IVwStylesheet Stylesheet + { + set + { + VwPropertyStore_Stylesheet(pVwPropStore, value); + } + } + + /// + public ILgWritingSystemFactory WritingSystemFactory + { + set + { + VwPropertyStore_WritingSystemFactory(pVwPropStore, value); + } + } + + /// + public LgCharRenderProps get_ChrpFor(ITsTextProps ttp) + { + IntPtr pInt = VwPropertyStore_get_ChrpFor(pVwPropStore, ttp); + return (LgCharRenderProps)Marshal.PtrToStructure(pInt, typeof(LgCharRenderProps)); + } + + #region Disposable stuff + /// + ~VwPropertyStoreManaged() => Dispose(false); + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + private void Dispose(bool disposing) + { + if (Interlocked.CompareExchange(ref _isDisposed, 1, 0) == 0) + { + // Dispose managed resources (if there are any). + if (disposing) + { + } + + // Dispose unmanaged resources. + VwPropertyStore_Delete(pVwPropStore); + } + } + #endregion + + #region DLLImport stuff + [DllImport(_viewsDllPath, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr VwPropertyStore_Create(); + + [DllImport(_viewsDllPath, CallingConvention = CallingConvention.Cdecl)] + private static extern void VwPropertyStore_Delete(IntPtr pVwPropStore); + + [DllImport(_viewsDllPath, CallingConvention = CallingConvention.Cdecl)] + private static extern void VwPropertyStore_Stylesheet(IntPtr pVwPropStore, + [MarshalAs(UnmanagedType.Interface)] IVwStylesheet pss); + + [DllImport(_viewsDllPath, CallingConvention = CallingConvention.Cdecl)] + private static extern void VwPropertyStore_WritingSystemFactory(IntPtr pVwPropStore, + [MarshalAs(UnmanagedType.Interface)] ILgWritingSystemFactory pwsf); + + [DllImport(_viewsDllPath, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr VwPropertyStore_get_ChrpFor(IntPtr pVwPropStore, + [MarshalAs(UnmanagedType.Interface)] ITsTextProps _ttp); + #endregion + } +} diff --git a/Src/views/Views.idh b/Src/views/Views.idh index 26cc5793d8..b052958cc9 100644 --- a/Src/views/Views.idh +++ b/Src/views/Views.idh @@ -3429,28 +3429,10 @@ Last reviewed: [propget] HRESULT StringProperty( [in] int sp, [out, retval] BSTR * bstrValue); - // Get the LgCharRenderProps that this property store would produce for the - // specified pttp. The pttp should specify the writing system and ows that the properties - // are wanted for. - [propget] HRESULT ChrpFor( - [in] ITsTextProps * pttp, - [out, retval] LgCharRenderProps * pchrp); - // Set the style sheet that this property store will use to interpret - [propputref] HRESULT Stylesheet( - [in] IVwStylesheet * pvps); - - // Set the writing system factory that this property store uses. - [propputref] HRESULT WritingSystemFactory( - [in] ILgWritingSystemFactory * pwsf); // Get the property store that this one was derived from. [propget] HRESULT ParentStore([out, retval]IVwPropertyStore ** ppvps); - // Gets an ${ITsTextProps} interface pointer on an ITsTextProps object whose properties are - // those currently in the store. In particular, if the current VwPropertyStore has just - // been created and not changed, the properties will be the system default properties. - [propget] HRESULT TextProps([out,retval] ITsTextProps ** ppttp); - // Get the actual, working value of some string-valued property. [propget] HRESULT DerivedPropertiesForTtp( [in] ITsTextProps * pttp, diff --git a/Src/views/VwPropertyStore.cpp b/Src/views/VwPropertyStore.cpp index 4432adcf7d..20a047f005 100644 --- a/Src/views/VwPropertyStore.cpp +++ b/Src/views/VwPropertyStore.cpp @@ -55,6 +55,31 @@ static const int s_ctptWsStyleProps = (isizeof(s_rgtptWsStyleProps) / isizeof(in // Magic font strings that are used in markup: static OleStringLiteral g_pszDefaultFont(L""); +//:>******************************************************************************************** +//:> DllExports +//:>******************************************************************************************** +extern "C" _declspec(dllexport) void* VwPropertyStore_Create() { + return (void*)NewObj VwPropertyStore(); +} + +extern "C" _declspec(dllexport) void VwPropertyStore_Delete(VwPropertyStore* t) { + delete t; +} + +extern "C" _declspec(dllexport) void VwPropertyStore_Stylesheet(VwPropertyStore* t, IVwStylesheet* pss) { + t->putref_Stylesheet(pss); +} + +extern "C" _declspec(dllexport) void VwPropertyStore_WritingSystemFactory(VwPropertyStore* t, ILgWritingSystemFactory* pwsf) { + t->putref_WritingSystemFactory(pwsf); +} + +extern "C" _declspec(dllexport) LgCharRenderProps* VwPropertyStore_get_ChrpFor(VwPropertyStore* t, ITsTextProps* pttp) { + LgCharRenderProps* pchrp = NewObj LgCharRenderProps(); + t->get_ChrpFor(pttp, pchrp); + return pchrp; +} + //:>******************************************************************************************** //:> Constructor/Destructor //:>********************************************************************************************