+ fix: Hyperlink detection for Unicode

+ fix: Insertion handling: keep selection if non empty selection is replaced
This commit is contained in:
Rainer Kottenhoff 2019-08-30 14:32:37 +02:00
parent ac6a4371ac
commit 5ddfbc08ee
9 changed files with 71 additions and 44 deletions

View File

@ -1 +1 @@
2607
2609

View File

@ -12,12 +12,18 @@
* *
* *
*******************************************************************************/
#if !defined(_WIN32_WINNT)
#define _WIN32_WINNT 0x601
#if !defined(WINVER)
#define WINVER 0x601 /*_WIN32_WINNT_WIN7*/
#endif
#define VC_EXTRALEAN 1
//#define WIN32_LEAN_AND_MEAN 1
//#define NOMINMAX 1
#if !defined(_WIN32_WINNT)
#define _WIN32_WINNT 0x601 /*_WIN32_WINNT_WIN7*/
#endif
#if !defined(NTDDI_VERSION)
#define NTDDI_VERSION 0x06010000 /*NTDDI_WIN7*/
#endif
//~#define VC_EXTRALEAN 1
//~#define WIN32_LEAN_AND_MEAN 1
#define NOMINMAX 1
#include <windows.h>
#include <shlobj.h>
#include <shlwapi.h>

View File

@ -3,7 +3,7 @@
<assemblyIdentity
name="Notepad3"
processorArchitecture="*"
version="5.19.829.2607"
version="5.19.830.2609"
type="win32"
/>
<description>Notepad3 BETA</description>

View File

@ -204,12 +204,13 @@ static void CALLBACK MQ_ExecuteNext(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWOR
//
// EditReplaceSelection()
//
void EditReplaceSelection(const char* text, bool bReselect)
void EditReplaceSelection(const char* text, bool bForceSel)
{
_BEGIN_UNDO_ACTION_
bool const bSelWasEmpty = SciCall_IsSelectionEmpty();
DocPos const posSelBeg = SciCall_GetSelectionStart();
SciCall_ReplaceSel(text);
if (bReselect) {
if (bForceSel || !bSelWasEmpty) {
SciCall_SetSel(posSelBeg, SciCall_GetCurrentPos());
}
_END_UNDO_ACTION_
@ -1754,30 +1755,26 @@ void EditURLEncode(HWND hwnd)
const char* pszText = (const char*)SciCall_GetRangePointer(min_p(iCurPos, iAnchorPos), iSelSize);
LPWSTR pszTextW = AllocMem(iSelSize * sizeof(WCHAR), HEAP_ZERO_MEMORY);
if (pszTextW == NULL) {
return;
}
/*int cchTextW =*/ MultiByteToWideChar(Encoding_SciCP, 0, pszText, (MBWC_DocPos_Cast)(iSelSize-1),
pszTextW, (MBWC_DocPos_Cast)iSelSize);
WCHAR szTextW[INTERNET_MAX_URL_LENGTH+1];
int const cchTextW = MultiByteToWideChar(Encoding_SciCP, 0, pszText, (MBWC_DocPos_Cast)(iSelSize-1), szTextW, INTERNET_MAX_URL_LENGTH);
szTextW[cchTextW] = L'\0';
size_t const cchEscaped = iSelSize * 3;
char* pszEscaped = (char*)AllocMem(cchEscaped, HEAP_ZERO_MEMORY);
if (pszEscaped == NULL) {
FreeMem(pszTextW);
return;
}
LPWSTR pszEscapedW = (LPWSTR)AllocMem(cchEscaped * sizeof(WCHAR), HEAP_ZERO_MEMORY);
if (pszEscapedW == NULL) {
FreeMem(pszTextW);
FreeMem(pszEscaped);
return;
}
DWORD cchEscapedW = (DWORD)cchEscaped;
UrlEscape(pszTextW, pszEscapedW, &cchEscapedW, URL_ESCAPE_SEGMENT_ONLY | URL_ESCAPE_PERCENT | URL_ESCAPE_AS_UTF8);
DWORD const flags = (DWORD)(URL_ESCAPE_SEGMENT_ONLY | URL_ESCAPE_PERCENT | URL_ESCAPE_AS_UTF8);
UrlEscape(szTextW, pszEscapedW, &cchEscapedW, flags);
DWORD const cchEscapedEnc = WideCharToMultiByte(Encoding_SciCP, 0, pszEscapedW, cchEscapedW,
pszEscaped, (MBWC_DocPos_Cast)cchEscaped, NULL, NULL);
@ -1807,7 +1804,6 @@ void EditURLEncode(HWND hwnd)
_END_UNDO_ACTION_;
FreeMem(pszTextW);
FreeMem(pszEscaped);
FreeMem(pszEscapedW);
}
@ -2215,7 +2211,7 @@ void EditModifyNumber(HWND hwnd,bool bIncrease) {
StringCchPrintfA(chFormat, COUNTOF(chFormat), "%%#0%ix", iWidth);
StringCchPrintfA(chNumber, COUNTOF(chNumber), chFormat, iNumber);
EditReplaceSelection(chNumber,false);
EditReplaceSelection(chNumber, false);
}
}
}
@ -7151,9 +7147,13 @@ void EditUpdateIndicators(HWND hwnd, DocPos startPos, DocPos endPos, bool bClear
if (Settings.HyperlinkHotspot)
{
static const char* pUrlRegEx = "\\b(?:(?:https?|ftp|file)://|www\\.|ftp\\.)"
"(?:\\([-A-Z0-9+&@#/%=~_|$?!:,.]*\\)|[-A-Z0-9+&@#/%=~_|$?!:,.])*"
"(?:\\([-A-Z0-9+&@#/%=~_|$?!:,.]*\\)|[A-Z0-9+&@#/%=~_|$])";
//static const char* pUrlRegEx = "\\b(?:(?:https?|ftp|file)://|www\\.|ftp\\.)"
// "(?:\\([-a-z\\u00a1-\\uffff0-9+&@#/%=~_|$?!:,.]*\\)|[-a-z\\u00a1-\\uffff0-9+&@#/%=~_|$?!:,.])*"
// "(?:\\([-a-z\\u00a1-\\uffff0-9+&@#/%=~_|$?!:,.]*\\)|[a-z\\u00a1-\\uffff0-9+&@#/%=~_|$])";
// https://mathiasbynens.be/demo/url-regex : @stephenhay
static const char* pUrlRegEx = "\\b(?:(?:https?|ftp|file)://|www\\.|ftp\\.)[^\\s/$.?#].[^\\s]*";
_UpdateIndicators(hwnd, INDIC_NP3_HYPERLINK, INDIC_NP3_HYPERLINK_U, pUrlRegEx, startPos, endPos);
}

View File

@ -21,7 +21,7 @@
#include "TypeDefs.h"
void EditInitializeSciCtrl(HWND);
void EditReplaceSelection(const char* text, bool bReselect);
void EditReplaceSelection(const char* text, bool bForceSel);
void EditInitWordDelimiter(HWND hwnd);
void EditSetNewText(HWND hwnd,const char* lpstrText,DocPos lenText,bool);
bool EditConvertText(HWND hwnd, cpi_enc_t encSource, cpi_enc_t encDest,bool);

View File

@ -4344,7 +4344,7 @@ LRESULT MsgCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
cpi_enc_t const iEncoding = Encoding_Current(CPI_GET);
char chEncStrg[128] = { '\0' };
WideCharToMultiByte(Encoding_SciCP, 0, Encoding_GetLabel(iEncoding), -1, chEncStrg, COUNTOF(chEncStrg), NULL, NULL);
EditReplaceSelection(chEncStrg, true);
EditReplaceSelection(chEncStrg, false);
}
break;
@ -4428,7 +4428,7 @@ LRESULT MsgCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
StrTrimW(tchMaxPathBuffer, L"{}");
char chMaxPathBuffer[MAX_PATH] = { '\0' };
if (WideCharToMultiByte(Encoding_SciCP, 0, tchMaxPathBuffer, -1, chMaxPathBuffer, COUNTOF(chMaxPathBuffer), NULL, NULL)) {
EditReplaceSelection(chMaxPathBuffer, true);
EditReplaceSelection(chMaxPathBuffer, false);
}
}
}
@ -6498,36 +6498,46 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio
if (SciCall_IndicatorValueAt(INDIC_NP3_HYPERLINK, position) == 0) { return false; }
char chURL[HUGE_BUFFER] = { '\0' };
bool bHandled = false;
DocPos const firstPos = SciCall_IndicatorStart(INDIC_NP3_HYPERLINK, position);
DocPos const lastPos = SciCall_IndicatorEnd(INDIC_NP3_HYPERLINK, position);
DocPos const length = min_p(lastPos - firstPos, COUNTOF(chURL));
DocPos const length = min_p(lastPos - firstPos, INTERNET_MAX_URL_LENGTH);
StringCchCopyNA(chURL, COUNTOF(chURL), SciCall_GetRangePointer(firstPos, length), length);
StrTrimA(chURL, " \t\n\r");
const char* pszText = (const char*)SciCall_GetRangePointer(firstPos, length);
if (StrIsEmptyA(chURL)) { return bHandled; }
WCHAR szTextW[INTERNET_MAX_URL_LENGTH+1];
int const cchTextW = MultiByteToWideChar(Encoding_SciCP, 0, pszText, (MBWC_DocPos_Cast)length, szTextW, COUNTOF(szTextW));
szTextW[cchTextW] = L'\0';
WCHAR wchURL[XHUGE_BUFFER] = { L'\0' };
int const lenHypLnk = MultiByteToWideChar(Encoding_SciCP, 0, chURL, -1, wchURL, COUNTOF(wchURL)) - 1;
const WCHAR* chkPreFix = L"file://";
if (operation & COPY_HYPERLINK)
{
if (lenHypLnk > 0) {
SetClipboardTextW(Globals.hwndMain, wchURL, lenHypLnk);
if (cchTextW > 0) {
LPWSTR pszEscapedW = (LPWSTR)AllocMem(length * 3 * sizeof(WCHAR), HEAP_ZERO_MEMORY);
if (pszEscapedW == NULL) {
return false;
}
DWORD cchEscapedW = (DWORD)(length * 3);
DWORD const flags = (DWORD)(URL_BROWSER_MODE | URL_ESCAPE_AS_UTF8);
UrlEscape(szTextW, pszEscapedW, &cchEscapedW, flags);
//SetClipboardTextW(Globals.hwndMain, szTextW, cchTextW);
SetClipboardTextW(Globals.hwndMain, pszEscapedW, cchEscapedW);
FreeMem(pszEscapedW);
bHandled = true;
}
}
else if ((operation & OPEN_WITH_NOTEPAD3) && (StrStrIA(chURL, "file://") == chURL))
else if ((operation & OPEN_WITH_NOTEPAD3) && (StrStrI(szTextW, chkPreFix) == szTextW))
{
const WCHAR* chkPreFix = L"file://";
size_t const lenPfx = StringCchLenW(chkPreFix, 0);
WCHAR* szFileName = &(wchURL[lenPfx]);
WCHAR* szFileName = &(szTextW[lenPfx]);
szTextW[lenPfx + MAX_PATH] = L'\0'; // limit length
StrTrimW(szFileName, L"/");
PathCanonicalizeEx(szFileName, (DWORD)(COUNTOF(wchURL) - lenPfx));
PathCanonicalizeEx(szFileName, (DWORD)(COUNTOF(szTextW) - lenPfx));
if (PathIsDirectory(szFileName))
{
WCHAR tchFile[MAX_PATH] = { L'\0' };
@ -6555,7 +6565,7 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio
sei.fMask = SEE_MASK_NOZONECHECKS;
sei.hwnd = NULL;
sei.lpVerb = NULL;
sei.lpFile = wchURL;
sei.lpFile = szTextW;
sei.lpParameters = NULL;
sei.lpDirectory = wchDirectory;
sei.nShow = SW_SHOWNORMAL;

View File

@ -601,6 +601,12 @@ typedef struct _docviewpos_t
#define NOTEPAD3_MODULE_DIR_ENV_VAR L"NOTEPAD3MODULEDIR"
// from <wininet.h>
#define INTERNET_MAX_PATH_LENGTH 2048
#define INTERNET_MAX_SCHEME_LENGTH 32 // longest protocol name length
#define INTERNET_MAX_URL_LENGTH (INTERNET_MAX_SCHEME_LENGTH \
+ sizeof("://") \
+ INTERNET_MAX_PATH_LENGTH)
//=============================================================================

View File

@ -7,8 +7,8 @@
#define SAPPNAME "Notepad3"
#define VERSION_MAJOR 5
#define VERSION_MINOR 19
#define VERSION_REV 829
#define VERSION_BUILD 2607
#define VERSION_REV 830
#define VERSION_BUILD 2609
#define SCINTILLA_VER 420
#define ONIGURUMA_REGEX_VER 6.9.3
#define UCHARDET_VER 2018.09.27

View File

@ -2,6 +2,11 @@
# https://github.com/toml-lang/toml
#
# https://fr.wikipedia.org/wiki/Caractères_de_civilité
# https://fr.wikipedia.org/wiki/Caract%C3%A8res_de_civilit%C3%A9
#
title = "TOML Example"
[owner]