Enhance Sel info provided in main status bar

Fix #8524, close #8876
This commit is contained in:
Scott Sumner 2020-09-09 17:06:59 -04:00 committed by Don HO
parent bbde64c308
commit 8426c9ccd9
No known key found for this signature in database
GPG Key ID: 6C429F1D8D84F46E
5 changed files with 176 additions and 69 deletions

View File

@ -3653,36 +3653,92 @@ int Notepad_plus::wordCount()
return _findReplaceDlg.processAll(ProcessCountAll, &env, true);
}
void Notepad_plus::updateStatusBar()
{
TCHAR strLnCol[128];
TCHAR strSel[64];
int selByte = 0;
int selLine = 0;
// these sections of status bar NOT updated by this function:
// STATUSBAR_DOC_TYPE , STATUSBAR_EOF_FORMAT , STATUSBAR_UNICODE_TYPE
_pEditView->getSelectedCount(selByte, selLine);
long selected_length = _pEditView->getUnicodeSelectedLength();
if (selected_length != -1)
wsprintf(strSel, TEXT("Sel : %s | %s"), commafyInt(selected_length).c_str(), commafyInt(selLine).c_str());
else
wsprintf(strSel, TEXT("Sel : %s"), TEXT("N/A"));
wsprintf(strLnCol, TEXT("Ln : %s Col : %s %s"),
commafyInt(_pEditView->getCurrentLineNumber() + 1).c_str(),
commafyInt(_pEditView->getCurrentColumnNumber() + 1).c_str(),
strSel);
_statusBar.setText(strLnCol, STATUSBAR_CUR_POS);
TCHAR strDocLen[256];
TCHAR strDocLen[256];
wsprintf(strDocLen, TEXT("length : %s lines : %s"),
commafyInt(_pEditView->getCurrentDocLen()).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);
TCHAR strSel[64];
int numSelections = static_cast<int>(_pEditView->execute(SCI_GETSELECTIONS));
if (numSelections == 1)
{
if (_pEditView->execute(SCI_GETSELECTIONEMPTY))
{
int currPos = static_cast<int>(_pEditView->execute(SCI_GETCURRENTPOS));
wsprintf(strSel, TEXT("Pos : %s"), commafyInt(currPos + 1).c_str());
}
else
{
const std::pair<int, int> oneSelCharsAndLines = _pEditView->getSelectedCharsAndLinesCount();
wsprintf(strSel, TEXT("Sel : %s | %s"),
commafyInt(oneSelCharsAndLines.first).c_str(),
commafyInt(oneSelCharsAndLines.second).c_str());
}
}
else if (_pEditView->execute(SCI_SELECTIONISRECTANGLE))
{
const std::pair<int, int> rectSelCharsAndLines = _pEditView->getSelectedCharsAndLinesCount();
bool sameCharCountOnEveryLine = true;
int maxLineCharCount = 0;
for (int sel = 0; sel < numSelections; ++sel)
{
int start = static_cast<int>(_pEditView->execute(SCI_GETSELECTIONNSTART, sel));
int end = static_cast<int>(_pEditView->execute(SCI_GETSELECTIONNEND, sel));
int lineCharCount = static_cast<int>(_pEditView->execute(SCI_COUNTCHARACTERS, start, end));
if (sel == 0)
{
maxLineCharCount = lineCharCount;
}
else
{
if (lineCharCount != maxLineCharCount)
{
sameCharCountOnEveryLine = false;
if (lineCharCount > maxLineCharCount)
{
maxLineCharCount = lineCharCount;
}
}
}
}
wsprintf(strSel, TEXT("Sel : %sx%s %s %s"),
commafyInt(numSelections).c_str(), // lines (rows) in rectangular selection
commafyInt(maxLineCharCount).c_str(), // show maximum width for columns
sameCharCountOnEveryLine ? TEXT("=") : TEXT("->"),
commafyInt(rectSelCharsAndLines.first).c_str());
}
else // multiple stream selections
{
const int maxSelsToProcessLineCount = 99; // limit the number of selections to process, for performance reasons
const std::pair<int, int> multipleSelCharsAndLines = _pEditView->getSelectedCharsAndLinesCount(maxSelsToProcessLineCount);
wsprintf(strSel, TEXT("Sel %s : %s | %s"),
commafyInt(numSelections).c_str(),
commafyInt(multipleSelCharsAndLines.first).c_str(),
numSelections <= maxSelsToProcessLineCount ?
commafyInt(multipleSelCharsAndLines.second).c_str() :
TEXT("...")); // show ellipsis for line count if too many selections are active
}
TCHAR strLnColSel[128];
wsprintf(strLnColSel, TEXT("Ln : %s Col : %s %s"),
commafyInt(_pEditView->getCurrentLineNumber() + 1).c_str(),
commafyInt(_pEditView->getCurrentColumnNumber() + 1).c_str(),
strSel);
_statusBar.setText(strLnColSel, STATUSBAR_CUR_POS);
_statusBar.setText(_pEditView->execute(SCI_GETOVERTYPE) ? TEXT("OVR") : TEXT("INS"), STATUSBAR_TYPING_MODE);
}
void Notepad_plus::dropFiles(HDROP hdrop)

View File

@ -1521,9 +1521,9 @@ void Notepad_plus::command(int id)
case IDM_EDIT_SPLIT_LINES:
{
pair<int, int> lineRange = _pEditView->getSelectionLinesRange();
if (lineRange.first != -1)
if (_pEditView->execute(SCI_GETSELECTIONS) == 1)
{
pair<int, int> lineRange = _pEditView->getSelectionLinesRange();
auto anchorPos = _pEditView->execute(SCI_POSITIONFROMLINE, lineRange.first);
auto caretPos = _pEditView->execute(SCI_GETLINEENDPOSITION, lineRange.second);
_pEditView->execute(SCI_SETSELECTION, caretPos, anchorPos);

View File

@ -890,7 +890,14 @@ BOOL Notepad_plus::notify(SCNotification *notification)
}
}
updateStatusBar();
bool selectionIsChanged = (notification->updated & SC_UPDATE_SELECTION) != 0;
// note: changing insert/overwrite mode will cause Scintilla to notify with SC_UPDATE_SELECTION
bool contentIsChanged = (notification->updated & SC_UPDATE_CONTENT) != 0;
if (selectionIsChanged || contentIsChanged)
{
updateStatusBar();
}
if (_pFuncList && (!_pFuncList->isClosed()) && _pFuncList->isVisible())
_pFuncList->markEntry();
AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub;

View File

@ -2789,27 +2789,36 @@ void ScintillaEditView::setMultiSelections(const ColumnModeInfos & cmi)
}
}
// Get selection range : (fromLine, toLine)
// return (-1, -1) if multi-selection
pair<int, int> ScintillaEditView::getSelectionLinesRange() const
// Get selection range (fromLine, toLine) for the specified selection
// specify selectionNumber = -1 for the MAIN selection
pair<int, int> ScintillaEditView::getSelectionLinesRange(int selectionNumber /* = -1 */) const
{
pair<int, int> range(-1, -1);
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));
int numSelections = static_cast<int>(execute(SCI_GETSELECTIONS));
range.first = static_cast<int32_t>(execute(SCI_LINEFROMPOSITION, start));
range.second = static_cast<int32_t>(execute(SCI_LINEFROMPOSITION, end));
int start_pos, end_pos;
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,
// 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
@ -3715,3 +3724,65 @@ void ScintillaEditView::getFoldColor(COLORREF& fgColor, COLORREF& bgColor, COLOR
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 (execute(SCI_SELECTIONISRECTANGLE))
{
selectedCharsAndLines.second = numSelections;
}
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;
};

View File

@ -459,36 +459,9 @@ public:
return long(execute(SCI_GETCOLUMN, execute(SCI_GETCURRENTPOS)));
};
bool getSelectedCount(int & selByte, int & selLine) 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;
};
std::pair<int, int> getSelectedCharsAndLinesCount(int maxSelectionsForLineCount = -1) const;
int getUnicodeSelectedLength() const;
long getLineLength(int line) const {
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);
std::pair<int, int> getSelectionLinesRange() const;
std::pair<int, int> getSelectionLinesRange(int selectionNumber = -1) const;
void currentLinesUp() const;
void currentLinesDown() const;