mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-21 21:04:54 +02:00
Enhance info provided in Sel portion of main status bar
No selection: Example: Pos : 1,234 Meaning: Single caret is at position 1233 in document (user position 1234) Single stream selection (no change to existing behavior): Example: Sel : 27 | 2 Meaning: 27 characters selected on 2 lines Multiple stream selections (this PR behavior): Example: Sel 3 : 72 | 6 Meaning: 3 selections of 72 characters on 6 lines Rectangular selection with no virtual space in column block (this PR behavior): Example: Sel : 2x4 = 8 Meaning: selection of 2 rows(lines) by 4 columns; 8 characters in that selection Rectangular selection with some virtual space in column block (this PR behavior): Example: Sel : 2x4 🡢 6 Meaning: selection of 2 rows(lines) by 4 columns; 6 real characters in that selection Close #8524, close #8780
This commit is contained in:
parent
3fd3e85a54
commit
4ca25503bc
@ -3235,33 +3235,65 @@ int Notepad_plus::wordCount()
|
|||||||
|
|
||||||
void Notepad_plus::updateStatusBar()
|
void Notepad_plus::updateStatusBar()
|
||||||
{
|
{
|
||||||
TCHAR strLnCol[128];
|
TCHAR strLnCol[128];
|
||||||
TCHAR strSel[64];
|
TCHAR strSel[64];
|
||||||
int selByte = 0;
|
|
||||||
int selLine = 0;
|
|
||||||
|
|
||||||
_pEditView->getSelectedCount(selByte, selLine);
|
int selCount = static_cast<int>(_pEditView->execute(SCI_GETSELECTIONS));
|
||||||
|
|
||||||
long selected_length = _pEditView->getUnicodeSelectedLength();
|
const int maxSelsToProcessLineCount = 99; // limit the number of selections to process, for performance reasons
|
||||||
if (selected_length != -1)
|
const std::pair<int, int> selCharsAndLines = _pEditView->getSelectedCharsAndLinesCount(maxSelsToProcessLineCount);
|
||||||
wsprintf(strSel, TEXT("Sel : %s | %s"), commafyInt(selected_length).c_str(), commafyInt(selLine).c_str());
|
|
||||||
|
if (_pEditView->execute(SCI_SELECTIONISRECTANGLE))
|
||||||
|
{
|
||||||
|
int rectAnchor = static_cast<int>(_pEditView->execute(SCI_GETCOLUMN, _pEditView->execute(SCI_GETRECTANGULARSELECTIONANCHOR)));
|
||||||
|
rectAnchor += static_cast<int>(_pEditView->execute(SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE));
|
||||||
|
int rectCaret = static_cast<int>(_pEditView->execute(SCI_GETCOLUMN, _pEditView->execute(SCI_GETRECTANGULARSELECTIONCARET)));
|
||||||
|
rectCaret += static_cast<int>(_pEditView->execute(SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE));
|
||||||
|
int rectWidth = std::abs(rectCaret - rectAnchor);
|
||||||
|
bool hasVirtualSpace = selCharsAndLines.first != selCount * rectWidth;
|
||||||
|
|
||||||
|
wsprintf(strSel, TEXT("Sel : %sx%s %s %s"),
|
||||||
|
commafyInt(selCount).c_str(),
|
||||||
|
commafyInt(rectWidth).c_str(),
|
||||||
|
hasVirtualSpace ? TEXT("🡢") : TEXT("="),
|
||||||
|
commafyInt(selCharsAndLines.first).c_str());
|
||||||
|
}
|
||||||
|
else if (selCount > 1)
|
||||||
|
{
|
||||||
|
wsprintf(strSel, TEXT("Sel %s : %s | %s"),
|
||||||
|
commafyInt(selCount).c_str(),
|
||||||
|
commafyInt(selCharsAndLines.first).c_str(),
|
||||||
|
selCount <= maxSelsToProcessLineCount ?
|
||||||
|
commafyInt(selCharsAndLines.second).c_str() :
|
||||||
|
TEXT("…")); // show ellipsis for line count if too many selections are active
|
||||||
|
}
|
||||||
|
else if (selCharsAndLines.first > 0)
|
||||||
|
{
|
||||||
|
wsprintf(strSel, TEXT("Sel : %s | %s"),
|
||||||
|
commafyInt(selCharsAndLines.first).c_str(),
|
||||||
|
commafyInt(selCharsAndLines.second).c_str());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
wsprintf(strSel, TEXT("Sel : %s"), TEXT("N/A"));
|
{
|
||||||
|
int curPos = static_cast<int>(_pEditView->execute(SCI_GETCURRENTPOS));
|
||||||
|
|
||||||
|
wsprintf(strSel, TEXT("Pos : %s"), commafyInt(curPos + 1).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
wsprintf(strLnCol, TEXT("Ln : %s Col : %s %s"),
|
wsprintf(strLnCol, TEXT("Ln : %s Col : %s %s"),
|
||||||
commafyInt(_pEditView->getCurrentLineNumber() + 1).c_str(),
|
commafyInt(_pEditView->getCurrentLineNumber() + 1).c_str(),
|
||||||
commafyInt(_pEditView->getCurrentColumnNumber() + 1).c_str(),
|
commafyInt(_pEditView->getCurrentColumnNumber() + 1).c_str(),
|
||||||
strSel);
|
strSel);
|
||||||
|
|
||||||
_statusBar.setText(strLnCol, STATUSBAR_CUR_POS);
|
_statusBar.setText(strLnCol, STATUSBAR_CUR_POS);
|
||||||
|
|
||||||
TCHAR strDocLen[256];
|
TCHAR strDocLen[256];
|
||||||
wsprintf(strDocLen, TEXT("length : %s lines : %s"),
|
wsprintf(strDocLen, TEXT("length : %s lines : %s"),
|
||||||
commafyInt(_pEditView->getCurrentDocLen()).c_str(),
|
commafyInt(_pEditView->getCurrentDocLen()).c_str(),
|
||||||
commafyInt(_pEditView->execute(SCI_GETLINECOUNT)).c_str());
|
commafyInt(_pEditView->execute(SCI_GETLINECOUNT)).c_str());
|
||||||
|
|
||||||
_statusBar.setText(strDocLen, STATUSBAR_DOC_SIZE);
|
_statusBar.setText(strDocLen, STATUSBAR_DOC_SIZE);
|
||||||
_statusBar.setText(_pEditView->execute(SCI_GETOVERTYPE) ? TEXT("OVR") : TEXT("INS"), STATUSBAR_TYPING_MODE);
|
_statusBar.setText(_pEditView->execute(SCI_GETOVERTYPE) ? TEXT("OVR") : TEXT("INS"), STATUSBAR_TYPING_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notepad_plus::dropFiles(HDROP hdrop)
|
void Notepad_plus::dropFiles(HDROP hdrop)
|
||||||
|
@ -1484,9 +1484,9 @@ void Notepad_plus::command(int id)
|
|||||||
|
|
||||||
case IDM_EDIT_SPLIT_LINES:
|
case IDM_EDIT_SPLIT_LINES:
|
||||||
{
|
{
|
||||||
pair<int, int> lineRange = _pEditView->getSelectionLinesRange();
|
if (_pEditView->execute(SCI_GETSELECTIONS) == 1)
|
||||||
if (lineRange.first != -1)
|
|
||||||
{
|
{
|
||||||
|
pair<int, int> lineRange = _pEditView->getSelectionLinesRange();
|
||||||
auto anchorPos = _pEditView->execute(SCI_POSITIONFROMLINE, lineRange.first);
|
auto anchorPos = _pEditView->execute(SCI_POSITIONFROMLINE, lineRange.first);
|
||||||
auto caretPos = _pEditView->execute(SCI_GETLINEENDPOSITION, lineRange.second);
|
auto caretPos = _pEditView->execute(SCI_GETLINEENDPOSITION, lineRange.second);
|
||||||
_pEditView->execute(SCI_SETSELECTION, caretPos, anchorPos);
|
_pEditView->execute(SCI_SETSELECTION, caretPos, anchorPos);
|
||||||
|
@ -2787,27 +2787,36 @@ void ScintillaEditView::setMultiSelections(const ColumnModeInfos & cmi)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get selection range : (fromLine, toLine)
|
// Get selection range (fromLine, toLine) for the specified selection
|
||||||
// return (-1, -1) if multi-selection
|
// specify selectionNumber = -1 for the MAIN selection
|
||||||
pair<int, int> ScintillaEditView::getSelectionLinesRange() const
|
pair<int, int> ScintillaEditView::getSelectionLinesRange(int selectionNumber /* = -1 */) const
|
||||||
{
|
{
|
||||||
pair<int, int> range(-1, -1);
|
int numSelections = static_cast<int>(execute(SCI_GETSELECTIONS));
|
||||||
if (execute(SCI_GETSELECTIONS) > 1) // multi-selection
|
|
||||||
return range;
|
|
||||||
int32_t start = static_cast<int32_t>(execute(SCI_GETSELECTIONSTART));
|
|
||||||
int32_t end = static_cast<int32_t>(execute(SCI_GETSELECTIONEND));
|
|
||||||
|
|
||||||
range.first = static_cast<int32_t>(execute(SCI_LINEFROMPOSITION, start));
|
int start_pos, end_pos;
|
||||||
range.second = static_cast<int32_t>(execute(SCI_LINEFROMPOSITION, end));
|
|
||||||
|
|
||||||
if ((range.first != range.second) && (execute(SCI_POSITIONFROMLINE, range.second) == end))
|
if ((selectionNumber < 0) || (selectionNumber >= numSelections))
|
||||||
|
{
|
||||||
|
start_pos = static_cast<int>(execute(SCI_GETSELECTIONSTART));
|
||||||
|
end_pos = static_cast<int>(execute(SCI_GETSELECTIONEND));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start_pos = static_cast<int>(execute(SCI_GETSELECTIONNSTART, selectionNumber));
|
||||||
|
end_pos = static_cast<int>(execute(SCI_GETSELECTIONNEND, selectionNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
int line1 = static_cast<int>(execute(SCI_LINEFROMPOSITION, start_pos));
|
||||||
|
int line2 = static_cast<int>(execute(SCI_LINEFROMPOSITION, end_pos));
|
||||||
|
|
||||||
|
if ((line1 != line2) && (execute(SCI_POSITIONFROMLINE, line2) == end_pos))
|
||||||
{
|
{
|
||||||
// if the end of the selection includes the line-ending,
|
// if the end of the selection includes the line-ending,
|
||||||
// then don't include the following line in the range
|
// then don't include the following line in the range
|
||||||
--range.second;
|
--line2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return range;
|
return pair<int, int>(line1, line2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScintillaEditView::currentLinesUp() const
|
void ScintillaEditView::currentLinesUp() const
|
||||||
@ -3713,3 +3722,61 @@ void ScintillaEditView::getFoldColor(COLORREF& fgColor, COLORREF& bgColor, COLOR
|
|||||||
activeFgColor = style._fgColor;
|
activeFgColor = style._fgColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pair<int, int> ScintillaEditView::getSelectedCharsAndLinesCount(int maxSelectionsForLineCount /* = -1 */) const
|
||||||
|
{
|
||||||
|
pair<int, int> selectedCharsAndLines(0, 0);
|
||||||
|
|
||||||
|
selectedCharsAndLines.first = getUnicodeSelectedLength();
|
||||||
|
|
||||||
|
int numSelections = static_cast<int>(execute(SCI_GETSELECTIONS));
|
||||||
|
|
||||||
|
if (numSelections == 1)
|
||||||
|
{
|
||||||
|
pair<int, int> lineRange = getSelectionLinesRange();
|
||||||
|
selectedCharsAndLines.second = lineRange.second - lineRange.first + 1;
|
||||||
|
}
|
||||||
|
else if ((maxSelectionsForLineCount == -1) || // -1 means process ALL of the selections
|
||||||
|
(numSelections <= maxSelectionsForLineCount))
|
||||||
|
{
|
||||||
|
// selections are obtained from Scintilla in the order user creates them,
|
||||||
|
// not in a lowest-to-highest position-based order;
|
||||||
|
// to be able to get a line-count that can't count the same line more than once,
|
||||||
|
// we have to reorder the lines touched
|
||||||
|
// by selection into low-to-high line number order before processing them further
|
||||||
|
|
||||||
|
vector< pair <int, int> > v;
|
||||||
|
for (int s = 0; s < numSelections; ++s)
|
||||||
|
{
|
||||||
|
v.push_back(getSelectionLinesRange(s));
|
||||||
|
}
|
||||||
|
sort(v.begin(), v.end());
|
||||||
|
int previousSecondLine = -1;
|
||||||
|
for (auto lineRange : v)
|
||||||
|
{
|
||||||
|
selectedCharsAndLines.second += lineRange.second - lineRange.first;
|
||||||
|
if (lineRange.first != previousSecondLine)
|
||||||
|
{
|
||||||
|
++selectedCharsAndLines.second;
|
||||||
|
}
|
||||||
|
previousSecondLine = lineRange.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectedCharsAndLines;
|
||||||
|
};
|
||||||
|
|
||||||
|
int ScintillaEditView::getUnicodeSelectedLength() const
|
||||||
|
{
|
||||||
|
int length = 0;
|
||||||
|
int numSelections = static_cast<int>(execute(SCI_GETSELECTIONS));
|
||||||
|
|
||||||
|
for (int s = 0; s < numSelections; ++s)
|
||||||
|
{
|
||||||
|
int start = static_cast<int>(execute(SCI_GETSELECTIONNSTART, s));
|
||||||
|
int end = static_cast<int>(execute(SCI_GETSELECTIONNEND, s));
|
||||||
|
length += static_cast<int>(execute(SCI_COUNTCHARACTERS, start, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
};
|
||||||
|
@ -459,36 +459,9 @@ public:
|
|||||||
return long(execute(SCI_GETCOLUMN, execute(SCI_GETCURRENTPOS)));
|
return long(execute(SCI_GETCOLUMN, execute(SCI_GETCURRENTPOS)));
|
||||||
};
|
};
|
||||||
|
|
||||||
bool getSelectedCount(int & selByte, int & selLine) const {
|
std::pair<int, int> getSelectedCharsAndLinesCount(int maxSelectionsForLineCount = -1) const;
|
||||||
// return false if it's multi-selection or rectangle selection
|
|
||||||
if ((execute(SCI_GETSELECTIONS) > 1) || execute(SCI_SELECTIONISRECTANGLE))
|
|
||||||
return false;
|
|
||||||
long pStart = long(execute(SCI_GETSELECTIONSTART));
|
|
||||||
long pEnd = long(execute(SCI_GETSELECTIONEND));
|
|
||||||
selByte = pEnd - pStart;
|
|
||||||
|
|
||||||
long lStart = long(execute(SCI_LINEFROMPOSITION, pStart));
|
|
||||||
long lEnd = long(execute(SCI_LINEFROMPOSITION, pEnd));
|
|
||||||
selLine = lEnd - lStart;
|
|
||||||
if (selLine || selByte)
|
|
||||||
++selLine;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
long getUnicodeSelectedLength() const
|
|
||||||
{
|
|
||||||
// return -1 if it's multi-selection or rectangle selection
|
|
||||||
if ((execute(SCI_GETSELECTIONS) > 1) || execute(SCI_SELECTIONISRECTANGLE))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
long start = long(execute(SCI_GETSELECTIONSTART));
|
|
||||||
long end = long(execute(SCI_GETSELECTIONEND));
|
|
||||||
long length = long(execute(SCI_COUNTCHARACTERS, start, end));
|
|
||||||
|
|
||||||
return length;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
int getUnicodeSelectedLength() const;
|
||||||
|
|
||||||
long getLineLength(int line) const {
|
long getLineLength(int line) const {
|
||||||
return long(execute(SCI_GETLINEENDPOSITION, line) - execute(SCI_POSITIONFROMLINE, line));
|
return long(execute(SCI_GETLINEENDPOSITION, line) - execute(SCI_POSITIONFROMLINE, line));
|
||||||
@ -531,7 +504,7 @@ public:
|
|||||||
|
|
||||||
void expand(size_t& line, bool doExpand, bool force = false, int visLevels = 0, int level = -1);
|
void expand(size_t& line, bool doExpand, bool force = false, int visLevels = 0, int level = -1);
|
||||||
|
|
||||||
std::pair<int, int> getSelectionLinesRange() const;
|
std::pair<int, int> getSelectionLinesRange(int selectionNumber = -1) const;
|
||||||
void currentLinesUp() const;
|
void currentLinesUp() const;
|
||||||
void currentLinesDown() const;
|
void currentLinesDown() const;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user