1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Windows.API;
  8 
  9 namespace System.Windows
 10 {
 11     public class ClipboardFormat : GraphicsObject
 12     {
 13         public enum Format : uint
 14         {
 15             text = 1uunicodeText = 13u
 16         }
 17         public ClipboardFormat(Format format) : formatName()formatNumber(format)
 18         {
 19         }
 20         public ClipboardFormat(const string& formatName_) : formatName(formatName_)formatNumber(0u)
 21         {
 22             auto registerResult = RegisterClipboardFormat(formatName.Chars());
 23             if (registerResult.Error())
 24             {
 25                 SetErrorId(registerResult.GetErrorId());
 26             }
 27             formatNumber = registerResult.Value();
 28         }
 29         public inline uint Number() const
 30         {
 31             return formatNumber;
 32         }
 33         private string formatName;
 34         private uint formatNumber;
 35     }
 36 
 37     public class MemoryHandle : GraphicsObject
 38     {
 39         public MemoryHandle() : base()handle(null)
 40         {
 41         }
 42         public MemoryHandle(void* handle_) : base()handle(handle_)memory(null)
 43         {
 44             auto result = GlobalLock(handle);
 45             if (result.Error())
 46             {
 47                 SetErrorId(result.GetErrorId());
 48             }
 49             memory = result.Value();
 50         }
 51         suppress MemoryHandle(const MemoryHandle&);
 52         suppress void operator=(const MemoryHandle&);
 53         public MemoryHandle(MemoryHandle&& that) : handle(that.handle)
 54         {
 55             that.handle = null;
 56         }
 57         public default void operator=(MemoryHandle&&);
 58         public ~MemoryHandle()
 59         {
 60             if (handle != null)
 61             {
 62                 auto result = GlobalUnlock(handle);
 63             }
 64         }
 65         public static Result<MemoryHandle> AllocateMemory(ulong size)
 66         {
 67             auto result = GlobalAlloc(GlobalAllocFlags.GHNDsize);
 68             if (result.Error())
 69             {
 70                 return Result<MemoryHandle>(ErrorId(result.GetErrorId()));
 71             }
 72             MemoryHandle memoryHandle(result.Value());
 73             if (memoryHandle.Error())
 74             {
 75                 return Result<MemoryHandle>(ErrorId(memoryHandle.GetErrorId()));
 76             }
 77             return Result<MemoryHandle>(Rvalue(memoryHandle));
 78         }
 79         public void* Memory() const
 80         {
 81             return memory;
 82         }
 83         [nodiscard]
 84         public Result<ulong> Size() const
 85         {
 86             return GlobalSize(handle);
 87         }
 88         public void* Handle() const
 89         {
 90             return handle;
 91         }
 92         private void* handle;
 93         private void* memory;
 94     }
 95 
 96     public class ClipboardListener : GraphicsObject
 97     {
 98         public ClipboardListener(void* windowHandle_) : windowHandle(windowHandle_)
 99         {
100             auto result = AddClipboardFormatListener(windowHandle);
101             if (result.Error())
102             {
103                 SetErrorId(result.GetErrorId());
104             }
105         }
106         public ~ClipboardListener()
107         {
108             auto result = RemoveClipboardFormatListener(windowHandle);
109         }
110         private void* windowHandle;
111     }
112 
113     public class Clipboard : GraphicsObject
114     {
115         public Clipboard(void* windowHandle_) : windowHandle(windowHandle_)
116         {
117             auto result = OpenClipboard(windowHandle);
118             if (result.Error())
119             {
120                 SetErrorId(result.GetErrorId());
121             }
122         }
123         public ~Clipboard()
124         {
125             auto result = CloseClipboard();
126         }
127         public bool IsClipboardFormatAvailable(const ClipboardFormat& clipboardFormat) const
128         {
129             return IsClipboardFormatAvailable(clipboardFormat.Number());
130         }
131         [nodiscard]
132         public Result<bool> SetEmpty()
133         {
134             return EmptyClipboard();
135         }
136         [nodiscard]
137         public Result<MemoryHandle> GetData(const ClipboardFormat& clipboardFormat)
138         {
139             auto result = GetClipboardData(clipboardFormat.Number());
140             if (result.Error())
141             {
142                 return Result<MemoryHandle>(ErrorId(result.GetErrorId()));
143             }
144             return Result<MemoryHandle>(MemoryHandle(result.Value()));
145         }
146         [nodiscard]
147         public Result<bool> SetData(const ClipboardFormat& clipboardFormatconst MemoryHandle& memoryHandle)
148         {
149             auto result = SetEmpty();
150             if (result.Error())
151             {
152                 return Result<bool>(ErrorId(result.GetErrorId()));
153             }
154             auto setResult = SetClipboardData(clipboardFormat.Number()memoryHandle.Handle());
155             if (setResult.Error())
156             {
157                 return Result<bool>(ErrorId(setResult.GetErrorId()));
158             }
159             return Result<bool>(true);
160         }
161         [nodiscard]
162         public Result<ustring> GetStringData(const ClipboardFormat& clipboardFormat)
163         {
164             Result<MemoryHandle> memoryHandleResult = GetData(clipboardFormat);
165             if (memoryHandleResult.Error())
166             {
167                 return Result<ustring>(ErrorId(memoryHandleResult.GetErrorId()));
168             }
169             MemoryHandle& memoryHandle = memoryHandleResult.Value();
170             Result<ulong> sizeResult = memoryHandle.Size();
171             if (sizeResult.Error())
172             {
173                 return Result<ustring>(ErrorId(sizeResult.GetErrorId()));
174             }
175             ulong size = sizeResult.Value();
176             if (clipboardFormat.Number() == ClipboardFormat.Format.text)
177             {
178                 UniquePtr<char> ptr(cast<char*>(MemAlloc(cast<long>(size))));
179                 StrCopy(ptr.Get()cast<char*>(memoryHandle.Memory()));
180                 string str(ptr.Get());
181                 auto utf32Result = ToUtf32(str);
182                 if (utf32Result.Error())
183                 {
184                     return Result<ustring>(ErrorId(utf32Result.GetErrorId()));
185                 }
186                 return Result<ustring>(Rvalue(utf32Result.Value()));
187             }
188             else if (clipboardFormat.Number() == ClipboardFormat.Format.unicodeText)
189             {
190                 UniquePtr<wchar> ptr(cast<wchar*>(MemAlloc(cast<long>(size))));
191                 StrCopy(ptr.Get()cast<wchar*>(memoryHandle.Memory()));
192                 wstring str(ptr.Get());
193                 auto utf32Result = ToUtf32(str);
194                 if (utf32Result.Error())
195                 {
196                     return Result<ustring>(ErrorId(utf32Result.GetErrorId()));
197                 }
198                 return Result<ustring>(Rvalue(utf32Result.Value()));
199             }
200             else
201             {
202                 UniquePtr<uchar> ptr(cast<uchar*>(MemAlloc(cast<long>(size))));
203                 StrCopy(ptr.Get()cast<uchar*>(memoryHandle.Memory()));
204                 ustring str(ptr.Get());
205                 return Result<ustring>(Rvalue(str));;
206             }
207         }
208         [nodiscard]
209         public Result<bool> SetStringData(const ClipboardFormat& clipboardFormatconst ustring& str)
210         {
211             if (clipboardFormat.Number() == ClipboardFormat.Format.text)
212             {
213                 auto utf8Result = ToUtf8(str);
214                 if (utf8Result.Error())
215                 {
216                     return Result<bool>(ErrorId(utf8Result.GetErrorId()));
217                 }
218                 string s = Rvalue(utf8Result.Value());
219                 Result<MemoryHandle> memoryHandleResult = MemoryHandle.AllocateMemory(cast<ulong>((s.Length() + 1) * sizeof(char)));
220                 if (memoryHandleResult.Error())
221                 {
222                     return Result<bool>(ErrorId(memoryHandleResult.GetErrorId()));
223                 }
224                 MemoryHandle& memoryHandle = memoryHandleResult.Value();
225                 StrCopy(cast<char*>(memoryHandle.Memory())s.Chars());
226                 auto result = SetData(clipboardFormatmemoryHandle);
227                 return result;
228             }
229             else if (clipboardFormat.Number() == ClipboardFormat.Format.unicodeText)
230             {
231                 auto utf16Result = ToUtf16(str);
232                 if (utf16Result.Error())
233                 {
234                     return Result<bool>(ErrorId(utf16Result.GetErrorId()));
235                 }
236                 wstring s = Rvalue(utf16Result.Value());
237                 Result<MemoryHandle> memoryHandleResult = MemoryHandle.AllocateMemory(cast<ulong>((s.Length() + 1) * sizeof(wchar)));
238                 if (memoryHandleResult.Error())
239                 {
240                     return Result<bool>(ErrorId(memoryHandleResult.GetErrorId()));
241                 }
242                 MemoryHandle& memoryHandle = memoryHandleResult.Value();
243                 StrCopy(cast<wchar*>(memoryHandle.Memory())s.Chars());
244                 auto result = SetData(clipboardFormatmemoryHandle);
245                 return result;
246             }
247             else
248             {
249                 Result<MemoryHandle> memoryHandleResult = MemoryHandle.AllocateMemory(cast<ulong>((str.Length() + 1) * sizeof(uchar)));
250                 if (memoryHandleResult.Error())
251                 {
252                     return Result<bool>(ErrorId(memoryHandleResult.GetErrorId()));
253                 }
254                 MemoryHandle& memoryHandle = memoryHandleResult.Value();
255                 StrCopy(cast<uchar*>(memoryHandle.Memory())str.Chars());
256                 auto result = SetData(clipboardFormatmemoryHandle);
257                 return result;
258             }
259         }
260         private void* windowHandle;
261     }