Skip to content

Commit 8b3a49b

Browse files
author
elfmz
committed
cygwin: VT clipboard UTF16/32 interoperability (fix #640)
1 parent d4735f4 commit 8b3a49b

2 files changed

Lines changed: 92 additions & 4 deletions

File tree

‎WinPort/src/Backend/TTY/TTYFar2lClipboardBackend.cpp‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <fcntl.h>
22
#include <utils.h>
33
#include <base64.h>
4+
#include <ConvertUTF.h>
45
#include "TTYFar2lClipboardBackend.h"
56
#include "FSClipboardBackend.h"
67

@@ -147,8 +148,30 @@ void *TTYFar2lClipboardBackend::OnClipboardSetData(UINT format, void *data)
147148

148149
try {
149150
StackSerializer stk_ser;
151+
152+
#if (__WCHAR_MAX__ <= 0xffff)
153+
UTF32 *new_data = nullptr;
154+
if (format == CF_UNICODETEXT && len != 0) { // UTF16 -> UTF32
155+
int cnt = 0;
156+
const UTF16 *src = (const UTF16 *)data;
157+
CalcSpaceUTF16toUTF32(&cnt, &src, src + len / sizeof(UTF16), lenientConversion);
158+
new_data = (UTF32 *)malloc((cnt + 1) * sizeof(UTF32));
159+
if (new_data != nullptr) {
160+
new_data[cnt] = 0;
161+
src = (const UTF16 *)data;
162+
UTF32 *dst = new_data;
163+
ConvertUTF16toUTF32( &src, src + len / sizeof(UTF16), &dst, dst + cnt, lenientConversion);
164+
len = cnt * sizeof(UTF32);
165+
}
166+
}
167+
stk_ser.Push(new_data ? new_data : data, len);
168+
stk_ser.PushPOD(len);
169+
free(new_data);
170+
#else
150171
stk_ser.Push(data, len);
151172
stk_ser.PushPOD(len);
173+
#endif
174+
152175
stk_ser.PushPOD(format);
153176
stk_ser.PushPOD('s');
154177
Far2lInterract(stk_ser, true);
@@ -176,6 +199,24 @@ void *TTYFar2lClipboardBackend::OnClipboardGetData(UINT format)
176199
data = malloc(len);
177200
if (data) {
178201
stk_ser.Pop(data, len);
202+
#if (__WCHAR_MAX__ <= 0xffff)
203+
if (format == CF_UNICODETEXT) { // UTF32 -> UTF16
204+
int cnt = 0;
205+
const UTF32 *src = (const UTF32 *)data;
206+
CalcSpaceUTF32toUTF16(&cnt, &src, src + len / sizeof(UTF32), lenientConversion);
207+
UTF16 *new_data = (UTF16 *)malloc((cnt + 1) * sizeof(UTF16));
208+
if (new_data != nullptr) {
209+
new_data[cnt] = 0;
210+
src = (const UTF32 *)data;
211+
UTF16 *dst = new_data;
212+
ConvertUTF32toUTF16( &src, src + len / sizeof(UTF32), &dst, dst + cnt, lenientConversion);
213+
free(data);
214+
data = new_data;
215+
len = cnt * sizeof(UTF16);
216+
}
217+
}
218+
#endif
219+
179220
return data;
180221
}
181222
}

‎far2l/VTFar2lExtensios.cpp‎

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <assert.h>
22
#include <base64.h>
33
#include <utils.h>
4+
#include <ConvertUTF.h>
45
#include <fcntl.h>
56
#include "../WinPort/src/SavedScreen.h"
67

@@ -267,6 +268,14 @@ void VTFar2lExtensios::OnInterract_ClipboardIsFormatAvailable(StackSerializer &s
267268
stk_ser.PushPOD(out);
268269
}
269270

271+
void ClipboardData_Local2Remote(UINT fmt, void *&data, uint32_t &len)
272+
{
273+
}
274+
275+
void ClipboardData_Remote2Local(UINT fmt, void *&data, uint32_t &len)
276+
{
277+
}
278+
270279
void VTFar2lExtensios::OnInterract_ClipboardSetData(StackSerializer &stk_ser)
271280
{
272281
char out = -1;
@@ -280,6 +289,23 @@ void VTFar2lExtensios::OnInterract_ClipboardSetData(StackSerializer &stk_ser)
280289
if (len) {
281290
data = malloc(len);
282291
stk_ser.Pop(data, len);
292+
#if (__WCHAR_MAX__ <= 0xffff)
293+
if (fmt == CF_UNICODETEXT) { // UTF32 -> UTF16
294+
int cnt = 0;
295+
const UTF32 *src = (const UTF32 *)data;
296+
CalcSpaceUTF32toUTF16(&cnt, &src, src + len / sizeof(UTF32), lenientConversion);
297+
UTF16 *new_data = (UTF16 *)malloc((cnt + 1) * sizeof(UTF16));
298+
if (new_data != nullptr) {
299+
new_data[cnt] = 0;
300+
src = (const UTF32 *)data;
301+
UTF16 *dst = new_data;
302+
ConvertUTF32toUTF16( &src, src + len / sizeof(UTF32), &dst, dst + cnt, lenientConversion);
303+
free(data);
304+
data = new_data;
305+
len = cnt * sizeof(UTF16);
306+
}
307+
}
308+
#endif
283309
} else
284310
data = nullptr;
285311

@@ -297,11 +323,32 @@ void VTFar2lExtensios::OnInterract_ClipboardGetData(StackSerializer &stk_ser)
297323

298324
UINT fmt;
299325
stk_ser.PopPOD(fmt);
300-
void *ptr = allowed ? WINPORT(GetClipboardData)(fmt) : nullptr;
326+
void *data = allowed ? WINPORT(GetClipboardData)(fmt) : nullptr;
301327
stk_ser.Clear();
302-
uint32_t len = ptr ? GetMallocSize(ptr) : 0;
303-
if (len)
304-
stk_ser.Push(ptr, len);
328+
uint32_t len = data ? GetMallocSize(data) : 0;
329+
if (len) {
330+
#if (__WCHAR_MAX__ <= 0xffff)
331+
UTF32 *new_data = nullptr;
332+
if (fmt == CF_UNICODETEXT) { // UTF16 -> UTF32
333+
int cnt = 0;
334+
const UTF16 *src = (const UTF16 *)data;
335+
CalcSpaceUTF16toUTF32(&cnt, &src, src + len / sizeof(UTF16), lenientConversion);
336+
new_data = (UTF32 *)malloc((cnt + 1) * sizeof(UTF32));
337+
if (new_data != nullptr) {
338+
new_data[cnt] = 0;
339+
src = (const UTF16 *)data;
340+
UTF32 *dst = new_data;
341+
ConvertUTF16toUTF32( &src, src + len / sizeof(UTF16), &dst, dst + cnt, lenientConversion);
342+
data = new_data;
343+
len = cnt * sizeof(UTF32);
344+
}
345+
}
346+
stk_ser.Push(data, len);
347+
free(new_data);
348+
#else
349+
stk_ser.Push(data, len);
350+
#endif
351+
}
305352
stk_ser.PushPOD(len);
306353

307354
if (allowed) { // prolong allowance

0 commit comments

Comments
 (0)