From 6788d9d6d53438b92bbed78b4cb3d3ad9c581ae2 Mon Sep 17 00:00:00 2001 From: Neil Date: Sun, 29 Mar 2020 10:26:11 +1100 Subject: Widen types to size_t to match change from int to position of CallTipSetHlt in Scintilla.iface. --- src/CallTip.cxx | 155 ++++++++++++++++++++++++++------------------------ src/CallTip.h | 19 +++++-- src/ScintillaBase.cxx | 6 +- 3 files changed, 96 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/CallTip.cxx b/src/CallTip.cxx index d12033de3..d9c6bc9b5 100644 --- a/src/CallTip.cxx +++ b/src/CallTip.cxx @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -28,6 +29,10 @@ using namespace Scintilla; +size_t Chunk::Length() const noexcept { + return end - start; +} + CallTip::CallTip() noexcept { wCallTip = {}; inCallTipMode = false; @@ -36,8 +41,6 @@ CallTip::CallTip() noexcept { rectDown = PRectangle(0,0,0,0); lineHeight = 1; offsetMain = 0; - startHighlight = 0; - endHighlight = 0; tabSize = 0; above = false; useStyleCallTip = false; // for backwards compatibility @@ -119,62 +122,63 @@ void DrawArrow(Scintilla::Surface *surface, const PRectangle &rc, bool upArrow, } // Draw a section of the call tip that does not include \n in one colour. -// The text may include up to numEnds tabs or arrow characters. -void CallTip::DrawChunk(Surface *surface, int &x, const char *s, - int posStart, int posEnd, int ytext, PRectangle rcClient, - bool highlight, bool draw) { - s += posStart; - const int len = posEnd - posStart; +// The text may include tabs or arrow characters. +int CallTip::DrawChunk(Surface *surface, int x, std::string_view sv, + int ytext, PRectangle rcClient, bool asHighlight, bool draw) { + + if (sv.empty()) { + return x; + } // Divide the text into sections that are all text, or that are // single arrows or single tab characters (if tabSize > 0). - int maxEnd = 0; - constexpr int numEnds = 10; - int ends[numEnds + 2] {}; - for (int i=0; i 0) - ends[maxEnd++] = i; - ends[maxEnd++] = i+1; + // Start with single element 0 to simplify append checks. + std::vector ends(1); + for (size_t i=0; i startSeg) { - int xEnd; - if (IsArrowCharacter(s[startSeg])) { - xEnd = x + widthArrow; - const bool upArrow = s[startSeg] == '\001'; + if (ends.back() != sv.length()) + ends.push_back(sv.length()); + ends.erase(ends.begin()); // Remove initial 0. + + size_t startSeg = 0; + for (const size_t endSeg : ends) { + assert(endSeg > 0); + int xEnd; + if (IsArrowCharacter(sv[startSeg])) { + xEnd = x + widthArrow; + const bool upArrow = sv[startSeg] == '\001'; + rcClient.left = static_cast(x); + rcClient.right = static_cast(xEnd); + if (draw) { + DrawArrow(surface, rcClient, upArrow, colourBG, colourUnSel); + } + offsetMain = xEnd; + if (upArrow) { + rectUp = rcClient; + } else { + rectDown = rcClient; + } + } else if (IsTabCharacter(sv[startSeg])) { + xEnd = NextTabPos(x); + } else { + const std::string_view segText = sv.substr(startSeg, endSeg - startSeg); + xEnd = x + static_cast(std::lround(surface->WidthText(font, segText))); + if (draw) { rcClient.left = static_cast(x); rcClient.right = static_cast(xEnd); - if (draw) { - DrawArrow(surface, rcClient, upArrow, colourBG, colourUnSel); - } - offsetMain = xEnd; - if (upArrow) { - rectUp = rcClient; - } else { - rectDown = rcClient; - } - } else if (IsTabCharacter(s[startSeg])) { - xEnd = NextTabPos(x); - } else { - const std::string_view segText(s + startSeg, endSeg - startSeg); - xEnd = x + static_cast(std::lround(surface->WidthText(font, segText))); - if (draw) { - rcClient.left = static_cast(x); - rcClient.right = static_cast(xEnd); - surface->DrawTextTransparent(rcClient, font, static_cast(ytext), - segText, highlight ? colourSel : colourUnSel); - } + surface->DrawTextTransparent(rcClient, font, static_cast(ytext), + segText, asHighlight ? colourSel : colourUnSel); } - x = xEnd; - startSeg = endSeg; } + x = xEnd; + startSeg = endSeg; } + return x; } int CallTip::PaintContents(Surface *surfaceWindow, bool draw) { @@ -190,40 +194,42 @@ int CallTip::PaintContents(Surface *surfaceWindow, bool draw) { // Draw the definition in three parts: before highlight, highlighted, after highlight int ytext = static_cast(rcClient.top) + ascent + 1; rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1; - const char *chunkVal = val.c_str(); - bool moreChunks = true; + std::string_view remaining(val); int maxWidth = 0; - - while (moreChunks) { - const char *chunkEnd = strchr(chunkVal, '\n'); - if (!chunkEnd) { - chunkEnd = chunkVal + strlen(chunkVal); - moreChunks = false; + size_t lineStart = 0; + while (!remaining.empty()) { + const std::string_view chunkVal = remaining.substr(0, remaining.find_first_of('\n')); + remaining.remove_prefix(chunkVal.length()); + if (!remaining.empty()) { + remaining.remove_prefix(1); // Skip \n } - const int chunkOffset = static_cast(chunkVal - val.c_str()); - const int chunkLength = static_cast(chunkEnd - chunkVal); - const int chunkEndOffset = chunkOffset + chunkLength; - int thisStartHighlight = std::max(startHighlight, chunkOffset); - thisStartHighlight = std::min(thisStartHighlight, chunkEndOffset); - thisStartHighlight -= chunkOffset; - int thisEndHighlight = std::max(endHighlight, chunkOffset); - thisEndHighlight = std::min(thisEndHighlight, chunkEndOffset); - thisEndHighlight -= chunkOffset; + + const Chunk chunkLine(lineStart, lineStart + chunkVal.length()); + Chunk chunkHighlight( + std::clamp(highlight.start, chunkLine.start, chunkLine.end), + std::clamp(highlight.end, chunkLine.start, chunkLine.end) + ); + chunkHighlight.start -= lineStart; + chunkHighlight.end -= lineStart; + rcClient.top = static_cast(ytext - ascent - 1); int x = insetX; // start each line at this inset - DrawChunk(surfaceWindow, x, chunkVal, 0, thisStartHighlight, + x = DrawChunk(surfaceWindow, x, + chunkVal.substr(0, chunkHighlight.start), ytext, rcClient, false, draw); - DrawChunk(surfaceWindow, x, chunkVal, thisStartHighlight, thisEndHighlight, + x = DrawChunk(surfaceWindow, x, + chunkVal.substr(chunkHighlight.start, chunkHighlight.Length()), ytext, rcClient, true, draw); - DrawChunk(surfaceWindow, x, chunkVal, thisEndHighlight, chunkLength, + x = DrawChunk(surfaceWindow, x, + chunkVal.substr(chunkHighlight.end), ytext, rcClient, false, draw); - chunkVal = chunkEnd + 1; ytext += lineHeight; rcClient.bottom += lineHeight; maxWidth = std::max(maxWidth, x); + lineStart += chunkVal.length() + 1; } return maxWidth; } @@ -274,8 +280,7 @@ PRectangle CallTip::CallTipStart(Sci::Position pos, Point pt, int textHeight, co surfaceMeasure->Init(wParent.GetID()); surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage); surfaceMeasure->SetDBCSMode(codePage); - startHighlight = 0; - endHighlight = 0; + highlight = Chunk(); inCallTipMode = true; posStartCallTip = pos; const XYPOSITION deviceHeight = static_cast(surfaceMeasure->DeviceHeightFont(size)); @@ -308,11 +313,11 @@ void CallTip::CallTipCancel() { } } -void CallTip::SetHighlight(int start, int end) { +void CallTip::SetHighlight(size_t start, size_t end) { // Avoid flashing by checking something has really changed - if ((start != startHighlight) || (end != endHighlight)) { - startHighlight = start; - endHighlight = (end > start) ? end : start; + if ((start != highlight.start) || (end != highlight.end)) { + highlight.start = start; + highlight.end = (end > start) ? end : start; if (wCallTip.Created()) { wCallTip.InvalidateAll(); } diff --git a/src/CallTip.h b/src/CallTip.h index a720bd3a3..562b24f9d 100644 --- a/src/CallTip.h +++ b/src/CallTip.h @@ -10,11 +10,19 @@ namespace Scintilla { +struct Chunk { + size_t start; + size_t end; + constexpr Chunk(size_t start_=0, size_t end_=0) noexcept : start(start_), end(end_) { + assert(start <= end); + } + size_t Length() const noexcept; +}; + /** */ class CallTip { - int startHighlight; // character offset to start and... - int endHighlight; // ...end of highlighted text + Chunk highlight; // character offset to start and end of highlighted text std::string val; Font font; PRectangle rectUp; // rectangle of last up angle in the tip @@ -25,9 +33,8 @@ class CallTip { bool useStyleCallTip; // if true, STYLE_CALLTIP should be used bool above; // if true, display calltip above text - void DrawChunk(Surface *surface, int &x, const char *s, - int posStart, int posEnd, int ytext, PRectangle rcClient, - bool highlight, bool draw); + int DrawChunk(Surface *surface, int x, std::string_view sv, + int ytext, PRectangle rcClient, bool asHighlight, bool draw); int PaintContents(Surface *surfaceWindow, bool draw); bool IsTabCharacter(char ch) const noexcept; int NextTabPos(int x) const noexcept; @@ -71,7 +78,7 @@ public: /// Set a range of characters to be displayed in a highlight style. /// Commonly used to highlight the current parameter. - void SetHighlight(int start, int end); + void SetHighlight(size_t start, size_t end); /// Set the tab size in pixels for the call tip. 0 or -ve means no tab expand. void SetTabSize(int tabSz) noexcept; diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx index 9086f2976..7794ea75e 100644 --- a/src/ScintillaBase.cxx +++ b/src/ScintillaBase.cxx @@ -1004,7 +1004,7 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara return ac.GetTypesep(); case SCI_CALLTIPSHOW: - CallTipShow(LocationFromPosition(static_cast(wParam)), + CallTipShow(LocationFromPosition(wParam), ConstCharPtrFromSPtr(lParam)); break; @@ -1019,11 +1019,11 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara return ct.posStartCallTip; case SCI_CALLTIPSETPOSSTART: - ct.posStartCallTip = static_cast(wParam); + ct.posStartCallTip = wParam; break; case SCI_CALLTIPSETHLT: - ct.SetHighlight(static_cast(wParam), static_cast(lParam)); + ct.SetHighlight(wParam, lParam); break; case SCI_CALLTIPSETBACK: -- cgit v1.2.3