This commit is contained in:
Adam D. Ruppe 2018-11-27 21:24:29 -05:00
parent 1cfacea360
commit d8f1907458
2 changed files with 66 additions and 21 deletions

View File

@ -5426,7 +5426,7 @@ abstract class EditableTextWidget : EditableTextWidgetParent {
} }
@property void content(string s) { @property void content(string s) {
version(win32_widgets) { version(win32_widgets) {
WCharzBuffer bfr = WCharzBuffer(s); WCharzBuffer bfr = WCharzBuffer(s, WindowsStringConversionFlags.convertNewLines);
SetWindowTextW(hwnd, bfr.ptr); SetWindowTextW(hwnd, bfr.ptr);
} else version(custom_widgets) { } else version(custom_widgets) {
textLayout.clear(); textLayout.clear();

View File

@ -4248,19 +4248,56 @@ struct WCharzBuffer {
} else static assert(0, "can only copy into wchar[n], not " ~ R.stringof); } else static assert(0, "can only copy into wchar[n], not " ~ R.stringof);
} }
this(in char[] data) { /++
conversionFlags = [WindowsStringConversionFlags]
+/
this(in char[] data, int conversionFlags = 0) {
conversionFlags |= WindowsStringConversionFlags.zeroTerminate; // this ALWAYS zero terminates cuz of its name
auto sz = sizeOfConvertedWstring(data, conversionFlags);
if(sz > staticBuffer.length)
buffer = new wchar[](sz);
else
buffer = staticBuffer[];
buffer = makeWindowsString(data, buffer, conversionFlags);
}
}
version(Windows)
int sizeOfConvertedWstring(in char[] s, int conversionFlags) {
int size = 0;
if(conversionFlags & WindowsStringConversionFlags.convertNewLines) {
// need to convert line endings, which means the length will get bigger.
// BTW I betcha this could be faster with some simd stuff.
char last;
foreach(char ch; s) {
if(ch == 10 && last != 13)
size++; // will add a 13 before it...
size++;
last = ch;
}
} else {
// no conversion necessary, just estimate based on length
/* /*
I don't think there's any string with a longer length I don't think there's any string with a longer length
in code units when encoded in UTF-16 than it has in UTF-8. in code units when encoded in UTF-16 than it has in UTF-8.
This will probably over allocate, but that's OK. This will probably over allocate, but that's OK.
*/ */
if(data.length + 1 > staticBuffer.length) // +1 cuz of zero terminator size = cast(int) s.length;
buffer = new wchar[](data.length + 1);
else
buffer = staticBuffer[];
buffer = makeWindowsString(data, buffer);
} }
if(conversionFlags & WindowsStringConversionFlags.zeroTerminate)
size++;
return size;
}
version(Windows)
enum WindowsStringConversionFlags : int {
zeroTerminate = 1,
convertNewLines = 2,
} }
version(Windows) version(Windows)
@ -4329,20 +4366,30 @@ class ErrnoApiException : Exception {
} }
version(Windows) version(Windows)
wchar[] makeWindowsString(in char[] str, wchar[] buffer, bool zeroTerminate = true) { wchar[] makeWindowsString(in char[] str, wchar[] buffer, int conversionFlags = WindowsStringConversionFlags.zeroTerminate) {
if(str.length == 0) if(str.length == 0)
return null; return null;
auto got = MultiByteToWideChar(CP_UTF8, 0, str.ptr, cast(int) str.length, buffer.ptr, cast(int) buffer.length);
if(got == 0) { int pos = 0;
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) dchar last;
throw new Exception("not enough buffer"); foreach(dchar c; str) {
else if(c <= 0xFFFF) {
throw new Exception("conversion"); // FIXME: GetLastError if((conversionFlags & WindowsStringConversionFlags.convertNewLines) && c == 10 && last != 13)
buffer[pos++] = 13;
buffer[pos++] = cast(wchar) c;
} else if(c <= 0x10FFFF) {
buffer[pos++] = cast(wchar)((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
buffer[pos++] = cast(wchar)(((c - 0x10000) & 0x3FF) + 0xDC00);
}
last = c;
} }
if(zeroTerminate) {
buffer[got] = 0; if(conversionFlags & WindowsStringConversionFlags.zeroTerminate) {
buffer[pos] = 0;
} }
return buffer[0 .. got];
return buffer[0 .. pos];
} }
version(Windows) version(Windows)
@ -4416,9 +4463,7 @@ void setClipboardText(SimpleWindow clipboardOwner, string text) {
scope(failure) scope(failure)
GlobalUnlock(handle); GlobalUnlock(handle);
auto str = makeWindowsString(text, slice); auto str = makeWindowsString(text, slice, WindowsStringConversionFlags.convertNewLines);
// FIXME: CR/LF conversions?
GlobalUnlock(handle); GlobalUnlock(handle);
SetClipboardData(CF_UNICODETEXT, handle); SetClipboardData(CF_UNICODETEXT, handle);