diff options
Diffstat (limited to 'win32/ScintillaWin.cxx')
-rw-r--r-- | win32/ScintillaWin.cxx | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 64ca03cfa..a231e2e55 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -1328,12 +1328,28 @@ std::string ScintillaWin::EncodeWString(std::wstring_view wsv) { } sptr_t ScintillaWin::GetTextLength() { - return pdoc->CountUTF16(0, pdoc->Length()); + if (pdoc->dbcsCodePage == 0 || pdoc->dbcsCodePage == CpUtf8) { + return pdoc->CountUTF16(0, pdoc->Length()); + } else { + // Count the number of UTF-16 code units line by line + const UINT cpSrc = CodePageOfDocument(); + const Sci::Line lines = pdoc->LinesTotal(); + Sci::Position codeUnits = 0; + std::string lineBytes; + for (Sci::Line line = 0; line < lines; line++) { + const Sci::Position start = pdoc->LineStart(line); + const Sci::Position width = pdoc->LineStart(line+1) - start; + lineBytes.resize(width); + pdoc->GetCharRange(lineBytes.data(), start, width); + codeUnits += WideCharLenFromMultiByte(cpSrc, lineBytes); + } + return codeUnits; + } } sptr_t ScintillaWin::GetText(uptr_t wParam, sptr_t lParam) { if (lParam == 0) { - return pdoc->CountUTF16(0, pdoc->Length()); + return GetTextLength(); } if (wParam == 0) { return 0; @@ -1344,27 +1360,41 @@ sptr_t ScintillaWin::GetText(uptr_t wParam, sptr_t lParam) { return 0; } const Sci::Position lengthWanted = wParam - 1; - Sci::Position sizeRequestedRange = pdoc->GetRelativePositionUTF16(0, lengthWanted); - if (sizeRequestedRange < 0) { - // Requested more text than there is in the document. - sizeRequestedRange = pdoc->Length(); - } - std::string docBytes(sizeRequestedRange, '\0'); - pdoc->GetCharRange(&docBytes[0], 0, sizeRequestedRange); if (IsUnicodeMode()) { + Sci::Position sizeRequestedRange = pdoc->GetRelativePositionUTF16(0, lengthWanted); + if (sizeRequestedRange < 0) { + // Requested more text than there is in the document. + sizeRequestedRange = pdoc->Length(); + } + std::string docBytes(sizeRequestedRange, '\0'); + pdoc->GetCharRange(&docBytes[0], 0, sizeRequestedRange); const size_t uLen = UTF16FromUTF8(docBytes, ptr, lengthWanted); ptr[uLen] = L'\0'; return uLen; } else { // Not Unicode mode // Convert to Unicode using the current Scintilla code page + // Retrieve as UTF-16 line by line const UINT cpSrc = CodePageOfDocument(); - int lengthUTF16 = WideCharLenFromMultiByte(cpSrc, docBytes); - if (lengthUTF16 > lengthWanted) - lengthUTF16 = static_cast<int>(lengthWanted); - WideCharFromMultiByte(cpSrc, docBytes, ptr, lengthUTF16); - ptr[lengthUTF16] = L'\0'; - return lengthUTF16; + const Sci::Line lines = pdoc->LinesTotal(); + Sci::Position codeUnits = 0; + std::string lineBytes; + std::wstring lineAsUTF16; + for (Sci::Line line = 0; line < lines && codeUnits < lengthWanted; line++) { + const Sci::Position start = pdoc->LineStart(line); + const Sci::Position width = pdoc->LineStart(line + 1) - start; + lineBytes.resize(width); + pdoc->GetCharRange(lineBytes.data(), start, width); + const Sci::Position codeUnitsLine = WideCharLenFromMultiByte(cpSrc, lineBytes); + lineAsUTF16.resize(codeUnitsLine); + const Sci::Position lengthLeft = lengthWanted - codeUnits; + WideCharFromMultiByte(cpSrc, lineBytes, lineAsUTF16.data(), lineAsUTF16.length()); + const Sci::Position lengthToCopy = std::min(lengthLeft, codeUnitsLine); + lineAsUTF16.copy(ptr + codeUnits, lengthToCopy); + codeUnits += lengthToCopy; + } + ptr[codeUnits] = L'\0'; + return codeUnits; } } |