[BUG_FIXED] (Author: Andreas Jonsson) Fix Ctrl+double click delimiter selection bug.

git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@1059 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
Don Ho 2013-06-14 19:37:20 +00:00
parent 896c705979
commit d39c743ff4

View File

@ -32,6 +32,7 @@
#include "VerticalFileSwitcher.h" #include "VerticalFileSwitcher.h"
#include "ProjectPanel.h" #include "ProjectPanel.h"
#include "documentMap.h" #include "documentMap.h"
#include <stack>
BOOL Notepad_plus::notify(SCNotification *notification) BOOL Notepad_plus::notify(SCNotification *notification)
{ {
@ -437,9 +438,14 @@ BOOL Notepad_plus::notify(SCNotification *notification)
{ {
const NppGUI & nppGUI = NppParameters::getInstance()->getNppGUI(); const NppGUI & nppGUI = NppParameters::getInstance()->getNppGUI();
std::string bufstring;
unsigned int position_of_click;
// Anonymous scope to limit use of the buf pointer (much easier to deal with std::string).
{
char *buf; char *buf;
int length; int length;
int position_of_click;
if(nppGUI._delimiterSelectionOnEntireDocument) if(nppGUI._delimiterSelectionOnEntireDocument)
{ {
// Get entire document. // Get entire document.
@ -447,7 +453,12 @@ BOOL Notepad_plus::notify(SCNotification *notification)
buf = new char[length + 1]; buf = new char[length + 1];
notifyView->execute(SCI_GETTEXT, (LPARAM)(length + 1), (WPARAM)buf); notifyView->execute(SCI_GETTEXT, (LPARAM)(length + 1), (WPARAM)buf);
// For some reason Ctrl+DoubleClick on an empty line means that notification->position == 1.
// In that case we use SCI_GETCURRENTPOS to get the position.
if(notification->position != -1)
position_of_click = notification->position; position_of_click = notification->position;
else
position_of_click = int(_pEditView->execute(SCI_GETCURRENTPOS));
} }
else else
{ {
@ -461,11 +472,21 @@ BOOL Notepad_plus::notify(SCNotification *notification)
position_of_click = notification->position - line_position; position_of_click = notification->position - line_position;
} }
// Scan for the left delimiter. bufstring = buf;
delete [] buf;
}
int leftmost_position = -1; int leftmost_position = -1;
for(int i = position_of_click; i >= 0; --i) int rightmost_position = -1;
if(nppGUI._rightmostDelimiter == nppGUI._leftmostDelimiter)
{ {
if(buf[i] == nppGUI._leftmostDelimiter) // If the delimiters are the same (e.g. they are both a quotation mark), choose the ones
// which are closest to the clicked position.
for(unsigned int i = position_of_click; i >= 0; --i)
{
if(bufstring.at(i) == nppGUI._leftmostDelimiter)
{ {
leftmost_position = i; leftmost_position = i;
break; break;
@ -473,29 +494,55 @@ BOOL Notepad_plus::notify(SCNotification *notification)
} }
if(leftmost_position == -1) if(leftmost_position == -1)
{
delete [] buf;
break; break;
}
// Scan for right delimiter. // Scan for right delimiter.
int rightmost_position = -1; for(unsigned int i = position_of_click; i < bufstring.length(); ++i)
for(int i = position_of_click; i <= length; ++i)
{ {
if(buf[i] == nppGUI._rightmostDelimiter) if(bufstring.at(i) == nppGUI._rightmostDelimiter)
{ {
rightmost_position = i; rightmost_position = i;
break; break;
} }
} }
}
if(rightmost_position == -1) else
{ {
delete [] buf; // Find matching pairs of delimiters (e.g. parantheses).
break; // The pair where the distance from the left delimiter to position_of_click is at a minimum is the one we're looking for.
// Of course position_of_click must lie between the delimiters.
// This logic is required to handle cases like this:
// (size_t i = function(); i < _buffers.size(); i++)
std::stack<unsigned int> leftmost_delimiter_positions;
for(unsigned int i = 0; i < bufstring.length(); ++i)
{
if(bufstring.at(i) == nppGUI._leftmostDelimiter)
leftmost_delimiter_positions.push(i);
else if(bufstring.at(i) == nppGUI._rightmostDelimiter && ! leftmost_delimiter_positions.empty())
{
unsigned int matching_leftmost = leftmost_delimiter_positions.top();
leftmost_delimiter_positions.pop();
// We have either 1) chosen neither the left- or rightmost position, or 2) chosen both left- and rightmost position.
assert( (leftmost_position == -1 && rightmost_position == -1) || (leftmost_position >= 0 && rightmost_position >= 0) );
// Note: cast of leftmost_position to unsigned int is safe, since if leftmost_position is not -1 then it is guaranteed to be positive.
// If it was possible, leftmost_position and rightmost_position should be of type optional<unsigned int>.
if( matching_leftmost <= position_of_click && i >= position_of_click && (leftmost_position == -1 || matching_leftmost > (unsigned int)leftmost_position) )
{
leftmost_position = matching_leftmost;
rightmost_position = i;
}
}
}
} }
// Set selection to the position we found. // Set selection to the position we found (if any).
if(rightmost_position != -1 && leftmost_position != -1)
{
if(nppGUI._delimiterSelectionOnEntireDocument) if(nppGUI._delimiterSelectionOnEntireDocument)
{ {
notifyView->execute(SCI_SETCURRENTPOS, rightmost_position); notifyView->execute(SCI_SETCURRENTPOS, rightmost_position);
@ -507,8 +554,7 @@ BOOL Notepad_plus::notify(SCNotification *notification)
notifyView->execute(SCI_SETCURRENTPOS, line_position + rightmost_position); notifyView->execute(SCI_SETCURRENTPOS, line_position + rightmost_position);
notifyView->execute(SCI_SETANCHOR, line_position + leftmost_position + 1); notifyView->execute(SCI_SETANCHOR, line_position + leftmost_position + 1);
} }
}
delete [] buf;
} }
else if (_isHotspotDblClicked) else if (_isHotspotDblClicked)
{ {