Merge pull request #2212 from unxed/ctrl_yo
[far2l.git] / far2l / src / clipboard.cpp
blob8cfb469f2502033b6e8dd862cd946580ce618c1c
1 /*
2 clipboard.cpp
4 Работа с буфером обмена.
5 */
6 /*
7 Copyright (c) 1996 Eugene Roshal
8 Copyright (c) 2000 Far Group
9 All rights reserved.
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions
13 are met:
14 1. Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16 2. Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in the
18 documentation and/or other materials provided with the distribution.
19 3. The name of the authors may not be used to endorse or promote products
20 derived from this software without specific prior written permission.
22 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "headers.hpp"
36 #include "clipboard.hpp"
37 #include "console.hpp"
39 static const wchar_t FAR_VerticalBlock_Unicode[] = L"FAR_VerticalBlock_Unicode";
41 /* ------------------------------------------------------------ */
42 // CF_OEMTEXT CF_TEXT CF_UNICODETEXT CF_HDROP
43 HGLOBAL Clipboard::hInternalClipboard[5] = {0};
44 UINT Clipboard::uInternalClipboardFormat[5] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
46 bool Clipboard::UseInternalClipboard = false;
47 bool Clipboard::InternalClipboardOpen = false;
49 // Sets UseInternalClipboard to State, and returns previous state
50 bool Clipboard::SetUseInternalClipboardState(bool State)
52 bool OldState = UseInternalClipboard;
53 UseInternalClipboard = State;
54 return OldState;
57 bool Clipboard::GetUseInternalClipboardState()
59 return UseInternalClipboard;
62 UINT Clipboard::RegisterFormat(LPCWSTR lpszFormat)
64 if (UseInternalClipboard) {
65 if (!StrCmp(lpszFormat, FAR_VerticalBlock_Unicode)) {
66 return 0xFEB1;
69 return 0;
72 return WINPORT(RegisterClipboardFormat)(lpszFormat);
75 BOOL Clipboard::Open()
77 if (UseInternalClipboard) {
78 if (!InternalClipboardOpen) {
79 InternalClipboardOpen = true;
80 return TRUE;
83 return FALSE;
86 return WINPORT(OpenClipboard)(NULL); // Console.GetWindow());
89 BOOL Clipboard::Close()
91 if (UseInternalClipboard) {
92 if (InternalClipboardOpen) {
93 InternalClipboardOpen = false;
94 return TRUE;
97 return FALSE;
100 return WINPORT(CloseClipboard)();
103 BOOL Clipboard::Empty()
105 if (UseInternalClipboard) {
106 if (InternalClipboardOpen) {
107 for (size_t I = 0; I < ARRAYSIZE(hInternalClipboard); ++I) {
108 if (hInternalClipboard[I]) {
109 WINPORT(ClipboardFree)(hInternalClipboard[I]);
110 hInternalClipboard[I] = 0;
111 uInternalClipboardFormat[I] = 0xFFFF;
115 return TRUE;
118 return FALSE;
121 return WINPORT(EmptyClipboard)();
124 HANDLE Clipboard::GetData(UINT uFormat)
126 if (UseInternalClipboard) {
127 if (InternalClipboardOpen && uFormat != 0xFFFF) {
128 for (size_t I = 0; I < ARRAYSIZE(hInternalClipboard); ++I) {
129 if (uInternalClipboardFormat[I] == uFormat) {
130 return hInternalClipboard[I];
135 return (HANDLE) nullptr;
138 return WINPORT(GetClipboardData)(uFormat);
141 HANDLE Clipboard::SetData(UINT uFormat, HANDLE hMem)
143 if (UseInternalClipboard) {
144 if (InternalClipboardOpen) {
145 for (size_t I = 0; I < ARRAYSIZE(hInternalClipboard); ++I) {
146 if (!hInternalClipboard[I]) {
147 hInternalClipboard[I] = hMem;
148 uInternalClipboardFormat[I] = uFormat;
149 return hMem;
154 return (HANDLE) nullptr;
157 return WINPORT(SetClipboardData)(uFormat, hMem);
160 bool Clipboard::IsFormatAvailable(UINT Format)
162 if (UseInternalClipboard) {
163 for (size_t I = 0; I < ARRAYSIZE(hInternalClipboard); ++I) {
164 if (uInternalClipboardFormat[I] != 0xFFFF && uInternalClipboardFormat[I] == Format) {
165 return true;
169 return false;
172 return WINPORT(IsClipboardFormatAvailable)(Format) != FALSE;
175 // Перед вставкой производится очистка буфера
176 bool Clipboard::Copy(const wchar_t *Data, bool IsVertical)
178 Empty();
180 if (!AddData(CF_UNICODETEXT, Data, (wcslen(Data) + 1) * sizeof(wchar_t))) {
181 return false;
184 if (IsVertical) {
185 UINT FormatType = RegisterFormat(FAR_VerticalBlock_Unicode);
186 if (FormatType) {
187 AddData(FormatType, "\0\0\0\0", 4);
191 return true;
194 bool Clipboard::AddData(UINT FormatType, const void *Data, size_t Size)
196 if (!Data || !Size)
197 return true;
199 void *CData = WINPORT(ClipboardAlloc)(Size);
201 if (!CData)
202 return false;
204 memcpy(CData, Data, Size);
205 if (!SetData(FormatType, (HANDLE)CData)) {
206 WINPORT(ClipboardFree)(CData);
207 return false;
210 return true;
213 // max - без учета символа конца строки!
214 // max = -1 - there is no limit!
215 wchar_t *Clipboard::Paste(bool &IsVertical, int MaxChars)
217 PVOID ClipData = GetData(CF_UNICODETEXT);
219 if (!ClipData)
220 return nullptr;
222 size_t CharsCount =
223 wcsnlen((const wchar_t *)ClipData, WINPORT(ClipboardSize)(ClipData) / sizeof(wchar_t));
225 if (MaxChars >= 0 && CharsCount < (size_t)MaxChars)
226 CharsCount = (size_t)MaxChars;
228 wchar_t *ClipText = (wchar_t *)malloc((CharsCount + 1) * sizeof(wchar_t));
229 if (ClipText) {
230 wmemcpy(ClipText, (const wchar_t *)ClipData, CharsCount);
231 ClipText[CharsCount] = 0;
234 IsVertical = false;
236 if (wcsstr(ClipText, NATIVE_EOLW)) {
237 UINT FormatType = RegisterFormat(FAR_VerticalBlock_Unicode);
238 if (FormatType && IsFormatAvailable(FormatType)) {
239 IsVertical = true;
243 return ClipText;
246 wchar_t *Clipboard::Paste()
248 bool IsVertical;
249 return Paste(IsVertical);
252 /* ------------------------------------------------------------ */
253 int WINAPI CopyToClipboard(const wchar_t *Data)
255 Clipboard clip;
257 if (!clip.Open())
258 return FALSE;
260 BOOL ret = clip.Copy(Data);
262 clip.Close();
264 return ret;
267 wchar_t *PasteFromClipboardEx(int MaxChars)
269 Clipboard clip;
271 if (!clip.Open())
272 return nullptr;
274 bool IsVertical;
275 wchar_t *ClipText = clip.Paste(IsVertical, MaxChars);
277 clip.Close();
279 return ClipText;
282 wchar_t *WINAPI PasteFromClipboard()
284 return PasteFromClipboardEx();
287 BOOL EmptyInternalClipboard()
289 bool OldState = Clipboard::SetUseInternalClipboardState(true);
291 Clipboard clip;
293 if (!clip.Open())
294 return FALSE;
296 BOOL ret = clip.Empty();
298 clip.Close();
300 Clipboard::SetUseInternalClipboardState(OldState);
302 return ret;