From aea7ff4f05f6384826370de782fbdd44c51d1b92 Mon Sep 17 00:00:00 2001
From: Eugene Wang <8755753+soukoku@users.noreply.github.com>
Date: Mon, 3 Apr 2023 23:06:10 -0400
Subject: [PATCH] Started on caps support.
---
src/NTwain/Data/TWAINH.cs | 5 +-
src/NTwain/Data/TWAINH_EXTRAS.cs | 47 ++++-
src/NTwain/IMemoryManager.cs | 16 ++
src/NTwain/Triplets/ControlDATs/Capability.cs | 2 +
src/NTwain/TwainSession.Caps.cs | 175 ++++++++++++++++++
src/NTwain/TwainSession.Memory.cs | 2 +-
src/NTwain/TwainSession.cs | 2 +-
7 files changed, 236 insertions(+), 13 deletions(-)
create mode 100644 src/NTwain/IMemoryManager.cs
create mode 100644 src/NTwain/TwainSession.Caps.cs
diff --git a/src/NTwain/Data/TWAINH.cs b/src/NTwain/Data/TWAINH.cs
index a21cf07..464b7fa 100644
--- a/src/NTwain/Data/TWAINH.cs
+++ b/src/NTwain/Data/TWAINH.cs
@@ -1148,7 +1148,7 @@ namespace NTwain.Data
/// Used by application to get/set capability from/in a data source.
///
[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)]
- public struct TW_CAPABILITY
+ public partial struct TW_CAPABILITY
{
public CAP Cap;
public TWON ConType;
@@ -2557,6 +2557,7 @@ namespace NTwain.Data
///
/// Flags used in TW_MEMORY structure.
///
+ [Flags]
public enum TWMF : ushort
{
APPOWNS = 0x0001,
@@ -3778,6 +3779,7 @@ namespace NTwain.Data
///
/// Data Groups...
///
+ [Flags]
public enum DG : uint
{
CONTROL = 0x1,
@@ -4327,6 +4329,7 @@ namespace NTwain.Data
/// bit patterns: for query the operation that are supported by the data source on a capability
/// Application gets these through DG_CONTROL/DAT_CAPABILITY/MSG_QUERYSUPPORT
///
+ [Flags]
public enum TWQC : ushort
{
Unknown = 0,
diff --git a/src/NTwain/Data/TWAINH_EXTRAS.cs b/src/NTwain/Data/TWAINH_EXTRAS.cs
index 1745f52..00e217d 100644
--- a/src/NTwain/Data/TWAINH_EXTRAS.cs
+++ b/src/NTwain/Data/TWAINH_EXTRAS.cs
@@ -606,16 +606,28 @@ namespace NTwain.Data
partial struct TW_STATUSUTF8
{
///
- /// Tries to read the text content and frees the memory.
+ /// Frees the memory if necessary.
///
- ///
+ ///
+ public void Free(IMemoryManager mgr)
+ {
+ // session already checks for zero
+ mgr.Free(UTF8string);
+ UTF8string = IntPtr.Zero;
+ }
+
+ ///
+ /// Tries to read the text content and optionally frees the memory.
+ ///
+ ///
+ /// Whether to free the pointer after reads.
///
- public string? ReadAndFree(TwainSession session)
+ public string? Read(IMemoryManager mgr, bool freeMemory = true)
{
string? val = null;
if (UTF8string != IntPtr.Zero && Size > 0)
{
- var locked = session.Lock(UTF8string);
+ var locked = mgr.Lock(UTF8string);
if (locked != IntPtr.Zero)
{
// does this work? who knows.
@@ -637,22 +649,37 @@ namespace NTwain.Data
}
finally
{
- session.Unlock(UTF8string);
+ mgr.Unlock(UTF8string);
}
}
}
- Free(session);
+ if (freeMemory) Free(mgr);
return val;
}
+ }
+
+ partial struct TW_CAPABILITY
+ {
+ public TW_CAPABILITY(CAP cap)
+ {
+ Cap = cap;
+ ConType = (TWON)TwainConst.TWON_DONTCARE16;
+ }
///
/// Frees the memory if necessary.
///
- ///
- public void Free(TwainSession session)
+ ///
+ public void Free(IMemoryManager mgr)
{
- session.Free(UTF8string);
- UTF8string = IntPtr.Zero;
+ // session already checks for zero
+ mgr.Free(hContainer);
+ hContainer = IntPtr.Zero;
+ }
+
+ public void Read(IMemoryManager mgr, bool freeMemory = true)
+ {
+ if (freeMemory) Free(mgr);
}
}
diff --git a/src/NTwain/IMemoryManager.cs b/src/NTwain/IMemoryManager.cs
new file mode 100644
index 0000000..252a9dc
--- /dev/null
+++ b/src/NTwain/IMemoryManager.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace NTwain
+{
+ ///
+ /// Something that can do the 4 memory mgmt
+ /// things required by TWAIN.
+ ///
+ public interface IMemoryManager
+ {
+ IntPtr Alloc(uint size);
+ void Free(IntPtr handle);
+ IntPtr Lock(IntPtr handle);
+ void Unlock(IntPtr handle);
+ }
+}
\ No newline at end of file
diff --git a/src/NTwain/Triplets/ControlDATs/Capability.cs b/src/NTwain/Triplets/ControlDATs/Capability.cs
index 668cef6..2915c81 100644
--- a/src/NTwain/Triplets/ControlDATs/Capability.cs
+++ b/src/NTwain/Triplets/ControlDATs/Capability.cs
@@ -28,6 +28,8 @@ namespace NTwain.Triplets.ControlDATs
=> DoIt(ref app, ref ds, MSG.RESETALL, ref data);
public STS Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data)
=> DoIt(ref app, ref ds, MSG.SET, ref data);
+ public STS SetConstraint(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data)
+ => DoIt(ref app, ref ds, MSG.SETCONSTRAINT, ref data);
static STS DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_CAPABILITY data)
{
diff --git a/src/NTwain/TwainSession.Caps.cs b/src/NTwain/TwainSession.Caps.cs
new file mode 100644
index 0000000..844913b
--- /dev/null
+++ b/src/NTwain/TwainSession.Caps.cs
@@ -0,0 +1,175 @@
+using NTwain.Data;
+using NTwain.Triplets;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace NTwain
+{
+ // this file contains capability mgmt methods
+
+ partial class TwainSession
+ {
+ /////
+ ///// Gets all the supported caps for the current source.
+ /////
+ /////
+ //public IEnumerable GetAllCaps()
+ //{
+ // // just as a sample of how to read cap values
+
+ // if (GetCapValues(CAP.CAP_SUPPORTEDCAPS, out TW_CAPABILITY value) == STS.SUCCESS)
+ // {
+ // value.Read(this);
+ // }
+ // return Enumerable.Empty();
+ //}
+
+ ///
+ /// Gets a CAP's actual supported operations.
+ /// This is not supported by all sources.
+ ///
+ ///
+ ///
+ public TWQC QueryCapSupport(CAP cap)
+ {
+ var value = new TW_CAPABILITY(cap);
+ if (DGControl.Capability.QuerySupport(ref _appIdentity, ref _currentDS, ref value) == STS.SUCCESS)
+ {
+ value.Read(this);
+ }
+ return TWQC.Unknown;
+ }
+
+ ///
+ /// Gets a CAP's current value.
+ /// Caller will need to free the memory.
+ ///
+ ///
+ ///
+ ///
+ public STS GetCapCurrent(CAP cap, out TW_CAPABILITY value)
+ {
+ value = new TW_CAPABILITY(cap);
+ return DGControl.Capability.Get(ref _appIdentity, ref _currentDS, ref value);
+ }
+
+ ///
+ /// Gets a CAP's default value.
+ /// Caller will need to free the memory.
+ ///
+ ///
+ ///
+ ///
+ public STS GetCapDefault(CAP cap, out TW_CAPABILITY value)
+ {
+ value = new TW_CAPABILITY(cap);
+ return DGControl.Capability.GetDefault(ref _appIdentity, ref _currentDS, ref value);
+ }
+
+ ///
+ /// Gets a CAP's supported values.
+ /// Caller will need to free the memory.
+ ///
+ ///
+ ///
+ ///
+ public STS GetCapValues(CAP cap, out TW_CAPABILITY value)
+ {
+ value = new TW_CAPABILITY(cap);
+ return DGControl.Capability.Get(ref _appIdentity, ref _currentDS, ref value);
+ }
+
+ ///
+ /// Gets a CAP's help text (description).
+ ///
+ ///
+ ///
+ ///
+ public STS GetCapHelp(CAP cap, out string? help)
+ {
+ help = null;
+ var value = new TW_CAPABILITY(cap);
+ var rc = DGControl.Capability.GetHelp(ref _appIdentity, ref _currentDS, ref value);
+ value.Free(this);
+ return rc;
+ }
+
+ ///
+ /// Gets a CAP's text name label.
+ ///
+ ///
+ ///
+ ///
+ public STS GetCapLabel(CAP cap, out string? label)
+ {
+ label = null;
+ var value = new TW_CAPABILITY(cap);
+ var rc = DGControl.Capability.GetLabel(ref _appIdentity, ref _currentDS, ref value);
+ value.Free(this);
+ return rc;
+ }
+
+ ///
+ /// Gets a CAP's value label texts.
+ ///
+ ///
+ ///
+ ///
+ public STS GetCapLabelEnum(CAP cap, out string[]? labels)
+ {
+ labels = null;
+ var value = new TW_CAPABILITY(cap);
+ var rc = DGControl.Capability.GetLabelEnum(ref _appIdentity, ref _currentDS, ref value);
+ value.Free(this);
+ return rc;
+ }
+
+ ///
+ /// Sets a CAP's current value.
+ ///
+ ///
+ ///
+ public STS SetCap(ref TW_CAPABILITY value)
+ {
+ var rc = DGControl.Capability.Set(ref _appIdentity, ref _currentDS, ref value);
+ value.Free(this);
+ return rc;
+ }
+
+ ///
+ /// Sets a CAP's constraint values.
+ ///
+ ///
+ ///
+ public STS SetConstraint(ref TW_CAPABILITY value)
+ {
+ var rc = DGControl.Capability.SetConstraint(ref _appIdentity, ref _currentDS, ref value);
+ value.Free(this);
+ return rc;
+ }
+
+ ///
+ /// Resets a CAP's current value to power-on default.
+ /// Caller will need to free the memory.
+ ///
+ ///
+ ///
+ ///
+ public STS ResetCap(CAP cap, out TW_CAPABILITY value)
+ {
+ value = new TW_CAPABILITY(cap);
+ return DGControl.Capability.Reset(ref _appIdentity, ref _currentDS, ref value);
+ }
+
+ ///
+ /// Resets all CAP values and constraint to power-on defaults.
+ ///
+ ///
+ public STS ResetAllCaps()
+ {
+ var value = new TW_CAPABILITY(CAP.CAP_SUPPORTEDCAPS);
+ var rc = DGControl.Capability.ResetAll(ref _appIdentity, ref _currentDS, ref value);
+ return rc;
+ }
+ }
+}
diff --git a/src/NTwain/TwainSession.Memory.cs b/src/NTwain/TwainSession.Memory.cs
index 595a11c..597974a 100644
--- a/src/NTwain/TwainSession.Memory.cs
+++ b/src/NTwain/TwainSession.Memory.cs
@@ -7,7 +7,7 @@ namespace NTwain
{
// this file contains memory methods
- partial class TwainSession
+ partial class TwainSession : IMemoryManager
{
internal TW_ENTRYPOINT_DELEGATES _entryPoint;
diff --git a/src/NTwain/TwainSession.cs b/src/NTwain/TwainSession.cs
index 2759fb6..0ea4682 100644
--- a/src/NTwain/TwainSession.cs
+++ b/src/NTwain/TwainSession.cs
@@ -256,7 +256,7 @@ namespace NTwain
{
if (DGControl.StatusUtf8.Get(ref _appIdentity, status, out TW_STATUSUTF8 extendedStatus) == STS.SUCCESS)
{
- return extendedStatus.ReadAndFree(this);
+ return extendedStatus.Read(this);
}
return null;
}