mirror of
https://github.com/rizonesoft/Notepad3.git
synced 2026-06-14 21:09:05 +08:00
Merge pull request #5884 from RaiKoHoff/dev_master
feat: Open Containing Folder (sel) and Open File from Selection
This commit is contained in:
commit
f443e8807d
@ -751,6 +751,8 @@
|
||||
#define IDM_EDIT_COPY_MARKED 40392
|
||||
#define IDM_EDIT_DELETE_MARKED 40393
|
||||
#define IDM_EDIT_COPYRTF 40394
|
||||
#define IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL 40395
|
||||
#define IDM_EDIT_OPEN_FILE_FROM_SEL 40396
|
||||
|
||||
#define IDM_VIEW_SCHEME 41001
|
||||
#define IDM_VIEW_USE2NDDEFAULT 41002
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Kies &Woord of Lyne\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Multi-Select &Alles wat Pas\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Verdeel en Onttrek &Transaksies by Lynbrekings", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Web Sjabloon 1", CMD_WEBACTION1
|
||||
MENUITEM "Web Sjabloon 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Maak File Explorer Oop", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Вылучыць с&лова альбо радок\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "&Мультывылучэнне ўсіх уваходжанняў\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Падзяліць &транзакцыю адмены па канчаткам радкоў", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Адкрыць вэб-дзеянне 1", CMD_WEBACTION1
|
||||
MENUITEM "Адкрыць вэб-дзеянне 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Адкрыць Праваднік", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Selektiere &Wort oder Zeile\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Multiselektion &aller Fundstellen\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Neue Undo &Transaktion bei Zeilenumbruch", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Öffne Web-Aktion 1", CMD_WEBACTION1
|
||||
MENUITEM "Öffne Web Aktion 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Öffne Datei-Explorer", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Επιλογή &λέξης ή γραμμών\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Π&ολλαπλή επιλογή όλων των συμφωνιών\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Νέα λειτουργία αναίρεσης σε κάθε αλλαγή γραμμής", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Άνοιγμα ενέργειας Web 1", CMD_WEBACTION1
|
||||
MENUITEM "Άνοιγμα ενέργειας Web 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Άνοιγμα Εξερεύνησης αρχείων", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Select &Word or Lines\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Multi-Select &All Matches\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Split Undo &Transaction at Line-Breaks", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Web Action 1", CMD_WEBACTION1
|
||||
MENUITEM "Open Web Action 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Open File Explorer", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Select &Word or Lines\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Multi-Select &All Matches\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Split Undo &Transaction at Line-Breaks", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Web Action 1", CMD_WEBACTION1
|
||||
MENUITEM "Open Web Action 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Open File Explorer", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Seleccionar &palabra o líneas\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Multi-selección &todas coincidencias\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Dividir &transacción de deshacer en saltos de línea", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Abrir Web Acción 1", CMD_WEBACTION1
|
||||
MENUITEM "Abrir Web Acción 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Abrir Explorador de archivos", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Valitse &sana tai rivi\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Monivalitse k&aikki täsmäävät\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Jaa kumous&tapahtuma rivinvaihdon kohdalla", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Avaa verkkotoiminto 1", CMD_WEBACTION1
|
||||
MENUITEM "Avaa verkkotoiminto 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Avaa tiedostonhallinta", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Sélectionner le mot ou la ligne\tCtrl+Espac.", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Multi-sélectionner toutes les correspond&ances\tCtrl+Maj+Espac.", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Fractionner l'opération ""Défaire"" aux sauts de ligne", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Ouvrir Action Web &1", CMD_WEBACTION1
|
||||
MENUITEM "Ouvrir Action Web &2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Ouvrir l'Explorateur de fichiers", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "शब्द या रेखा चयनित करें (&W)\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "सारे मिलान बहु-चयनित करें (&A)\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "पंक्ति-विराम पर पूर्ववत लेनदेन विभाजित करें", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "वेब प्रक्रिया 1 खोलें", CMD_WEBACTION1
|
||||
MENUITEM "वेब प्रक्रिया 2 खोलें", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "फ़ाइल एक्स्प्लोरर खोलें", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Szó vag&y sorok kijelölése\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Összes egyezés ki&jelölése\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Visszavonás műveletek szétvágása sortöréseknél", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Webes művelet 1", CMD_WEBACTION1
|
||||
MENUITEM "Webes művelet 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Fájlböngésző megnyitása", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Pilih Kata a&tau Baris\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Pilih Semua yang &Sesuai\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Pisahkan &Riwayat Kembali pada Baris Baru", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Buka Aksi Web 1", CMD_WEBACTION1
|
||||
MENUITEM "Buka Aksi Web 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Buka File Explorer", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Seleziona &parola o linea\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Multi selezione di &tutte le occorrenze\tCtrl+Maiusc+Spazio", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Separa &transazione annulla azione per ogni linea", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Apri azione web 1", CMD_WEBACTION1
|
||||
MENUITEM "Apri azione web 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Apri Esplora File", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "単語や行を選択(&W)\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "一致文字列すべてに複数カーソル(&A)\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "「元に戻す」の履歴を改行で区切る(&T)", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "ウェブ1で開く", CMD_WEBACTION1
|
||||
MENUITEM "ウェブ2で開く", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "エクスプローラーを開く", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "단어 또는 줄 선택(&W)\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "모든 일치 다중 선택(&A)\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "줄 바꿈에서 분할 실행 취소 처리(&T)", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "웹 작업 1 열기", CMD_WEBACTION1
|
||||
MENUITEM "웹 작업 2 열기", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "파일 탐색기 열기", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "&Woord of regel(s) selecteren\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "&Alle overeenkomsten selecteren\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Ongedaan maken bij regeleinde afbreken", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Websjabloon 1 openen", CMD_WEBACTION1
|
||||
MENUITEM "Websjabloon 2 openen", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "MiniPath verkenner openen", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Zaznacz wyraz lub wiersz\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Multiwybór-wszystko pasujące\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Podział operacji cofania przy przenoszeniu wierszy", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Otwórz Web Action 1", CMD_WEBACTION1
|
||||
MENUITEM "Otwórz Web Action 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Otwórz Eksplorator plików", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Selecionar &Palavras ou Linhas\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Multi-Seleção de &Todos os Casados\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Dividir &Transações Desfeitas nas Quebras de Linha", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Abrir Ação Web 1", CMD_WEBACTION1
|
||||
MENUITEM "Abrir Ação Web 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Abri Gerenciador de Arquivos", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Seleccionar &palavra ou linhas\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Multi-Seleccionar tod&as as correspondências\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Dividir &transacção anular nas quebras de linha", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Abrir acção Web 1", CMD_WEBACTION1
|
||||
MENUITEM "Abrir acção Web 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Abrir Explorador de ficheiros", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Выбрать с&лово или строку\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "&Мультивыбор всех совпадений\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Разделить &транзакцию отмены по окончаниям строк", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Открыть веб-действие 1", CMD_WEBACTION1
|
||||
MENUITEM "Открыть веб-действие 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Открыть Проводник", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Vybrať &slovo alebo riadok\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "&Viacnásobný výber všetkých zhôd\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Rozdeliť a&kciu Späť po zalomení riadku", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Webová šablóna 1", CMD_WEBACTION1
|
||||
MENUITEM "Webová šablóna 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Otvoriť Prieskumníka", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Markera ord eller rader\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Markera alla matchningar\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Dela ångra vid radslut", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Öppna webbåtgärd 1", CMD_WEBACTION1
|
||||
MENUITEM "Öppna webbåtgärd 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Öppna Utforskaren", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Sözcük &ya da satır seç\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "&Tüm eşleşmeleri seç\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Satır sonlarında &geri alma işlemini ayır", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "1. web işlemini aç", CMD_WEBACTION1
|
||||
MENUITEM "2. web işlemini aç", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Dosya gezginini aç", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "Chọn từ hoặc dòng(&W)\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "Chọn tất cả khớp(&A)\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Xử lý Undo khi phân chia tại dòng(&T)", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Mở tác vụ web 1", CMD_WEBACTION1
|
||||
MENUITEM "Mở tác vụ web 2", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "Mở Explorer", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "选定单词或行(&W)\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "选定全部匹配(&A)\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "换行时重定撤销操作边界(&T)", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "用超链接模板 1 打开", CMD_WEBACTION1
|
||||
MENUITEM "用超链接模板 2 打开", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "打开资源管理器", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
@ -317,6 +317,9 @@ BEGIN
|
||||
MENUITEM "選定單詞或行(&W)\tCtrl+Spc", IDM_EDIT_SELECTWORD
|
||||
MENUITEM "選定全部符合(&A)\tCtrl+Shift+Spc", IDM_EDIT_SELECTALLMATCHES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open &File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "換行時重定復原操作邊界(&T)", IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
@ -596,6 +599,9 @@ BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "用超連結模板 1 打開", CMD_WEBACTION1
|
||||
MENUITEM "用超連結模板 2 打開", CMD_WEBACTION2
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open Containing Folder of Selection", IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL
|
||||
MENUITEM "Open File from Selection", IDM_EDIT_OPEN_FILE_FROM_SEL
|
||||
MENUITEM "打開檔案總管", IDM_FILE_EXPLORE_DIR
|
||||
END
|
||||
POPUP "+"
|
||||
|
||||
226
plans/explore_file_refs.md
Normal file
226
plans/explore_file_refs.md
Normal file
@ -0,0 +1,226 @@
|
||||
# Plan — Follow-up enhancements: file/path reference handling
|
||||
|
||||
Companion to the now-shipped change that added `IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL` / `IDM_EDIT_OPEN_FILE_FROM_SEL` and fixed the `Paths.ModuleDirectory` anchor bug in the hyperlink-click handler.
|
||||
|
||||
These items were intentionally deferred from that change to keep the scope tight. They are independent of each other; pick any subset.
|
||||
|
||||
## Status (2026-05-16)
|
||||
|
||||
Already shipped on `dev_master`:
|
||||
- New selection-based commands `IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL` (40395) and `IDM_EDIT_OPEN_FILE_FROM_SEL` (40396), wired to Edit > Miscellaneous and the editor right-click popup. No accelerator — users can bind one via custom keybindings if desired.
|
||||
- Shared helpers in `src\Helpers.c`: `ExtractSelectionOrTokenAtCaret`, `SplitFilePathLineColNum`, `ResolveSelectionToPath`.
|
||||
- Bug fix at `src\Notepad3.c:8891` (or thereabouts after later edits) — relative `file:///` URLs now anchor to the current document's directory, fallback `Paths.WorkingDirectory`, never `Paths.ModuleDirectory`.
|
||||
- English placeholder strings replicated across all 25 sibling locale `menu_*.rc` files. Translators still need to translate them.
|
||||
|
||||
Function bodies for the two new commands live in `src\Notepad3.c` (not Edit.c) because `<shlobj.h>` defines `SORT_ASCENDING` / `SORT_DESCENDING` enum values that conflict with Edit.c's `SortOrderMask` enum.
|
||||
|
||||
## Item 1 — Bare-path hotspotting (`HYPLNK_REGEX_FULL` extension)
|
||||
|
||||
**Goal**: make `C:\Users\me\foo.txt`, `\\server\share\file`, `.\rel\path.c`, `../include/foo.h`, and similar bare paths clickable hotspots in the editor, just like `https://...` URLs already are.
|
||||
|
||||
### Why this is deferred and load-bearing
|
||||
|
||||
The existing hyperlink hotspot system (`src\Edit.c:111-116`) uses one big PCRE2 regex that requires an explicit scheme prefix:
|
||||
```c
|
||||
#define HYPLNK_REGEX_FULL "\\b(?:(?:https?|ftp)://|file:///|file://|mailto:|www\\.|ftp\\.)" ...
|
||||
```
|
||||
Adding bare-path matching is high-risk because:
|
||||
1. **False positives** — `C:` could match in non-path text (e.g. a code snippet, a colon-time `12:34:56`).
|
||||
2. **Indicator-marking pass cost** — the URL hotspotter runs on every restyle (`MarkAllOccurrences` flow). A broader regex adds CPU per keystroke in large documents.
|
||||
3. **Lexer interference** — many lexers already style strings/paths in domain-specific ways. Adding `INDIC_NP3_HYPERLINK` on top of an existing lexer style can cause visual conflicts (double-underlining, color clash).
|
||||
4. **`SCN_INDICATORRELEASE` activation** — currently `HandleHotSpotURLClicked` at `src\Notepad3.c:8824` is dispatched on indicator-release. It calls `UrlIsFileUrl(szTextW)` to decide between OPEN_IN_NOTEPAD3 and OPEN_WITH_BROWSER. Bare paths aren't file:// URLs, so the routing logic needs a new branch: "if it looks like a Windows path, treat it as OPEN_IN_NOTEPAD3 directly."
|
||||
|
||||
### Implementation sketch
|
||||
|
||||
Two viable approaches:
|
||||
|
||||
**A. Single bigger regex.** Add an alternation arm for paths. E.g.:
|
||||
```
|
||||
\\b(?:[A-Za-z]:[\\\\/]|\\\\\\\\[^\\s]+\\\\|\\.{1,2}[\\\\/])[^\\s'`"<>|*,;]+
|
||||
```
|
||||
- Drive-letter: `C:\...`, `c:/...`
|
||||
- UNC: `\\server\share\...`
|
||||
- Relative: `.\foo`, `..\foo`, `./foo`, `../foo`
|
||||
|
||||
Pros: minimal code change. Cons: regex becomes harder to maintain; false-positive risk is concentrated.
|
||||
|
||||
**B. Second-pass detection.** Keep `HYPLNK_REGEX_FULL` for scheme URLs. Add a separate, more restrictive pass for bare paths only when the line context suggests "this is a path" — e.g. preceded by `at`, `file:`, `> `, in compiler-error format `file.c:42:`, etc. More conservative; harder to author.
|
||||
|
||||
**Recommendation**: try (A) but gate behind a `Settings2.HyperlinkBarePaths` opt-in toggle defaulting to `false`. Document the toggle in `Build\Notepad3.ini` `[Settings2]` and `readme/config/Configuration.md` (CLAUDE.md invariant).
|
||||
|
||||
### Required touchpoints
|
||||
|
||||
| File | Change |
|
||||
|---|---|
|
||||
| `src\Edit.c:111-116` | Extend `HYPLNK_REGEX_FULL` (or add `HYPLNK_REGEX_BAREPATH` and run both) |
|
||||
| `src\Notepad3.c:8824` (`HandleHotSpotURLClicked`) | New branch when `!UrlIsFileUrl(szTextW)` AND text looks like a Windows path → call same OPEN_IN_NOTEPAD3 logic but skip `PathCreateFromUrlW` (use the text as-is, then `ResolveSelectionToPath`-style anchoring) |
|
||||
| `src\TypeDefs.h` (`Settings2`) | Add `HyperlinkBarePaths` bool with default `false` |
|
||||
| `src\Config\Config.cpp` | Persist `HyperlinkBarePaths` |
|
||||
| `Build\Notepad3.ini`, `readme\config\Configuration.md` | Document new INI key |
|
||||
|
||||
### Verification
|
||||
|
||||
- Open a fresh `.txt` buffer with toggle ON. Paste:
|
||||
```
|
||||
C:\Windows\notepad.exe
|
||||
..\src\Helpers.c
|
||||
\\?\C:\Windows
|
||||
src/Edit.c:111
|
||||
See line C: this should NOT highlight
|
||||
Time 12:34:56 must NOT highlight
|
||||
```
|
||||
Expect: lines 1-4 hotspotted, lines 5-6 not.
|
||||
- With toggle OFF: no change vs. current behavior.
|
||||
- Test in C/C++ buffer (SCLEX_CPP) to confirm no lexer-style clash on strings containing paths.
|
||||
|
||||
## Item 2 — Markdown `[label](url)` extraction in `ExtractSelectionOrTokenAtCaret`
|
||||
|
||||
**Goal**: when the caret is inside the URL portion of a Markdown link `[label](url)`, the selection extractor should grab `url` rather than expanding outward through the closing `)` and stopping at the next whitespace.
|
||||
|
||||
### Why this is deferred
|
||||
|
||||
The current `ExtractSelectionOrTokenAtCaret` in `src\Helpers.c` uses a flat boundary set `[\s'`"<>|*,;]` and never considers paired-delimiter context. Notepad4's `EditGetStringAroundCaret` (`notepad4\src\Edit.cpp:7015-7093`) has a dedicated subroutine to recognize `(...)` after a Markdown link target and clamp the extraction.
|
||||
|
||||
It's deferred because: (a) Notepad3 already hotspots Markdown URLs via the lexer-driven indicator path, so most Markdown click flows already work; (b) the extractor is used by the new selection commands, where the user can always select the URL by hand if the auto-expand is wrong.
|
||||
|
||||
### Sketch
|
||||
|
||||
Inside `ExtractSelectionOrTokenAtCaret` in `src\Helpers.c`, when the selection is empty, BEFORE the regular boundary scan:
|
||||
|
||||
```c
|
||||
// Markdown link target: if caret sits inside `(...)` and the char before '(' is ']',
|
||||
// clamp the extraction to the contents of the parens.
|
||||
DocPos const posCur = SciCall_GetCurrentPos();
|
||||
// Walk back to find an unmatched '(' on the same line.
|
||||
// If found AND the char immediately before is ']', use [openParen+1, matching ')') as the span.
|
||||
```
|
||||
|
||||
Use Scintilla's bracket-matching (`SciCall_BraceMatch`) — but only on `(`; Scintilla supports `()` `[]` `{}` `<>`. Caveat: caret-on-`(` semantics vary; you may need to do a manual scan.
|
||||
|
||||
### Touchpoints
|
||||
|
||||
- `src\Helpers.c` — `ExtractSelectionOrTokenAtCaret` (introduced in the prior change).
|
||||
|
||||
### Verification
|
||||
|
||||
```markdown
|
||||
See [the doc](D:\projects\foo\readme.md) for details.
|
||||
^ caret here
|
||||
```
|
||||
Invoke "Open File from Selection" → opens `D:\projects\foo\readme.md`. Currently expands to `D:\projects\foo\readme.md)` and the trailing `)` may or may not be tolerated by `ResolveSelectionToPath`.
|
||||
|
||||
## Item 3 — Enable/disable gating in `MsgInitMenu` for the new commands
|
||||
|
||||
**Goal**: grey out `IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL` / `IDM_EDIT_OPEN_FILE_FROM_SEL` when there's no selection AND no token at the caret position.
|
||||
|
||||
### Current behavior
|
||||
|
||||
The commands are always enabled. Invoking them with an empty selection on whitespace-only content silently produces a `MessageBeep(MB_ICONHAND)`. This matches Notepad4's UX and is acceptable, but a power user might prefer a greyed-out menu.
|
||||
|
||||
### Sketch
|
||||
|
||||
`MsgInitMenu()` in `src\Notepad3.c` should add (near the existing `IDM_EDIT_INSERT_GUID` enable check around line 4963):
|
||||
```c
|
||||
bool const bHasToken = !SciCall_IsSelectionEmpty();
|
||||
// optionally also check word boundaries at SciCall_GetCurrentPos()
|
||||
EnableCmd(hmenu, IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL, bHasToken /* OR token-at-caret */);
|
||||
EnableCmd(hmenu, IDM_EDIT_OPEN_FILE_FROM_SEL, bHasToken);
|
||||
```
|
||||
|
||||
Right-click context menu builder at `src\Notepad3.c:4549` (`imenu == MNU_EDIT` branch) already has a similar pattern for the case-conversion commands using `s_iCtxMenuClickPos`. Add the same predicate there.
|
||||
|
||||
### Verification
|
||||
|
||||
- Empty selection, caret on whitespace → menu items greyed.
|
||||
- Empty selection, caret in a word → enabled.
|
||||
- Any non-empty selection → enabled.
|
||||
|
||||
## Item 4 — `\\?\` long-path prefix handling in `ResolveSelectionToPath`
|
||||
|
||||
**Goal**: gracefully handle paths with the Windows long-path prefix when passed to `SHParseDisplayName`.
|
||||
|
||||
### Why
|
||||
|
||||
`SHParseDisplayName` does not always accept `\\?\C:\...`. For shell-API consumption the prefix should be stripped. PathLib wrappers already handle this internally for filesystem ops, but `EditOpenContainingFolderFromSelection` calls `SHParseDisplayName` directly with `Path_Get(hpth)` which may include the prefix.
|
||||
|
||||
### Sketch
|
||||
|
||||
Inside `EditOpenContainingFolderFromSelection` in `src\Notepad3.c`, before `SHParseDisplayName`:
|
||||
```c
|
||||
LPCWSTR pth = Path_Get(hpth);
|
||||
if (StrCmpNW(pth, L"\\\\?\\", 4) == 0) {
|
||||
// Skip the prefix for shell-API use. If \\?\UNC\..., strip differently.
|
||||
if (StrCmpNW(pth + 4, L"UNC\\", 4) == 0) {
|
||||
// \\?\UNC\server\share → \\server\share
|
||||
WCHAR shellPath[MAX_PATH_EXPLICIT];
|
||||
StringCchPrintf(shellPath, COUNTOF(shellPath), L"\\\\%s", pth + 8);
|
||||
SHParseDisplayName(shellPath, ...);
|
||||
} else {
|
||||
SHParseDisplayName(pth + 4, ...);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Verification
|
||||
|
||||
- `\\?\C:\Windows` → opens `C:\Windows` in Explorer.
|
||||
- `\\?\UNC\server\share\file.txt` → opens `\\server\share\` with `file.txt` selected.
|
||||
|
||||
## Item 5 — `#fragment` parsing for `file://` URLs
|
||||
|
||||
**Goal**: a `file:///D:/docs/readme.md#section-2` URL clicked in Notepad3 should at minimum open the file (currently works) and ideally jump to the line with `#section-2` as a heading anchor.
|
||||
|
||||
### Why deferred
|
||||
|
||||
Markdown anchor resolution is out of scope for a text editor — the heading-anchor mapping is a Markdown-specific convention. The minimum useful behavior is to strip `#...` before resolving the path. Currently `PathCreateFromUrlW` may or may not strip it depending on Windows version.
|
||||
|
||||
### Sketch
|
||||
|
||||
In `HandleHotSpotURLClicked` at `src\Notepad3.c:8824`, after `PathCreateFromUrlW`:
|
||||
```c
|
||||
LPWSTR const hash = StrChr(szUnEscW, L'#');
|
||||
if (hash) {
|
||||
*hash = L'\0'; // discard fragment
|
||||
}
|
||||
```
|
||||
A future Markdown-aware extension could parse `#anchor-name`, scan the buffer for `## Anchor Name` (case-insensitive, dashes→spaces), and `SCI_GOTOLINE` there. Probably not worth the complexity.
|
||||
|
||||
### Verification
|
||||
|
||||
Click `file:///D:/test/foo.md#whatever` — opens `foo.md`. Don't error or attempt to interpret `#whatever`.
|
||||
|
||||
## Item 6 — Localize the new menu strings (translator task, not Claude's)
|
||||
|
||||
The 25 sibling locales currently have **English placeholder** strings for the two new menu items. Translators need to update:
|
||||
|
||||
- `language\np3_*\menu_*.rc` — replace `"Open &Containing Folder of Selection\tCtrl+Shift+,"` and `"Open &File from Selection"` (both in Edit > Miscellaneous AND in `IDR_MUI_POPUPMENU`).
|
||||
|
||||
This is normal translator workflow — not blocked, just pending.
|
||||
|
||||
### What Claude can do
|
||||
|
||||
Nothing without authoritative translations. If asked to "translate", refuse and ask the user to source translations from the locale maintainers listed in `language\np3_*\strings_*.rc` (`IDS_MUI_TRANSL_AUTHOR`).
|
||||
|
||||
## Item 7 — Tinyexpr behavior in `SplitFilePathLineColNum` `:N` fallback
|
||||
|
||||
`SplitFilePathLineColNum` falls back to `SplitFilePathLineNum` (which uses `te_interp`) for the single-colon case `foo.c:42`. This means `foo.c:42+1` would parse as line 43 — a side effect of using tinyexpr. Two existing callers depend on this:
|
||||
|
||||
- `src\Notepad3.c:8666` — `SplitFilePathLineNum(wchUrl, NULL)` — only cuts the suffix, discards the number.
|
||||
- `src\Notepad3.c:8879` — `SplitFilePathLineNum(szTextW, &lineNum)` — uses the parsed number.
|
||||
|
||||
If we ever want to drop the tinyexpr quirk: replace the wrapper with a plain `_wtoi` parse. Verify the two existing callers don't pass arithmetic.
|
||||
|
||||
## Touch-stones for any future session
|
||||
|
||||
- **CLAUDE.md** in repo root has all the build/encoding/localization invariants. Read it before touching `.rc` files.
|
||||
- **`.venv\Scripts\python.exe`** is required for bulk locale edits. Do NOT use sed/perl.
|
||||
- **`.rc` files** are UTF-8 *without* BOM, CRLF. Use `Build\rc_to_utf8.cmd` if a BOM sneaks in.
|
||||
- **Locale es_la** has an empty directory — script-based bulk edits should skip it gracefully.
|
||||
- **Reference impl**: Notepad4 at `D:\DEV\GitHub\notepad4\` — inspect `src\Edit.cpp` (`EditOpenSelection`, `EditGetStringAroundCaret`) and `src\Helpers.cpp` (`OpenContainingFolder`).
|
||||
- **Build**: `Build\Build_x64.cmd Release` for quick verification. The Build.ps1 wrapper has quoting quirks under some PowerShell versions — invoke MSBuild directly if it fails: `& "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" "D:\DEV\GitHub\Notepad3\Notepad3.sln" /m /p:Configuration=Release /p:Platform=x64 /v:minimal`.
|
||||
|
||||
## Out of scope for these follow-ups
|
||||
|
||||
- IDS_MUI_* / Notepad3DLL string resources — none of the deferred items add user-facing strings beyond menu labels (which are inline in `.rc`).
|
||||
- ARM64-specific concerns — none of these touch rendering or CET paths.
|
||||
- grepWin integration — orthogonal.
|
||||
@ -57,6 +57,8 @@ void EditChar2Hex(HWND hwnd);
|
||||
void EditHex2Char(HWND hwnd);
|
||||
void EditFindMatchingBrace();
|
||||
void EditSelectToMatchingBrace();
|
||||
void EditOpenContainingFolderFromSelection(void);
|
||||
void EditOpenFileFromSelection(HWND hwnd);
|
||||
void EditModifyNumber(HWND hwnd, bool bIncrease);
|
||||
void EditInsertDateTimeStrg(bool bShortFmt, bool bTimestampFmt);
|
||||
void EditUpdateTimestamps();
|
||||
|
||||
323
src/Helpers.c
323
src/Helpers.c
@ -1164,6 +1164,329 @@ bool SplitFilePathLineNum(LPWSTR lpszPath, int* lineNum)
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// _IsAllDigitsW() - non-empty wide string consisting solely of ASCII digits
|
||||
//
|
||||
static inline bool _IsAllDigitsW(LPCWSTR s)
|
||||
{
|
||||
if (!s || *s == L'\0') {
|
||||
return false;
|
||||
}
|
||||
for (; *s; ++s) {
|
||||
if (*s < L'0' || *s > L'9') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// _StripCommonQuoting() - in-place strip of whitespace + quote-like chars
|
||||
// that wrap a path/URL token in source/log/doc text.
|
||||
//
|
||||
static inline void _StripCommonQuoting(HSTRINGW hstr)
|
||||
{
|
||||
StrgTrim(hstr, L' ');
|
||||
StrgTrim(hstr, L'\t');
|
||||
StrgTrim(hstr, L'"');
|
||||
StrgTrim(hstr, L'\'');
|
||||
StrgTrim(hstr, L'`');
|
||||
StrgTrim(hstr, L'<');
|
||||
StrgTrim(hstr, L'>');
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// SplitFilePathLineColNum()
|
||||
//
|
||||
// Strips an optional trailing line/column suffix from lpszPath in place.
|
||||
// Patterns recognised (first match wins):
|
||||
// foo.c(42) -> line 42
|
||||
// foo.c,42 -> line 42
|
||||
// foo.c:42:7 -> line 42, column 7
|
||||
// foo.c:<expr> -> falls through to SplitFilePathLineNum (te_interp)
|
||||
//
|
||||
// Drive-letter colons ("C:\...") are never treated as line separators.
|
||||
// Returns true if a suffix was stripped.
|
||||
//
|
||||
bool SplitFilePathLineColNum(LPWSTR lpszPath, int* lineNum, int* colNum)
|
||||
{
|
||||
if (lineNum) {
|
||||
*lineNum = -1;
|
||||
}
|
||||
if (colNum) {
|
||||
*colNum = -1;
|
||||
}
|
||||
if (StrIsEmpty(lpszPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t len = StrlenW(lpszPath);
|
||||
while (len > 0 && (lpszPath[len - 1] == L' ' || lpszPath[len - 1] == L'\t')) {
|
||||
lpszPath[--len] = L'\0';
|
||||
}
|
||||
if (len == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try trailing "(N)"
|
||||
if (lpszPath[len - 1] == L')') {
|
||||
size_t j = len - 1; // points at ')'
|
||||
while (j > 0 && lpszPath[j - 1] >= L'0' && lpszPath[j - 1] <= L'9') {
|
||||
--j;
|
||||
}
|
||||
if (j < (len - 1) && j > 0 && lpszPath[j - 1] == L'(') {
|
||||
int const ln = _wtoi(&lpszPath[j]);
|
||||
if (ln > 0) {
|
||||
lpszPath[j - 1] = L'\0';
|
||||
if (lineNum) {
|
||||
*lineNum = ln;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try trailing ",N"
|
||||
{
|
||||
size_t i = len;
|
||||
while (i > 0 && lpszPath[i - 1] >= L'0' && lpszPath[i - 1] <= L'9') {
|
||||
--i;
|
||||
}
|
||||
if (i < len && i > 0 && lpszPath[i - 1] == L',') {
|
||||
int const ln = _wtoi(&lpszPath[i]);
|
||||
if (ln > 0) {
|
||||
lpszPath[i - 1] = L'\0';
|
||||
if (lineNum) {
|
||||
*lineNum = ln;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try trailing ":N:M" (line + column). Reject drive-letter colon at pos 1.
|
||||
LPWSTR lastColon = StrRChr(lpszPath, NULL, L':');
|
||||
if (lastColon && lastColon != (lpszPath + 1) && _IsAllDigitsW(lastColon + 1)) {
|
||||
int const second = _wtoi(lastColon + 1);
|
||||
wchar_t const saved = *lastColon;
|
||||
*lastColon = L'\0';
|
||||
LPWSTR prevColon = StrRChr(lpszPath, NULL, L':');
|
||||
if (prevColon && prevColon != (lpszPath + 1) && _IsAllDigitsW(prevColon + 1)) {
|
||||
int const first = _wtoi(prevColon + 1);
|
||||
if (first > 0 && second > 0) {
|
||||
*prevColon = L'\0';
|
||||
if (lineNum) {
|
||||
*lineNum = first;
|
||||
}
|
||||
if (colNum) {
|
||||
*colNum = second;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*lastColon = saved;
|
||||
}
|
||||
|
||||
// Single-colon fallback (preserves te_interp expression support)
|
||||
return SplitFilePathLineNum(lpszPath, lineNum);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// _IsTokenBoundary() - true for chars that delimit a path/URL token
|
||||
// when no selection is present.
|
||||
//
|
||||
static inline bool _IsTokenBoundary(char c)
|
||||
{
|
||||
switch (c) {
|
||||
case ' ': case '\t': case '\r': case '\n':
|
||||
case '\'': case '`': case '"':
|
||||
case '<': case '>': case '|': case '*':
|
||||
case ',': case ';':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// ExtractSelectionOrTokenAtCaret()
|
||||
//
|
||||
// Returns a freshly-allocated HSTRINGW (caller must StrgDestroy()) holding
|
||||
// the current selection, or - if the selection is empty - the span around
|
||||
// the caret bounded by [\s'`"<>|*,;]. Newline-truncates selections.
|
||||
// Strips surrounding whitespace and quote-like characters.
|
||||
//
|
||||
HSTRINGW ExtractSelectionOrTokenAtCaret(void)
|
||||
{
|
||||
HSTRINGW hstr = StrgCreate(NULL);
|
||||
|
||||
DocPos byteStart = 0;
|
||||
DocPos byteEnd = 0;
|
||||
|
||||
if (!SciCall_IsSelectionEmpty()) {
|
||||
byteStart = SciCall_GetSelectionStart();
|
||||
byteEnd = SciCall_GetSelectionEnd();
|
||||
// truncate selection at first \r, \n, \t
|
||||
for (DocPos p = byteStart; p < byteEnd; ++p) {
|
||||
char const c = SciCall_GetCharAt(p);
|
||||
if (c == '\r' || c == '\n' || c == '\t') {
|
||||
byteEnd = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
DocPos const pos = SciCall_GetCurrentPos();
|
||||
DocLn const ln = SciCall_LineFromPosition(pos);
|
||||
DocPos const lineStart = SciCall_PositionFromLine(ln);
|
||||
DocPos const lineEnd = SciCall_GetLineEndPosition(ln);
|
||||
byteStart = pos;
|
||||
while (byteStart > lineStart && !_IsTokenBoundary(SciCall_GetCharAt(byteStart - 1))) {
|
||||
--byteStart;
|
||||
}
|
||||
byteEnd = pos;
|
||||
while (byteEnd < lineEnd && !_IsTokenBoundary(SciCall_GetCharAt(byteEnd))) {
|
||||
++byteEnd;
|
||||
}
|
||||
}
|
||||
|
||||
if (byteEnd > byteStart) {
|
||||
DocPos const length = byteEnd - byteStart;
|
||||
const char* const pszRange = SciCall_GetRangePointer(byteStart, length);
|
||||
if (pszRange) {
|
||||
int const wlen = MultiByteToWideChar(Encoding_SciCP, 0, pszRange, (int)length, NULL, 0);
|
||||
if (wlen > 0) {
|
||||
LPWSTR const buf = StrgWriteAccessBuf(hstr, (size_t)wlen + 1);
|
||||
int const written = MultiByteToWideChar(Encoding_SciCP, 0, pszRange, (int)length, buf, wlen);
|
||||
buf[written] = L'\0';
|
||||
StrgSanitize(hstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (StrgIsNotEmpty(hstr)) {
|
||||
_StripCommonQuoting(hstr);
|
||||
}
|
||||
|
||||
return hstr;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Path_CanonicalizeWithDocAnchor()
|
||||
//
|
||||
// In-place canonicalisation using the document-anchor priority:
|
||||
// 1) directory of Paths.CurrentFile (when non-empty)
|
||||
// 2) Paths.WorkingDirectory (fallback)
|
||||
// never Paths.ModuleDirectory.
|
||||
//
|
||||
// Safe to call for both relative and absolute paths — Path_CanonicalizeEx
|
||||
// only joins the anchor when the path IS relative.
|
||||
//
|
||||
void Path_CanonicalizeWithDocAnchor(HPATHL hpth)
|
||||
{
|
||||
HPATHL hAnchor = Path_Allocate(NULL);
|
||||
if (Path_IsNotEmpty(Paths.CurrentFile)) {
|
||||
Path_Reset(hAnchor, Path_Get(Paths.CurrentFile));
|
||||
Path_RemoveFileSpec(hAnchor);
|
||||
}
|
||||
if (Path_IsEmpty(hAnchor) && Path_IsNotEmpty(Paths.WorkingDirectory)) {
|
||||
Path_Reset(hAnchor, Path_Get(Paths.WorkingDirectory));
|
||||
}
|
||||
Path_CanonicalizeEx(hpth, hAnchor);
|
||||
Path_Release(hAnchor);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// ResolveSelectionToPath()
|
||||
//
|
||||
// Best-effort resolution of a selection token to an absolute filesystem path.
|
||||
//
|
||||
// Steps:
|
||||
// - Strip a leading file:// / file:/// prefix via PathCreateFromUrlW.
|
||||
// - Expand %VAR% environment references.
|
||||
// - If relative: canonicalise against (1) the directory of Paths.CurrentFile
|
||||
// when non-empty, otherwise (2) Paths.WorkingDirectory.
|
||||
// NEVER against Paths.ModuleDirectory.
|
||||
// - Probe filesystem; set *isDir true for an existing directory.
|
||||
//
|
||||
// Returns true iff the resolved path exists. hpthOut is always populated
|
||||
// with the best-effort resolution (caller may inspect on false).
|
||||
//
|
||||
bool ResolveSelectionToPath(LPCWSTR token, HPATHL hpthOut, bool* isDir)
|
||||
{
|
||||
if (isDir) {
|
||||
*isDir = false;
|
||||
}
|
||||
if (!hpthOut) {
|
||||
return false;
|
||||
}
|
||||
Path_Empty(hpthOut, true);
|
||||
if (StrIsEmpty(token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Defensive: callers may pass un-trimmed input. '<' '>' are shell-quote /
|
||||
// mail-style URL wrappers, never legitimate at a path-token boundary —
|
||||
// safe to strip even though they are valid filename chars mid-name.
|
||||
HSTRINGW htmp = StrgCreate(token);
|
||||
_StripCommonQuoting(htmp);
|
||||
|
||||
if (StrgIsEmpty(htmp)) {
|
||||
StrgDestroy(htmp);
|
||||
return false;
|
||||
}
|
||||
|
||||
// file:// / file:/// -> Windows path. Try Shell's PathCreateFromUrlW first;
|
||||
// on failure (malformed URL), fall back to a manual prefix strip so the
|
||||
// canonicalization step below still has a usable best-effort path.
|
||||
LPCWSTR const raw = StrgGet(htmp);
|
||||
if (StrCmpNIW(raw, L"file://", 7) == 0) {
|
||||
WCHAR szPath[INTERNET_MAX_URL_LENGTH + 1] = { L'\0' };
|
||||
DWORD cch = COUNTOF(szPath);
|
||||
if (SUCCEEDED(PathCreateFromUrlW(raw, szPath, &cch, 0))) {
|
||||
StrgReset(htmp, szPath);
|
||||
}
|
||||
else {
|
||||
size_t const skip = (StrCmpNIW(raw, L"file:///", 8) == 0) ? 8 : 7;
|
||||
HSTRINGW hStripped = StrgCreate(raw + skip);
|
||||
StrgSwap(htmp, hStripped);
|
||||
StrgDestroy(hStripped);
|
||||
}
|
||||
}
|
||||
|
||||
// Path_CanonicalizeEx already runs ExpandEnvironmentStrgs(hstr, true) and
|
||||
// strips quotes — no need to expand env vars manually here.
|
||||
Path_Reset(hpthOut, StrgGet(htmp));
|
||||
StrgDestroy(htmp);
|
||||
|
||||
Path_CanonicalizeWithDocAnchor(hpthOut);
|
||||
|
||||
if (Path_IsExistingFile(hpthOut)) {
|
||||
return true;
|
||||
}
|
||||
if (Path_IsExistingDirectory(hpthOut)) {
|
||||
if (isDir) {
|
||||
*isDir = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// FormatNumberStr()
|
||||
|
||||
@ -486,6 +486,11 @@ bool ReadFileXL(HANDLE hFile, char* const lpBuffer, const size_t nNumberOfBytesT
|
||||
bool WriteFileXL(HANDLE hFile, const char* const lpBuffer, const size_t nNumberOfBytesToWrite, size_t* const lpNumberOfBytesWritten);
|
||||
|
||||
bool SplitFilePathLineNum(LPWSTR lpszPath, int *lineNum);
|
||||
bool SplitFilePathLineColNum(LPWSTR lpszPath, int *lineNum, int *colNum);
|
||||
|
||||
HSTRINGW ExtractSelectionOrTokenAtCaret(void);
|
||||
bool ResolveSelectionToPath(LPCWSTR token, HPATHL hpthOut, bool *isDir);
|
||||
void Path_CanonicalizeWithDocAnchor(HPATHL hpth);
|
||||
|
||||
bool StrLTrimI(LPWSTR pszSource,LPCWSTR pszTrimChars);
|
||||
bool StrRTrimI(LPWSTR pszSource,LPCWSTR pszTrimChars);
|
||||
|
||||
142
src/Notepad3.c
142
src/Notepad3.c
@ -6017,6 +6017,132 @@ static bool _HandleEditBasicCommands(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// _ResolveSelectionForOpen()
|
||||
//
|
||||
// Shared preamble for the EditOpen*FromSelection commands:
|
||||
// extract token at selection/caret -> strip line/col suffix -> resolve.
|
||||
// Returns a freshly-allocated HPATHL on success (caller must Path_Release),
|
||||
// or NULL when no token or no resolvable path was found.
|
||||
// *lineNum / *isDir are output-only; either may be NULL.
|
||||
//
|
||||
static HPATHL _ResolveSelectionForOpen(int* lineNum, bool* isDir)
|
||||
{
|
||||
if (lineNum) {
|
||||
*lineNum = -1;
|
||||
}
|
||||
HSTRINGW hToken = ExtractSelectionOrTokenAtCaret();
|
||||
if (StrgIsEmpty(hToken)) {
|
||||
StrgDestroy(hToken);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LPWSTR const tokBuf = StrgWriteAccessBuf(hToken, 0);
|
||||
SplitFilePathLineColNum(tokBuf, lineNum, NULL);
|
||||
StrgSanitize(hToken);
|
||||
|
||||
HPATHL hpth = Path_Allocate(NULL);
|
||||
bool const ok = ResolveSelectionToPath(StrgGet(hToken), hpth, isDir);
|
||||
StrgDestroy(hToken);
|
||||
if (!ok) {
|
||||
Path_Release(hpth);
|
||||
return NULL;
|
||||
}
|
||||
return hpth;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// EditOpenContainingFolderFromSelection()
|
||||
//
|
||||
// Resolves the current selection (or token at the caret) to a filesystem
|
||||
// path and opens Explorer with that file/folder selected.
|
||||
//
|
||||
// Implemented in Notepad3.c (not Edit.c) because <shlobj.h> defines
|
||||
// SORT_ASCENDING / SORT_DESCENDING that collide with Edit.c's SortOrderMask.
|
||||
//
|
||||
void EditOpenContainingFolderFromSelection(void)
|
||||
{
|
||||
HPATHL hpth = _ResolveSelectionForOpen(NULL, NULL);
|
||||
if (!hpth) {
|
||||
MessageBeep(MB_ICONHAND);
|
||||
return;
|
||||
}
|
||||
|
||||
PIDLIST_ABSOLUTE pidl = NULL;
|
||||
SHParseDisplayName(Path_Get(hpth), NULL, &pidl, SFGAO_BROWSABLE | SFGAO_FILESYSTEM, NULL);
|
||||
if (pidl) {
|
||||
SHOpenFolderAndSelectItems(pidl, 0, NULL, 0);
|
||||
ILFree(pidl);
|
||||
}
|
||||
Path_Release(hpth);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// EditOpenFileFromSelection()
|
||||
//
|
||||
// Resolves the selection (or token at the caret) to a file path, then loads
|
||||
// it into Notepad3 (mirrors the OPEN_IN_NOTEPAD3 branch of the hyperlink
|
||||
// handler). For a directory, opens the file-open dialog rooted there.
|
||||
//
|
||||
void EditOpenFileFromSelection(HWND hwnd)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hwnd);
|
||||
|
||||
int lineNum = -1;
|
||||
bool isDir = false;
|
||||
HPATHL hpth = _ResolveSelectionForOpen(&lineNum, &isDir);
|
||||
if (!hpth) {
|
||||
MessageBeep(MB_ICONHAND);
|
||||
return;
|
||||
}
|
||||
|
||||
bool const bReuseWindow = Flags.bReuseWindow;
|
||||
FileLoadFlags fLoadFlags = FLF_None;
|
||||
fLoadFlags |= Settings.SkipUnicodeDetection ? FLF_SkipUnicodeDetect : 0;
|
||||
fLoadFlags |= Settings.SkipANSICodePageDetection ? FLF_SkipANSICPDetection : 0;
|
||||
|
||||
bool success = false;
|
||||
if (!isDir) {
|
||||
if (bReuseWindow) {
|
||||
success = FileLoad(hpth, fLoadFlags, 0, 0);
|
||||
if (success && lineNum > 0) {
|
||||
int const ln = clampi(lineNum - 1, 0, INT_MAX);
|
||||
SciCall_PostMsg(SCI_GOTOLINE, (WPARAM)ln, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
WCHAR wchParams[64];
|
||||
StringCchPrintf(wchParams, COUNTOF(wchParams), L"%s /g %i",
|
||||
Flags.bSingleFileInstance ? L"/ns" : L"/n", clampi(lineNum, 0, INT_MAX));
|
||||
success = LaunchNewInstance(Globals.hwndMain, wchParams, Path_Get(hpth));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (bReuseWindow) {
|
||||
if (OpenFileDlg(Globals.hwndMain, hpth, hpth)) {
|
||||
success = FileLoad(hpth, fLoadFlags, 0, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
WCHAR wchParams[64];
|
||||
StringCchPrintf(wchParams, COUNTOF(wchParams), L"%s",
|
||||
Flags.bSingleFileInstance ? L"/ns" : L"/n");
|
||||
success = LaunchNewInstance(Globals.hwndMain, wchParams, Path_Get(hpth));
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
MessageBeep(MB_ICONHAND);
|
||||
}
|
||||
Path_Release(hpth);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// _HandleEditLineManipulation() - Handler for MsgCommand()
|
||||
@ -6321,6 +6447,15 @@ static bool _HandleEditLineManipulation(HWND hwnd, UINT umsg, WPARAM wParam, LPA
|
||||
break;
|
||||
|
||||
|
||||
case IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL:
|
||||
EditOpenContainingFolderFromSelection();
|
||||
break;
|
||||
|
||||
|
||||
case IDM_EDIT_OPEN_FILE_FROM_SEL:
|
||||
EditOpenFileFromSelection(hwnd);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return false;
|
||||
@ -8888,8 +9023,11 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio
|
||||
StrTrim(szUnEscW, L"/");
|
||||
|
||||
HPATHL hfile_pth = Path_Allocate(szUnEscW);
|
||||
Path_CanonicalizeEx(hfile_pth, Paths.ModuleDirectory);
|
||||
//@@@???Path_CanonicalizeEx(hfile_pth, Paths.WorkingDirectory);
|
||||
// Anchor relative file:// URLs to the directory of the current
|
||||
// document, falling back to the working directory. Never to
|
||||
// Paths.ModuleDirectory — that resolves against Notepad3's
|
||||
// install dir, which is rarely what the author intended.
|
||||
Path_CanonicalizeWithDocAnchor(hfile_pth);
|
||||
|
||||
bool success = false;
|
||||
FileLoadFlags fLoadFlags = FLF_None;
|
||||
|
||||
@ -341,7 +341,7 @@
|
||||
- BUG: [#4952](https://github.com/rizonesoft/Notepad3/issues/4952) - Template vs Action naming inconsistency
|
||||
- [ ] **(Q2) Open Path or Link** - Open file path or URL under cursor
|
||||
- Issue: [#3926](https://github.com/rizonesoft/Notepad3/issues/3926) - Support relative file:// paths
|
||||
- [ ] **(Q1) Open Containing Folder** - Open the folder containing the current file in Explorer
|
||||
- [x] **(Q1) Open Containing Folder** - Open the folder containing the current file in Explorer - ✅ IMPLEMENTED
|
||||
- **Reference**: [Notepad4](https://github.com/zufuliu/notepad4) implements via `CMD_OPEN_CONTAINING_FOLDER` and `EditOpenSelection(OpenSelectionType_ContainingFolder)`
|
||||
|
||||
### Windows Integration
|
||||
|
||||
Loading…
Reference in New Issue
Block a user