diff --git a/src/Helpers.h b/src/Helpers.h index 991944b1a..527570351 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -642,6 +642,40 @@ inline WCHAR* StrEndW(const WCHAR* pStart, size_t siz) #define StrEnd(s,n) StrEndA((s),(n)) #endif +// ---------------------------------------------------------------------------- + +#if 0 + +inline void StrReplChrA(CHAR* pStrg, const CHAR chSearch, const CHAR chReplace) +{ + while (pStrg && *pStrg) { + if (*pStrg == chSearch) { + *pStrg = chReplace; + } + ++pStrg; + } +} + +inline void StrReplChrW(WCHAR* pStrg, const WCHAR chSearch, const WCHAR chReplace) +{ + while (pStrg && *pStrg) { + if (*pStrg == chSearch) { + *pStrg = chReplace; + } + ++pStrg; + } +} + +#if defined(UNICODE) || defined(_UNICODE) +#define StrReplChr(str, cs, cr) StrReplChrW((str), (cs), (cr)) +#else +#define StrReplChr(str, cs, cr) StrReplChrA((str), (cs), (cr)) +#endif + +#endif + +// ---------------------------------------------------------------------------- + //==== StrSafe lstrcmp(),lstrcmpi() ============================================= // NOTE: !!! differences in AutoCompleteList depending compare functions (CRT vs. Shlwapi)) !!! diff --git a/src/Notepad3.c b/src/Notepad3.c index 9efec6e32..4c9990711 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -7064,6 +7064,7 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio bool bHandled = false; if (SciCall_IndicatorValueAt(INDIC_NP3_HYPERLINK, position)) { + 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, INTERNET_MAX_URL_LENGTH); @@ -7072,14 +7073,15 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio return false; } - const char* pszText = (const char*)SciCall_GetRangePointer(firstPos, length); + const char *pszText = (const char *)SciCall_GetRangePointer(firstPos, length); WCHAR szTextW[INTERNET_MAX_URL_LENGTH + 1]; ptrdiff_t const cchTextW = MultiByteToWideChar(Encoding_SciCP, 0, pszText, (int)length, szTextW, COUNTOF(szTextW)); szTextW[cchTextW] = L'\0'; StrTrim(szTextW, L" \r\n\t"); - const WCHAR* chkPreFix = L"file://"; + const WCHAR *chkPreFix = L"file://"; + size_t const lenPfx = StringCchLenW(chkPreFix, 0); if (operation & SELECT_HYPERLINK) { SciCall_SetSelection(firstPos, lastPos); @@ -7096,42 +7098,63 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio bHandled = true; } } - } else if ((operation & OPEN_WITH_NOTEPAD3) && (StrStrI(szTextW, chkPreFix) == szTextW)) { - size_t const lenPfx = StringCchLenW(chkPreFix, 0); - WCHAR* szFileName = &(szTextW[lenPfx]); - szTextW[lenPfx + MAX_PATH] = L'\0'; // limit length - StrTrim(szFileName, L"/"); - PathCanonicalizeEx(szFileName, (DWORD)(COUNTOF(szTextW) - lenPfx)); - if (PathIsDirectory(szFileName)) { - WCHAR tchFile[MAX_PATH] = { L'\0' }; - if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), szFileName)) { - FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile); + } else { + + bool const isFileUrl = (StrStrI(szTextW, chkPreFix) == szTextW); + + WCHAR szUnEscW[INTERNET_MAX_URL_LENGTH + 1]; + DWORD dCchUnEsc = COUNTOF(szUnEscW); + UrlUnescapeEx(szTextW, szUnEscW, &dCchUnEsc); + + if ((operation & OPEN_WITH_NOTEPAD3) && isFileUrl) { + + WCHAR *const szFileName = &(szUnEscW[lenPfx]); + szUnEscW[min_i(MAX_PATH, INTERNET_MAX_URL_LENGTH)] = L'\0'; // limit length + StrTrim(szFileName, L"/"); + + PathCanonicalizeEx(szFileName, (DWORD)(COUNTOF(szUnEscW) - lenPfx)); + if (PathIsDirectory(szFileName)) { + WCHAR tchFile[MAX_PATH] = { L'\0' }; + if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), szFileName)) { + FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile); + } + } else { + FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, szFileName); } - } else { - FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, szFileName); - } - bHandled = true; - } else if (operation & OPEN_WITH_BROWSER) { // open in web browser - WCHAR wchDirectory[MAX_PATH] = { L'\0' }; - if (StrIsNotEmpty(Globals.CurrentFile)) { - StringCchCopy(wchDirectory, COUNTOF(wchDirectory), Globals.CurrentFile); - PathCchRemoveFileSpec(wchDirectory, COUNTOF(wchDirectory)); - } + bHandled = true; - SHELLEXECUTEINFO sei; - ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO)); - sei.cbSize = sizeof(SHELLEXECUTEINFO); - sei.fMask = SEE_MASK_NOZONECHECKS; - sei.hwnd = NULL; - sei.lpVerb = NULL; - sei.lpFile = szTextW; - sei.lpParameters = NULL; - sei.lpDirectory = wchDirectory; - sei.nShow = SW_SHOWNORMAL; - ShellExecuteEx(&sei); + } else if (operation & OPEN_WITH_BROWSER) { // open in web browser - bHandled = true; + if (isFileUrl) { + WCHAR *const szFileName = &(szUnEscW[lenPfx]); + dCchUnEsc = COUNTOF(szTextW); + UrlCreateFromPath(szFileName, szTextW, &dCchUnEsc, 0); + //~StringCchCopy(szUnEscW, COUNTOF(szUnEscW), L"http://"); + //~StringCchCat(szUnEscW, COUNTOF(szUnEscW), &(szTextW[lenPfx])); + StringCchCopy(szUnEscW, COUNTOF(szUnEscW), szTextW); + } + + WCHAR wchDirectory[MAX_PATH] = { L'\0' }; + if (StrIsNotEmpty(Globals.CurrentFile)) { + StringCchCopy(wchDirectory, COUNTOF(wchDirectory), Globals.CurrentFile); + PathCchRemoveFileSpec(wchDirectory, COUNTOF(wchDirectory)); + } + + SHELLEXECUTEINFO sei; + ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO)); + sei.cbSize = sizeof(SHELLEXECUTEINFO); + sei.fMask = SEE_MASK_NOZONECHECKS; + sei.hwnd = NULL; + sei.lpVerb = NULL; + sei.lpFile = szUnEscW; + sei.lpParameters = NULL; + sei.lpDirectory = wchDirectory; + sei.nShow = SW_SHOWNORMAL; + ShellExecuteEx(&sei); + + bHandled = true; + } } }