19#include <forward_list>
96Timer::Timer() noexcept :
97 ticking(false), ticksToWait(0), tickerID{} {}
100 state(false), idlerID(0) {}
103 for (
unsigned int i = 0; i < len; i++) {
210 const char *
const reps[] = {
211 "NUL",
"SOH",
"STX",
"ETX",
"EOT",
"ENQ",
"ACK",
"BEL",
212 "BS",
"HT",
"LF",
"VT",
"FF",
"CR",
"SO",
"SI",
213 "DLE",
"DC1",
"DC2",
"DC3",
"DC4",
"NAK",
"SYN",
"ETB",
214 "CAN",
"EM",
"SUB",
"ESC",
"FS",
"GS",
"RS",
"US"
216 for (
size_t j=0; j < Sci::size(reps); j++) {
217 const char c[2] = {
static_cast<char>(j), 0 };
225 const char *
const repsC1[] = {
226 "PAD",
"HOP",
"BPH",
"NBH",
"IND",
"NEL",
"SSA",
"ESA",
227 "HTS",
"HTJ",
"VTS",
"PLD",
"PLU",
"RI",
"SS2",
"SS3",
228 "DCS",
"PU1",
"PU2",
"STS",
"CCH",
"MW",
"SPA",
"EPA",
229 "SOS",
"SGCI",
"SCI",
"CSI",
"ST",
"OSC",
"PM",
"APC"
231 for (
size_t j=0; j < Sci::size(repsC1); j++) {
232 const char c1[3] = {
'\xc2',
static_cast<char>(0x80+j), 0 };
241 for (
int k=0x80; k < 0x100; k++) {
242 const char hiByte[2] = {
static_cast<char>(k), 0 };
244 sprintf(hexits,
"x%2X", k);
249 for (
int k = 0x80; k < 0x100; k++) {
250 const char ch =
static_cast<char>(k);
252 const char hiByte[2] = { ch, 0 };
254 sprintf(hexits,
"x%2X", k);
306 ptDocument.
x += ptOrigin.
x;
307 ptDocument.
y += ptOrigin.
y;
339 const int htClient =
static_cast<int>(rcClient.
bottom - rcClient.
top);
400 if (canReturnInvalid) {
404 rcClient.
Move(-ptOrigin.
x, -ptOrigin.
y);
443 if ((
topLine != topLineNew) && (topLineNew >= 0)) {
466 if (rc.
top < rcClient.
top)
505 if (!markersInText) {
517 if (rcLine.
top < rcMarkers.
top)
518 rcLine.
top = rcMarkers.
top;
523 rcMarkers.
top = rcLine.
top;
526 if (rcMarkers.
Empty())
531 rcMarkers.
Move(-ptOrigin.
x, -ptOrigin.
y);
548 if (rc.
top < rcClientDrawing.
top)
549 rc.
top = rcClientDrawing.
top;
588 const int increment = (lineCaret > lineAnchorRect) ? 1 : -1;
596 if (
line == lineAnchorRect)
618 invalidateWholeSelection =
true;
624 if (invalidateWholeSelection) {
625 for (
size_t r=0; r<
sel.
Count(); r++) {
643 if (currentPos_ > anchor_) {
748 const std::string selectedText =
RangeText(rangeMainSelection.
start, rangeMainSelection.
end);
751 std::vector<Range> searchRanges;
754 if (rangeTarget.
Overlaps(rangeMainSelection)) {
757 if (rangeMainSelection.
end < rangeTarget.
end)
758 searchRanges.push_back(
Range(rangeMainSelection.
end, rangeTarget.
end));
759 if (rangeTarget.
start < rangeMainSelection.
start)
760 searchRanges.push_back(
Range(rangeTarget.
start, rangeMainSelection.
start));
763 searchRanges.push_back(rangeTarget);
766 for (std::vector<Range>::const_iterator it = searchRanges.begin(); it != searchRanges.end(); ++it) {
780 searchStart =
pos + lengthFound;
790 if (vs.ProtectionActive()) {
797 if (vs.styles[pdoc->StyleIndexAt(
pos)].IsProtected())
805 for (
size_t r=0; r<
sel.
Count(); r++) {
823 if (posMoved !=
pos.Position())
824 pos.SetPosition(posMoved);
832 }
else if (moveDir < 0) {
834 while ((
pos.Position() > 0) &&
915 if (
pcs->GetVisible(lineDoc)) {
921 lineDisplay = Sci::clamp(lineDisplay,
static_cast<Sci::Line>(0),
pcs->LinesDisplayed());
925 lineDisplay = Sci::clamp(lineDisplay - 1,
static_cast<Sci::Line>(0),
pcs->LinesDisplayed());
999 const Sci::Line lineDisplay =
pcs->DisplayFromDoc(lineDoc);
1017 selectionStart = beginningOfStartLine;
1024 bool appendEol =
false;
1025 if (selectionEnd > beginningOfEndLine
1026 || selectionStart == selectionEnd) {
1034 if ((selectionStart == 0 && lineDelta < 0)
1035 || (selectionEnd ==
pdoc->
Length() && lineDelta > 0)
1036 || selectionStart == selectionEnd) {
1067 selectionLength += lengthInserted;
1083 if (pt.
y < rcClient.
top) {
1157 if (rcClient.
Empty()) {
1180 yMarginT = yMarginB = 0;
1186 yMarginB = yMarginT;
1188 yMarginB = linesOnScreen - yMarginT - 1;
1198 yMoveB = linesOnScreen - yMoveT - 1;
1200 if (lineCaret <
topLine + yMarginT) {
1202 newXY.
topLine = lineCaret - yMoveT;
1203 }
else if (lineCaret >
topLine + linesOnScreen - 1 - yMarginB) {
1205 newXY.
topLine = lineCaret - linesOnScreen + 1 + yMoveB;
1208 yMoveT = bJump ? policies.
y.
slop * 3 : policies.
y.
slop;
1209 yMoveT = Sci::clamp(yMoveT,
static_cast<Sci::Line>(1), halfScreen);
1213 yMoveB = linesOnScreen - yMoveT - 1;
1217 newXY.
topLine = lineCaret - yMoveT;
1218 }
else if (lineCaret >
topLine + linesOnScreen - 1) {
1220 newXY.
topLine = lineCaret - linesOnScreen + 1 + yMoveB;
1224 if (!bStrict && !bJump) {
1229 }
else if (lineCaret >
topLine + linesOnScreen - 1) {
1232 newXY.
topLine = lineCaret - linesOnScreen + 1;
1240 newXY.
topLine = lineCaret - halfScreen;
1249 if (lineAnchor < lineCaret) {
1264 const int halfScreen =
std::max(
static_cast<int>(rcClient.
Width()) - 4, 4) / 2;
1273 int xMarginL, xMarginR;
1277 xMarginL = xMarginR = 2;
1281 xMarginR = Sci::clamp(policies.
x.
slop, 2, halfScreen);
1283 xMarginL = xMarginR;
1285 xMarginL =
static_cast<int>(rcClient.
Width()) - xMarginR - 4;
1288 if (bJump && bEven) {
1290 xMoveL = xMoveR = Sci::clamp(policies.
x.
slop * 3, 1, halfScreen);
1292 xMoveL = xMoveR = 0;
1294 if (pt.
x < rcClient.
left + xMarginL) {
1296 if (bJump && bEven) {
1300 newXY.
xOffset -=
static_cast<int>((rcClient.
left + xMarginL) - pt.
x);
1302 }
else if (pt.
x >= rcClient.
right - xMarginR) {
1304 if (bJump && bEven) {
1308 newXY.
xOffset +=
static_cast<int>(pt.
x - (rcClient.
right - xMarginR) + 1);
1312 xMoveR = bJump ? policies.
x.
slop * 3 : policies.
x.
slop;
1313 xMoveR = Sci::clamp(xMoveR, 1, halfScreen);
1317 xMoveL =
static_cast<int>(rcClient.
Width()) - xMoveR - 4;
1319 if (pt.
x < rcClient.
left) {
1322 }
else if (pt.
x >= rcClient.
right) {
1329 (bJump && (pt.
x < rcClient.
left || pt.
x >= rcClient.
right))) {
1333 newXY.
xOffset +=
static_cast<int>(pt.
x - rcClient.
left - halfScreen);
1336 newXY.
xOffset +=
static_cast<int>(pt.
x - rcClient.
right + 1);
1340 if (pt.
x < rcClient.
left) {
1343 newXY.
xOffset -=
static_cast<int>(rcClient.
left - pt.
x);
1345 newXY.
xOffset +=
static_cast<int>(pt.
x - rcClient.
right) + 1;
1347 }
else if (pt.
x >= rcClient.
right) {
1349 newXY.
xOffset +=
static_cast<int>(pt.
x - rcClient.
right) + 1;
1364 if (ptAnchor.
x < pt.
x) {
1366 const int maxOffset =
static_cast<int>(ptAnchor.
x +
xOffset - rcClient.
left) - 1;
1367 const int minOffset =
static_cast<int>(pt.
x +
xOffset - rcClient.
right) + 1;
1372 const int minOffset =
static_cast<int>(ptAnchor.
x +
xOffset - rcClient.
right) + 1;
1373 const int maxOffset =
static_cast<int>(pt.
x +
xOffset - rcClient.
left) - 1;
1456 for (
size_t r=0; r<
sel.
Count(); r++) {
1486 int linesWrapped = 1;
1489 linesWrapped = ll->
lines;
1491 return pcs->SetHeight(lineToWrap, linesWrapped +
1502 bool wrapOccurred =
false;
1507 pcs->SetHeight(lineDoc, 1 +
1510 wrapOccurred =
true;
1530 lineToWrapEnd = lineDocTop;
1532 while ((lineToWrapEnd < pcs->LinesInDoc()) && (
lines>0)) {
1533 if (
pcs->GetVisible(lineToWrapEnd))
1544 constexpr double secondsAllowed = 0.01;
1545 const Sci::Line linesInAllowedTime = Sci::clamp(
1548 lineToWrapEnd = lineToWrap + linesInAllowedTime;
1551 lineToWrapEnd = std::min(lineToWrapEnd, lineEndNeedWrap);
1556 if (lineToWrap < lineToWrapEnd) {
1567 const Sci::Line linesBeingWrapped = lineToWrapEnd - lineToWrap;
1569 while (lineToWrap < lineToWrapEnd) {
1571 wrapOccurred =
true;
1578 goodTopLine =
pcs->DisplayFromDoc(lineDocTop) + std::min(
1579 subLineTop,
static_cast<Sci::Line>(
pcs->GetHeight(lineDocTop)-1));
1595 return wrapOccurred;
1601 bool prevNonWS =
true;
1630 if (pixelWidth == 0) {
1632 pixelWidth =
static_cast<int>(rcText.
Width());
1641 if (surface && ll) {
1645 for (
int subLine = 1; subLine < ll->
lines; subLine++) {
1647 posLineStart + lengthInsertedTotal + ll->
LineStart(subLine),
1650 lengthInsertedTotal += lengthInserted;
1675 rcMargin.
Move(0, -ptOrigin.
y);
1686 surface = surfaceWindow;
1692 if (rcMargin.
top < rc.
top)
1760 surfaceWindow->
SetClip(rcArea);
1772 rcLeftMargin.
left = 0;
1817 if (!surfaceMeasure) {
1875 if (virtualSpace > 0) {
1881 std::string spaceText(virtualSpace,
' ');
1918 std::vector<SelectionRange *> selPtrs;
1919 for (
size_t r = 0; r <
sel.
Count(); r++) {
1923 std::sort(selPtrs.begin(), selPtrs.end(),
1927 for (std::vector<SelectionRange *>::reverse_iterator rit = selPtrs.rbegin();
1928 rit != selPtrs.rend(); ++rit) {
1933 if (!currentSel->
Empty()) {
1934 if (currentSel->
Length()) {
1942 if (positionInsert < pdoc->Length()) {
1951 if (lengthInserted > 0) {
1983 int ch =
static_cast<unsigned char>(s[0]);
1987 ch = (ch << 8) | static_cast<unsigned char>(s[1]);
1990 if ((ch < 0xC0) || (1 == len)) {
1996 unsigned int utf32[1] = { 0 };
2004 std::string copy(s, len);
2013 for (
size_t r = 0; r<
sel.
Count(); r++) {
2037 if (lengthInserted > 0) {
2042 for (
size_t r=0; r<
sel.
Count(); r++) {
2057 if (lengthInserted > 0) {
2068 std::string convertedText;
2072 len = convertedText.length();
2073 text = convertedText.c_str();
2083 if ((len > 0) && (
text[len - 1] !=
'\n' &&
text[len - 1] !=
'\r')) {
2086 lengthInserted +=
pdoc->
InsertString(insertPos + lengthInserted, endline, length);
2101 for (
size_t r=0; r<
sel.
Count(); r++) {
2172 bool prevCr =
false;
2177 if ((
ptr[i] ==
'\r') || (!prevCr))
2194 prevCr =
ptr[i] ==
'\r';
2211 bool singleVirtual =
false;
2215 singleVirtual =
true;
2218 for (
size_t r=0; r<
sel.
Count(); r++) {
2271 allowLineStartDeletion =
false;
2274 for (
size_t r=0; r<
sel.
Count(); r++) {
2288 int indentationChange =
indentation % indentationStep;
2289 if (indentationChange == 0)
2290 indentationChange = indentationStep;
2439 if ((marginClicked >= 0) &&
vs.
ms[marginClicked].sensitive) {
2442 const bool ctrl = (modifiers &
SCI_CTRL) != 0;
2443 const bool shift = (modifiers &
SCI_SHIFT) != 0;
2445 if (shift && ctrl) {
2467 scn.
margin = marginClicked;
2477 if ((marginRightClicked >= 0) &&
vs.
ms[marginRightClicked].sensitive) {
2483 scn.
margin = marginRightClicked;
2504 scn.
y =
static_cast<int>(pt.
y);
2557 return startDeletion;
2632 if (lineLast < lineMaxSubord) {
2633 lineLast = lineMaxSubord;
2694 if (mh.
linesAdded != 0 && !CanDeferToLastStep(mh)) {
2713 if (IsLastStep(mh)) {
2880 needUpdateUI |= flags;
2900 if (stuttered && (direction < 0 && currentLine > topStutterLine)) {
2905 }
else if (stuttered && (direction > 0 && currentLine < bottomStutterLine)) {
2913 topLineNew = Sci::clamp(
2933 for (
size_t r=0; r<
sel.
Count(); r++) {
2937 const size_t rangeBytes = currentNoVS.
Length();
2938 if (rangeBytes > 0) {
2943 if (sMapped != sText) {
2944 size_t firstDifference = 0;
2945 while (sMapped[firstDifference] == sText[firstDifference])
2947 size_t lastDifferenceText = sText.size() - 1;
2948 size_t lastDifferenceMapped = sMapped.size() - 1;
2949 while (sMapped[lastDifferenceMapped] == sText[lastDifferenceText]) {
2950 lastDifferenceText--;
2951 lastDifferenceMapped--;
2953 const size_t endDifferenceText = sText.size() - 1 - lastDifferenceText;
2956 rangeBytes - firstDifference - endDifferenceText);
2957 const Sci::Position lengthChange = lastDifferenceMapped - firstDifference + 1;
2960 sMapped.c_str() + firstDifference,
2963 const Sci::Position diffSizes = sMapped.size() - sText.size() + lengthInserted - lengthChange;
2964 if (diffSizes != 0) {
2989 startCurrent -= linePrevious.length();
2992 lineCurrent.length());
2994 linePrevious.length());
3005 const Sci::Line lineDiff = lineEnd - lineStart;
3009 for (
Sci::Line i=(lineDiff+1)/2-1; i>=0; --i) {
3011 const Sci::Line lineNum1 = lineStart + i;
3020 lineStart2 -= lineLen1;
3034 const char *eol =
"";
3038 eolLen = strlen(eol);
3040 for (
size_t r=0; r<
sel.
Count(); r++) {
3088 size_t countInsertions = 0;
3089 for (
size_t r = 0; r <
sel.
Count(); r++) {
3094 if (insertLength > 0) {
3102 for (
size_t i = 0; i < countInsertions; i++) {
3130 const int subLine =
static_cast<int>(pt.
y - ptStartLine.
y) /
vs.
lineHeight;
3132 if (direction < 0 && subLine == 0) {
3133 const Sci::Line lineDisplay =
pcs->DisplayFromDoc(lineDoc);
3134 if (lineDisplay > 0) {
3144 lastX =
static_cast<int>(pt.
x) +
xOffset;
3149 if (direction < 0) {
3153 while ((posNew.
Position() > 0) && (pt.
y == ptNew.
y)) {
3206 for (
size_t r = 0; r <
sel.
Count(); r++) {
3225 if (direction > 0) {
3233 }
while (!
pcs->GetVisible(lineDoc));
3255constexpr short HighShortFromWParam(
uptr_t x) {
3256 return static_cast<short>(x >> 16);
3259constexpr short LowShortFromWParam(
uptr_t x) {
3260 return static_cast<short>(x & 0xffff);
3263unsigned int WithExtends(
unsigned int iMessage)
noexcept {
3286 default:
return iMessage;
3290int NaturalDirection(
unsigned int iMessage)
noexcept {
3321bool IsRectExtend(
unsigned int iMessage,
bool isRectMoveExtends)
noexcept {
3330 if (isRectMoveExtends) {
3352 if (viewLineStart > homePos)
3353 return viewLineStart;
3361 if ((viewLineStart <
position) && (viewLineStart > homePos))
3362 return viewLineStart;
3370 if (endPos > realEndPos
3382 iMessage = WithExtends(iMessage);
3431 const int directionMove = (spCaret < rangeBase.
caret) ? -1 : 1;
3458 for (
size_t r = 0; r <
sel.
Count(); r++) {
3514 if (spCaretNow <= spCaret)
3548 const int directionMove = (spCaret < spCaretNow) ? -1 : 1;
3637 for (
size_t r = 0; r <
sel.
Count(); r++) {
3650 rangeDelete =
Range(
3655 rangeDelete =
Range(
3660 rangeDelete =
Range(
3665 rangeDelete =
Range(
3670 rangeDelete =
Range(