Fix clickable links break syntax highlighting issue
By using indicators instead of stylers to make code shorter and cleaner. Fix #999, close #8263
This commit is contained in:
parent
9f29015a71
commit
4738c96318
|
@ -2453,123 +2453,38 @@ void Notepad_plus::setUniModeText()
|
|||
}
|
||||
|
||||
|
||||
void Notepad_plus::addHotSpot()
|
||||
void Notepad_plus::addHotSpot(ScintillaEditView* view)
|
||||
{
|
||||
ScintillaEditView* pView = view ? view : _pEditView;
|
||||
|
||||
int urlAction = (NppParameters::getInstance()).getNppGUI()._styleURL;
|
||||
LPARAM Style = (urlAction == 2) ? INDIC_PLAIN : INDIC_HIDDEN;
|
||||
pView->execute(SCI_INDICSETSTYLE, URL_INDIC, Style);
|
||||
pView->execute(SCI_INDICSETHOVERSTYLE, URL_INDIC, INDIC_FULLBOX);
|
||||
|
||||
int startPos = 0;
|
||||
int endPos = -1;
|
||||
auto endStyle = _pEditView->execute(SCI_GETENDSTYLED);
|
||||
pView->getVisibleStartAndEndPosition(&startPos, &endPos);
|
||||
if (startPos >= endPos) return;
|
||||
pView->execute(SCI_SETINDICATORCURRENT, URL_INDIC);
|
||||
pView->execute(SCI_INDICATORCLEARRANGE, startPos, endPos - startPos);
|
||||
if (!urlAction) return;
|
||||
|
||||
_pEditView->getVisibleStartAndEndPosition(&startPos, &endPos);
|
||||
|
||||
_pEditView->execute(SCI_SETSEARCHFLAGS, SCFIND_REGEXP|SCFIND_POSIX);
|
||||
|
||||
_pEditView->execute(SCI_SETTARGETRANGE, startPos, endPos);
|
||||
|
||||
std::vector<unsigned char> hotspotPairs; //= _pEditView->GetHotspotPairs();
|
||||
|
||||
unsigned char style_hotspot = 0;
|
||||
unsigned char mask = 0x40; // INDIC1_MASK;
|
||||
// INDIC2_MASK == 255 and it represents MSB bit
|
||||
// only LEX_HTML and LEX_POSTSCRIPT use use INDIC2_MASK bit internally
|
||||
// LEX_HTML is using INDIC2_MASK bit even though it has only 127 states, so it is safe to overwrite 8th bit
|
||||
// INDIC2_MASK will be used for LEX_HTML
|
||||
|
||||
// LEX_POSTSCRIPT is using INDIC2_MASK bit for "tokenization", and is using mask=31 in lexer,
|
||||
// therefore hotspot in LEX_POSTSCRIPT will be saved to 5th bit
|
||||
// there are only 15 states in LEX_POSTSCRIPT, so it is safe to overwrite 5th bit
|
||||
|
||||
// rule of the thumb is, any lexet that calls: styler.StartAt(startPos, 255);
|
||||
// must have special processing here, all other lexers are fine with INDIC1_MASK (7th bit)
|
||||
|
||||
LangType type = _pEditView->getCurrentBuffer()->getLangType();
|
||||
|
||||
if (type == L_HTML || type == L_PHP || type == L_ASP || type == L_JSP)
|
||||
mask = 0x80; // INDIC2_MASK;
|
||||
else if (type == L_PS)
|
||||
mask = 16;
|
||||
|
||||
int posFound = static_cast<int32_t>(_pEditView->execute(SCI_SEARCHINTARGET, strlen(URL_REG_EXPR), reinterpret_cast<LPARAM>(URL_REG_EXPR)));
|
||||
pView->execute(SCI_SETSEARCHFLAGS, SCFIND_REGEXP|SCFIND_POSIX);
|
||||
pView->execute(SCI_SETTARGETRANGE, startPos, endPos);
|
||||
int posFound = static_cast<int32_t>(pView->execute(SCI_SEARCHINTARGET, strlen(URL_REG_EXPR), reinterpret_cast<LPARAM>(URL_REG_EXPR)));
|
||||
|
||||
while (posFound != -1 && posFound != -2)
|
||||
{
|
||||
int start = int(_pEditView->execute(SCI_GETTARGETSTART));
|
||||
int end = int(_pEditView->execute(SCI_GETTARGETEND));
|
||||
int start = int(pView->execute(SCI_GETTARGETSTART));
|
||||
int end = int(pView->execute(SCI_GETTARGETEND));
|
||||
int foundTextLen = end - start;
|
||||
unsigned char idStyle = static_cast<unsigned char>(_pEditView->execute(SCI_GETSTYLEAT, posFound));
|
||||
|
||||
// Search the style
|
||||
int fs = -1;
|
||||
for (size_t i = 0, len = hotspotPairs.size(); i < len ; ++i)
|
||||
{
|
||||
// make sure to ignore "hotspot bit" when comparing document style with archived hotspot style
|
||||
if ((hotspotPairs[i] & ~mask) == (idStyle & ~mask))
|
||||
{
|
||||
fs = hotspotPairs[i];
|
||||
_pEditView->execute(SCI_STYLEGETFORE, fs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we found it then use it to colourize
|
||||
if (fs != -1)
|
||||
{
|
||||
_pEditView->execute(SCI_STARTSTYLING, start, 0xFF);
|
||||
_pEditView->execute(SCI_SETSTYLING, foundTextLen, fs);
|
||||
}
|
||||
else // generalize a new style and add it into a array
|
||||
{
|
||||
style_hotspot = idStyle | mask; // set "hotspot bit"
|
||||
hotspotPairs.push_back(style_hotspot);
|
||||
unsigned char idStyleMSBunset = idStyle & ~mask;
|
||||
char fontNameA[128];
|
||||
|
||||
Style hotspotStyle;
|
||||
|
||||
hotspotStyle._styleID = static_cast<int>(style_hotspot);
|
||||
_pEditView->execute(SCI_STYLEGETFONT, idStyleMSBunset, reinterpret_cast<LPARAM>(fontNameA));
|
||||
const size_t generic_fontnameLen = 128;
|
||||
TCHAR *generic_fontname = new TCHAR[generic_fontnameLen];
|
||||
|
||||
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance();
|
||||
const wchar_t * fontNameW = wmc.char2wchar(fontNameA, _nativeLangSpeaker.getLangEncoding());
|
||||
wcscpy_s(generic_fontname, generic_fontnameLen, fontNameW);
|
||||
hotspotStyle._fontName = generic_fontname;
|
||||
|
||||
hotspotStyle._fgColor = static_cast<COLORREF>(_pEditView->execute(SCI_STYLEGETFORE, idStyleMSBunset));
|
||||
hotspotStyle._bgColor = static_cast<COLORREF>(_pEditView->execute(SCI_STYLEGETBACK, idStyleMSBunset));
|
||||
hotspotStyle._fontSize = static_cast<int32_t>(_pEditView->execute(SCI_STYLEGETSIZE, idStyleMSBunset));
|
||||
|
||||
auto isBold = _pEditView->execute(SCI_STYLEGETBOLD, idStyleMSBunset);
|
||||
auto isItalic = _pEditView->execute(SCI_STYLEGETITALIC, idStyleMSBunset);
|
||||
auto isUnderline = _pEditView->execute(SCI_STYLEGETUNDERLINE, idStyleMSBunset);
|
||||
hotspotStyle._fontStyle = (isBold?FONTSTYLE_BOLD:0) | (isItalic?FONTSTYLE_ITALIC:0) | (isUnderline?FONTSTYLE_UNDERLINE:0);
|
||||
|
||||
int urlAction = (NppParameters::getInstance()).getNppGUI()._styleURL;
|
||||
if (urlAction == 2)
|
||||
hotspotStyle._fontStyle |= FONTSTYLE_UNDERLINE;
|
||||
|
||||
_pEditView->setHotspotStyle(hotspotStyle);
|
||||
|
||||
_pEditView->execute(SCI_STYLESETHOTSPOT, style_hotspot, TRUE);
|
||||
int activeFG = 0xFF0000;
|
||||
Style *urlHovered = getStyleFromName(TEXT("URL hovered"));
|
||||
if (urlHovered)
|
||||
activeFG = urlHovered->_fgColor;
|
||||
_pEditView->execute(SCI_SETHOTSPOTACTIVEFORE, TRUE, activeFG);
|
||||
_pEditView->execute(SCI_SETHOTSPOTSINGLELINE, style_hotspot, 0);
|
||||
|
||||
// colourize it!
|
||||
_pEditView->execute(SCI_STARTSTYLING, start, 0xFF);
|
||||
_pEditView->execute(SCI_SETSTYLING, foundTextLen, style_hotspot);
|
||||
}
|
||||
|
||||
_pEditView->execute(SCI_SETTARGETRANGE, posFound + foundTextLen, endPos);
|
||||
|
||||
posFound = static_cast<int32_t>(_pEditView->execute(SCI_SEARCHINTARGET, strlen(URL_REG_EXPR), reinterpret_cast<LPARAM>(URL_REG_EXPR)));
|
||||
pView->execute(SCI_SETINDICATORCURRENT, URL_INDIC);
|
||||
pView->execute(SCI_SETINDICATORVALUE, 0);
|
||||
pView->execute(SCI_INDICATORFILLRANGE, start, foundTextLen);
|
||||
pView->execute(SCI_SETTARGETRANGE, posFound + foundTextLen, endPos);
|
||||
posFound = static_cast<int32_t>(pView->execute(SCI_SEARCHINTARGET, strlen(URL_REG_EXPR), reinterpret_cast<LPARAM>(URL_REG_EXPR)));
|
||||
}
|
||||
|
||||
_pEditView->execute(SCI_STARTSTYLING, endStyle, 0xFF);
|
||||
_pEditView->execute(SCI_SETSTYLING, 0, 0);
|
||||
}
|
||||
|
||||
bool Notepad_plus::isConditionExprLine(int lineNumber)
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#define TOOLBAR 0x02
|
||||
|
||||
#define URL_REG_EXPR "[A-Za-z]+://[A-Za-z0-9_\\-\\+~.:?&@=/%#,;\\{\\}\\(\\)\\[\\]\\|\\*\\!\\\\]+"
|
||||
#define URL_INDIC 8
|
||||
|
||||
enum FileTransferMode {
|
||||
TransferClone = 0x01,
|
||||
|
@ -496,7 +497,7 @@ private:
|
|||
int findMachedBracePos(size_t startPos, size_t endPos, char targetSymbol, char matchedSymbol);
|
||||
void maintainIndentation(TCHAR ch);
|
||||
|
||||
void addHotSpot();
|
||||
void addHotSpot(ScintillaEditView* view = NULL);
|
||||
|
||||
void bookmarkAdd(int lineno) const
|
||||
{
|
||||
|
|
|
@ -2448,6 +2448,12 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
case NPPM_INTERNAL_UPDATECLICKABLELINKS:
|
||||
{
|
||||
addHotSpot(_pEditView);
|
||||
addHotSpot(_pNonEditView);
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if (message == WDN_NOTIFY)
|
||||
|
|
|
@ -611,9 +611,7 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
|||
|
||||
if (!_isFolding)
|
||||
{
|
||||
int urlAction = (NppParameters::getInstance()).getNppGUI()._styleURL;
|
||||
if ((urlAction == 1) || (urlAction == 2))
|
||||
addHotSpot();
|
||||
addHotSpot();
|
||||
}
|
||||
|
||||
if (_pDocMap)
|
||||
|
@ -789,7 +787,22 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Double click with no modifiers
|
||||
// Check wether cursor is within URL
|
||||
auto indicMsk = notifyView->execute(SCI_INDICATORALLONFOR, notification->position);
|
||||
if (!(indicMsk & (1 << URL_INDIC))) break;
|
||||
|
||||
// Revert selection of current word. Best to this early, otherwise the
|
||||
// selected word is visible all the time while the browser is starting
|
||||
notifyView->execute(SCI_SETSEL, notification->position, notification->position);
|
||||
|
||||
// Open URL
|
||||
auto startPos = notifyView->execute(SCI_INDICATORSTART, URL_INDIC, notification->position);
|
||||
auto endPos = notifyView->execute(SCI_INDICATOREND, URL_INDIC, notification->position);
|
||||
generic_string url = notifyView->getGenericTextAsString(static_cast<size_t>(startPos), static_cast<size_t>(endPos));
|
||||
::ShellExecute(_pPublicInterface->getHSelf(), TEXT("open"), url.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -804,9 +817,7 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
|||
// replacement for obsolete custom SCN_SCROLLED
|
||||
if (notification->updated & SC_UPDATE_V_SCROLL)
|
||||
{
|
||||
int urlAction = (NppParameters::getInstance()).getNppGUI()._styleURL;
|
||||
if ((urlAction == 1) || (urlAction == 2))
|
||||
addHotSpot();
|
||||
addHotSpot();
|
||||
}
|
||||
|
||||
// if it's searching/replacing, then do nothing
|
||||
|
@ -973,9 +984,7 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
|||
// if it's searching/replacing, then do nothing
|
||||
if ((_linkTriggered && !nppParam._isFindReplacing) || notification->wParam == LINKTRIGGERED)
|
||||
{
|
||||
int urlAction = (NppParameters::getInstance()).getNppGUI()._styleURL;
|
||||
if ((urlAction == 1) || (urlAction == 2))
|
||||
addHotSpot();
|
||||
addHotSpot();
|
||||
_linkTriggered = false;
|
||||
}
|
||||
|
||||
|
@ -987,42 +996,6 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
|||
break;
|
||||
}
|
||||
|
||||
case SCN_HOTSPOTDOUBLECLICK:
|
||||
{
|
||||
if (not notifyView)
|
||||
return FALSE;
|
||||
|
||||
// Get the style and make sure it is a hotspot
|
||||
uint8_t style = static_cast<uint8_t>(notifyView->execute(SCI_GETSTYLEAT, notification->position));
|
||||
if (not notifyView->execute(SCI_STYLEGETHOTSPOT, style))
|
||||
break;
|
||||
|
||||
long long startPos, endPos, docLen;
|
||||
startPos = endPos = notification->position;
|
||||
docLen = notifyView->getCurrentDocLen();
|
||||
|
||||
// Walk backwards/forwards to get the contiguous text in the same style
|
||||
while (startPos > 0 && static_cast<uint8_t>(notifyView->execute(SCI_GETSTYLEAT, static_cast<WPARAM>(startPos - 1))) == style)
|
||||
startPos--;
|
||||
while (endPos < docLen && static_cast<uint8_t>(notifyView->execute(SCI_GETSTYLEAT, static_cast<WPARAM>(endPos))) == style)
|
||||
endPos++;
|
||||
|
||||
// Select the entire link
|
||||
notifyView->execute(SCI_SETANCHOR, static_cast<WPARAM>(startPos));
|
||||
notifyView->execute(SCI_SETCURRENTPOS, static_cast<WPARAM>(endPos));
|
||||
|
||||
generic_string url = notifyView->getGenericTextAsString(static_cast<size_t>(startPos), static_cast<size_t>(endPos));
|
||||
|
||||
// remove the flickering: it seems a mouse left button up is missing after SCN_HOTSPOTDOUBLECLICK
|
||||
::PostMessage(notifyView->getHSelf(), WM_LBUTTONUP, 0, 0);
|
||||
auto curPos = notifyView->execute(SCI_GETCURRENTPOS);
|
||||
notifyView->execute(SCI_SETSEL, curPos, curPos);
|
||||
|
||||
::ShellExecute(_pPublicInterface->getHSelf(), TEXT("open"), url.c_str(), NULL, NULL, SW_SHOW);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCN_NEEDSHOWN:
|
||||
{
|
||||
break;
|
||||
|
|
|
@ -1004,6 +1004,8 @@ INT_PTR CALLBACK SettingsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM)
|
|||
::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_CLICKABLELINK_NOUNDERLINE), isChecked);
|
||||
|
||||
nppGUI._styleURL = isChecked?2:0;
|
||||
HWND grandParent = ::GetParent(_hParent);
|
||||
::SendMessage(grandParent, NPPM_INTERNAL_UPDATECLICKABLELINKS, 0, 0);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
|
@ -1011,6 +1013,8 @@ INT_PTR CALLBACK SettingsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM)
|
|||
{
|
||||
bool isChecked = isCheckedOrNot(IDC_CHECK_CLICKABLELINK_NOUNDERLINE);
|
||||
nppGUI._styleURL = isChecked?1:2;
|
||||
HWND grandParent = ::GetParent(_hParent);
|
||||
::SendMessage(grandParent, NPPM_INTERNAL_UPDATECLICKABLELINKS, 0, 0);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
|
|
|
@ -443,8 +443,8 @@
|
|||
#define NPPM_INTERNAL_STOPMONITORING (NOTEPADPLUS_USER_INTERNAL + 49) // Used by Monitoring feature
|
||||
#define NPPM_INTERNAL_EDGEBACKGROUND (NOTEPADPLUS_USER_INTERNAL + 50)
|
||||
#define NPPM_INTERNAL_EDGEMULTISETSIZE (NOTEPADPLUS_USER_INTERNAL + 51)
|
||||
//wParam: 0
|
||||
//lParam: document new index
|
||||
#define NPPM_INTERNAL_UPDATECLICKABLELINKS (NOTEPADPLUS_USER_INTERNAL + 52)
|
||||
|
||||
// See Notepad_plus_msgs.h
|
||||
//#define NOTEPADPLUS_USER (WM_USER + 1000)
|
||||
|
||||
|
|
Loading…
Reference in New Issue