Skip to content

Commit 22f5df7

Browse files
Improved clipboard handling
1 parent 427170d commit 22f5df7

File tree

2 files changed

+140
-61
lines changed

2 files changed

+140
-61
lines changed

fixlayouts.cpp

Lines changed: 139 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@ void ConvertSelectedTextInActiveWindow(HKL hklSource, HKL hklTarget)
1313

1414
// store previous clipboard data and set clipboard to dummy string
1515
ClipboardData prevClipboardData;
16-
StoreClipboardData(&prevClipboardData);
16+
if(!StoreClipboardData(&prevClipboardData))
17+
return;
1718

18-
SetClipboardText(dummy);
19+
if(!SetClipboardText(dummy))
20+
{
21+
// restore the original clipboard data
22+
RestoreClipboardData(&prevClipboardData);
23+
return;
24+
}
1925

2026
// copy the selected text by simulating Ctrl-C
2127
SendKeyCombo(VK_CONTROL, 'C', FALSE);
@@ -74,7 +80,6 @@ void ConvertSelectedTextInActiveWindow(HKL hklSource, HKL hklTarget)
7480

7581
// restore the original clipboard data
7682
RestoreClipboardData(&prevClipboardData);
77-
FreeClipboardData(&prevClipboardData);
7883
}
7984

8085
///////////////////////////////////////////////////////////////////////////////
@@ -194,97 +199,172 @@ HKL DetectLayoutFromString(const WCHAR* str, int* pmatches)
194199
// You must call FreeAllClipboardData on `formats` when it's no longer needed.
195200
BOOL StoreClipboardData(ClipboardData* formats)
196201
{
197-
if(OpenClipboard(NULL))
202+
if(!OpenClipboard(NULL))
203+
return FALSE;
204+
205+
formats->count = CountClipboardFormats();
206+
if(formats->count == 0)
207+
{
208+
DWORD dwError = GetLastError();
209+
CloseClipboard();
210+
return dwError == ERROR_SUCCESS;
211+
}
212+
213+
formats->dataArray = (ClipboardFormat*)malloc(sizeof(ClipboardData) * formats->count);
214+
ZeroMemory(formats->dataArray, sizeof(ClipboardData) * formats->count);
215+
int i = 0;
216+
217+
UINT format = EnumClipboardFormats(0);
218+
while(format)
198219
{
199-
formats->count = CountClipboardFormats();
200-
formats->dataArray = (ClipboardFormat*)malloc(sizeof(ClipboardData) * formats->count);
201-
ZeroMemory(formats->dataArray, sizeof(ClipboardData) * formats->count);
202-
int i = 0;
203-
UINT format = EnumClipboardFormats(0);
204-
while(format)
220+
if(i > formats->count - 1)
221+
break;
222+
223+
HANDLE dataHandle = GetClipboardData(format);
224+
if(!dataHandle)
225+
break;
226+
227+
size_t size;
228+
if(!(GlobalFlags(dataHandle) & GMEM_DISCARDED))
205229
{
206-
HANDLE dataHandle = GetClipboardData(format);
207-
LPVOID source = GlobalLock(dataHandle);
208-
size_t size = GlobalSize(dataHandle);
209-
formats->dataArray[i].format = format;
210-
formats->dataArray[i].dataHandle = GlobalAlloc(GHND, size);
211-
LPVOID dest = GlobalLock(formats->dataArray[i].dataHandle);
212-
CopyMemory(dest, source, size);
213-
GlobalUnlock(formats->dataArray[i].dataHandle);
214-
GlobalUnlock(dataHandle);
215-
216-
// next format
217-
format = EnumClipboardFormats(format);
218-
i++;
230+
size = GlobalSize(dataHandle);
231+
if(size == 0)
232+
break;
219233
}
220-
CloseClipboard();
221-
return TRUE;
234+
else
235+
size = 0;
236+
237+
LPVOID source = GlobalLock(dataHandle);
238+
if(!source)
239+
break;
240+
241+
BOOL bCopySucceeded = FALSE;
242+
243+
formats->dataArray[i].format = format;
244+
formats->dataArray[i].dataHandle = GlobalAlloc(GHND, size);
245+
if(formats->dataArray[i].dataHandle)
246+
{
247+
if(size == 0)
248+
{
249+
bCopySucceeded = TRUE;
250+
}
251+
else
252+
{
253+
LPVOID dest = GlobalLock(formats->dataArray[i].dataHandle);
254+
if(dest)
255+
{
256+
CopyMemory(dest, source, size);
257+
GlobalUnlock(formats->dataArray[i].dataHandle);
258+
bCopySucceeded = TRUE;
259+
}
260+
}
261+
262+
if(!bCopySucceeded)
263+
GlobalFree(formats->dataArray[i].dataHandle);
264+
}
265+
266+
GlobalUnlock(dataHandle);
267+
268+
if(!bCopySucceeded)
269+
break;
270+
271+
i++;
272+
273+
// next format
274+
format = EnumClipboardFormats(format);
222275
}
223-
return FALSE;
224-
}
225276

226-
///////////////////////////////////////////////////////////////////////////////
227-
// Restores the data in the clipboard from `formats` that was generated by
228-
// StoreClipboardData.
229-
BOOL RestoreClipboardData(const ClipboardData* formats)
230-
{
231-
if(OpenClipboard(NULL))
277+
CloseClipboard();
278+
279+
if(format) // if failed before completion
232280
{
233-
EmptyClipboard();
234-
for(int i = 0; i < formats->count; i++)
281+
for(int j = 0; j < i; j++)
235282
{
236-
SetClipboardData(formats->dataArray[i].format, formats->dataArray[i].dataHandle);
283+
GlobalFree(formats->dataArray[j].dataHandle);
237284
}
238-
CloseClipboard();
239-
return TRUE;
285+
286+
free(formats->dataArray);
287+
return FALSE;
240288
}
241-
return FALSE;
289+
290+
return TRUE;
242291
}
243292

244293
///////////////////////////////////////////////////////////////////////////////
245-
// Frees `formats` allocated by StoreClipboardData
246-
void FreeClipboardData(ClipboardData* formats)
294+
// Restores the data in the clipboard from `formats` that was generated by
295+
// StoreClipboardData, and frees allocated data.
296+
BOOL RestoreClipboardData(ClipboardData* formats)
247297
{
298+
if(!OpenClipboard(NULL))
299+
return FALSE;
300+
301+
EmptyClipboard();
302+
for(int i = 0; i < formats->count; i++)
303+
{
304+
SetClipboardData(formats->dataArray[i].format, formats->dataArray[i].dataHandle);
305+
}
306+
307+
CloseClipboard();
248308
free(formats->dataArray);
309+
return TRUE;
249310
}
250311

251312
///////////////////////////////////////////////////////////////////////////////
252313
// Gets unicode text from the clipboard.
253314
// You must free the returned string when you don't need it anymore.
254315
WCHAR* GetClipboardText()
255316
{
317+
if(!OpenClipboard(NULL))
318+
return FALSE;
319+
256320
WCHAR* text = NULL;
257-
if(OpenClipboard(NULL))
321+
HANDLE handle = GetClipboardData(CF_UNICODETEXT);
322+
if(handle)
258323
{
259-
HANDLE handle = GetClipboardData(CF_UNICODETEXT);
260324
WCHAR* clipboardText = (WCHAR*)GlobalLock(handle);
261-
if(!clipboardText) return NULL;
262-
size_t size = sizeof(WCHAR) * (wcslen(clipboardText) + 1);
263-
text = (WCHAR*)malloc(size);
264-
if(!text) return NULL;
265-
memcpy(text, clipboardText, size);
266-
CloseClipboard();
325+
if(clipboardText)
326+
{
327+
size_t size = sizeof(WCHAR) * (wcslen(clipboardText) + 1);
328+
text = (WCHAR*)malloc(size);
329+
if(text)
330+
memcpy(text, clipboardText, size);
331+
332+
GlobalUnlock(handle);
333+
}
267334
}
335+
336+
CloseClipboard();
268337
return text;
269338
}
270339

271340
///////////////////////////////////////////////////////////////////////////////
272341
// Puts unicode text on the clipboard
273342
BOOL SetClipboardText(const WCHAR* text)
274343
{
275-
if(OpenClipboard(NULL))
344+
if(!OpenClipboard(NULL))
345+
return FALSE;
346+
347+
BOOL bSucceeded = FALSE;
348+
349+
size_t size = sizeof(WCHAR) * (wcslen(text) + 1);
350+
HANDLE handle = GlobalAlloc(GHND, size);
351+
if(handle)
276352
{
277-
size_t size = sizeof(WCHAR) * (wcslen(text) + 1);
278-
HANDLE handle = GlobalAlloc(GHND, size);
279353
WCHAR* clipboardText = (WCHAR*)GlobalLock(handle);
280-
memcpy(clipboardText, text, size);
281-
GlobalUnlock(handle);
282-
EmptyClipboard();
283-
SetClipboardData(CF_UNICODETEXT, handle);
284-
CloseClipboard();
285-
return TRUE;
354+
if(clipboardText)
355+
{
356+
memcpy(clipboardText, text, size);
357+
GlobalUnlock(handle);
358+
bSucceeded = EmptyClipboard() &&
359+
SetClipboardData(CF_UNICODETEXT, handle);
360+
}
361+
362+
if(!bSucceeded)
363+
GlobalFree(handle);
286364
}
287-
return FALSE;
365+
366+
CloseClipboard();
367+
return bSucceeded;
288368
}
289369

290370
///////////////////////////////////////////////////////////////////////////////

fixlayouts.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ HKL DetectLayoutFromString(const WCHAR* str, BOOL* pmatches);
2828

2929
// Functions to store and restore all of the data in the clipboard
3030
BOOL StoreClipboardData(ClipboardData* formats);
31-
BOOL RestoreClipboardData(const ClipboardData* formats);
32-
void FreeClipboardData(ClipboardData* formats);
31+
BOOL RestoreClipboardData(ClipboardData* formats);
3332

3433
// Convenience functions for the clipboard
3534
WCHAR* GetClipboardText();

0 commit comments

Comments
 (0)