From 2daef9ba18d61944266b982f10d38609c2a8d076 Mon Sep 17 00:00:00 2001 From: "METANEOCORTEX\\Kotti" Date: Tue, 5 May 2026 14:16:48 +0200 Subject: [PATCH 1/3] feat: matching braces (Ctrl+B and with selection Ctrl+Shift+B) inside blocks --- language/common_res.h | 2 + language/np3_af_za/strings_af_za.rc | 2 + language/np3_be_by/strings_be_by.rc | 2 + language/np3_de_de/strings_de_de.rc | 2 + language/np3_el_gr/strings_el_gr.rc | 2 + language/np3_en_gb/strings_en_gb.rc | 2 + language/np3_en_us/strings_en_us.rc | 2 + language/np3_es_es/strings_es_es.rc | 2 + language/np3_fi_fi/strings_fi_fi.rc | 2 + language/np3_fr_fr/strings_fr_fr.rc | 2 + language/np3_hi_in/strings_hi_in.rc | 2 + language/np3_hu_hu/strings_hu_hu.rc | 2 + language/np3_id_id/strings_id_id.rc | 2 + language/np3_it_it/strings_it_it.rc | 2 + language/np3_ja_jp/strings_ja_jp.rc | 2 + language/np3_ko_kr/strings_ko_kr.rc | 2 + language/np3_nl_nl/strings_nl_nl.rc | 2 + language/np3_pl_pl/strings_pl_pl.rc | 2 + language/np3_pt_br/strings_pt_br.rc | 2 + language/np3_pt_pt/strings_pt_pt.rc | 2 + language/np3_ru_ru/strings_ru_ru.rc | 2 + language/np3_sk_sk/strings_sk_sk.rc | 2 + language/np3_sv_se/strings_sv_se.rc | 2 + language/np3_tr_tr/strings_tr_tr.rc | 2 + language/np3_vi_vn/strings_vi_vn.rc | 2 + language/np3_zh_cn/strings_zh_cn.rc | 2 + language/np3_zh_tw/strings_zh_tw.rc | 2 + src/Edit.c | 118 +++++++++++++++++++++++++++- src/Notepad3.c | 20 +++++ src/Notepad3.h | 1 + 30 files changed, 191 insertions(+), 2 deletions(-) diff --git a/language/common_res.h b/language/common_res.h index c3ff2b03b..3a86950ee 100644 --- a/language/common_res.h +++ b/language/common_res.h @@ -267,6 +267,8 @@ #define IDS_MUI_URL_DIR_EXISTS 15065 #define IDS_MUI_URL_FILE_EXISTS 15066 #define IDS_MUI_URL_PATH_NOT_FOUND 15067 +#define IDS_MUI_UNMATCHED_BRACE 15068 +#define IDS_MUI_NO_ENCLOSING_BRACE 15069 #define IDS_MUI_SB_MARK_ALL_OCC 15500 #define IDS_MUI_SB_TOGGLE_VIEW 15501 diff --git a/language/np3_af_za/strings_af_za.rc b/language/np3_af_za/strings_af_za.rc index 7e40adc35..4967ee6d6 100644 --- a/language/np3_af_za/strings_af_za.rc +++ b/language/np3_af_za/strings_af_za.rc @@ -208,6 +208,8 @@ BEGIN "URL gespesifiseerde pad nie gevind nie!" IDS_MUI_URL_OPEN_FILE "\nAlt + Klik om die lêer oop te maak" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Klik om skakel in leser oop te maak" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Die behoud van die oorspronklike tydstempel vir lêerveranderings is geaktiveer\nHierdie opsie bly vir hierdie sessie!" IDS_MUI_OUT_OFF_OCCMRK "Die optredemarkers raak op (Bookmerk/Merk)!" diff --git a/language/np3_be_by/strings_be_by.rc b/language/np3_be_by/strings_be_by.rc index 56322989f..a7fb989e6 100644 --- a/language/np3_be_by/strings_be_by.rc +++ b/language/np3_be_by/strings_be_by.rc @@ -208,6 +208,8 @@ BEGIN "Азначаны ва URL шлях не знойдзены!" IDS_MUI_URL_OPEN_FILE "\nAlt + Click, каб адкрыць файл" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Click, каб адкрыць спасылку ў браўзеры" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Захоўванне зыходняй часаадзнакі змянення файла ўключана\nГэта опцыя застанецца ўключанай для гэтай сесіі!" IDS_MUI_OUT_OFF_OCCMRK "Маркеры ўваходжанняў (закладка/падсвечванне) на зыходзе!" diff --git a/language/np3_de_de/strings_de_de.rc b/language/np3_de_de/strings_de_de.rc index c1cca02da..485914a69 100644 --- a/language/np3_de_de/strings_de_de.rc +++ b/language/np3_de_de/strings_de_de.rc @@ -208,6 +208,8 @@ BEGIN "URL spezifizierter Pfad nicht gefunden!" IDS_MUI_URL_OPEN_FILE "\nAlt + Click um die Datei zu öffnen" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Click um die URL im Browser zu öffnen" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Die Speicherung mit originalem Zeitstempel wurde aktiviert\nDiese Option gilt nun für die gesamte Sitzung (Datei)!" IDS_MUI_OUT_OFF_OCCMRK "Es stehen keine weiteren Fundstellen Markierungen/Lesezeichen mehr zur Verfügung!" diff --git a/language/np3_el_gr/strings_el_gr.rc b/language/np3_el_gr/strings_el_gr.rc index d3b1c8c74..3b3b73880 100644 --- a/language/np3_el_gr/strings_el_gr.rc +++ b/language/np3_el_gr/strings_el_gr.rc @@ -208,6 +208,8 @@ BEGIN "Η καθορισμένη διαδρομή URL δεν βρέθηκε!" IDS_MUI_URL_OPEN_FILE "\nAlt + Κλικ για άνοιγμα του αρχείου" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Κλικ για άνοιγμα του συνδέσμου στον περιηγητή" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Η διατήρηση της αρχικής χρονοσήμανσης μεταβολής του αρχείου είναι ενεργοποιημένη\nΑυτή η επιλογή θα παραμείνει για αυτή την σύνοδο!" IDS_MUI_OUT_OFF_OCCMRK "Δεν υπάρχουν άλλοι δείκτες εμφάνισης (Σελιδοδείκτης/Επισήμανση)!" diff --git a/language/np3_en_gb/strings_en_gb.rc b/language/np3_en_gb/strings_en_gb.rc index 6edf38298..ce4e12648 100644 --- a/language/np3_en_gb/strings_en_gb.rc +++ b/language/np3_en_gb/strings_en_gb.rc @@ -208,6 +208,8 @@ BEGIN "URL specified path not found!" IDS_MUI_URL_OPEN_FILE "\nAlt + Click to open the file" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Click to open link in browser" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Preserving original File Modification Timestamp enabled\nThis option will stay for this session!" IDS_MUI_OUT_OFF_OCCMRK "Running out of Occurrence Markers (Bookmark/Highlight)!" diff --git a/language/np3_en_us/strings_en_us.rc b/language/np3_en_us/strings_en_us.rc index 755c2852f..01fd1767a 100644 --- a/language/np3_en_us/strings_en_us.rc +++ b/language/np3_en_us/strings_en_us.rc @@ -208,6 +208,8 @@ BEGIN "URL specified path not found!" IDS_MUI_URL_OPEN_FILE "\nAlt + Click to open the file" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Click to open link in browser" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Preserving original File Modification Timestamp enabled\nThis option will stay for this session!" IDS_MUI_OUT_OFF_OCCMRK "Running out of Occurrence Markers (Bookmark/Highlight)!" diff --git a/language/np3_es_es/strings_es_es.rc b/language/np3_es_es/strings_es_es.rc index 8e144c6e6..12ea906eb 100644 --- a/language/np3_es_es/strings_es_es.rc +++ b/language/np3_es_es/strings_es_es.rc @@ -208,6 +208,8 @@ BEGIN "¡Ruta especificada por URL no encontrada!" IDS_MUI_URL_OPEN_FILE "\nAlt + Cliquear para abrir el archivo" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Cliquear para abrir el enlace en navegador" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Conservar la marca de tiempo de modificación del archivo original habilitada\n¡Esta opción permanecerá para esta sesión!" IDS_MUI_OUT_OFF_OCCMRK "¡No hay más marcadores de ocurrencia (Marcador/Resaltar)!" diff --git a/language/np3_fi_fi/strings_fi_fi.rc b/language/np3_fi_fi/strings_fi_fi.rc index 709383f5c..6d4075d88 100644 --- a/language/np3_fi_fi/strings_fi_fi.rc +++ b/language/np3_fi_fi/strings_fi_fi.rc @@ -208,6 +208,8 @@ BEGIN "URL määriteltyä polkua ei löydy!" IDS_MUI_URL_OPEN_FILE "\nAlt + Avaa tiedosto klikkaamalla" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Avaa linkki selaimessa klikkaamalla" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Alkuperäisen tiedoston muokkausaikaleiman säilyttäminen käytössä\nVaihtoehto säilyy tämän istunnon ajan!" IDS_MUI_OUT_OFF_OCCMRK "Esiintymämerkit loppumassa (kirjanmerkki/korostus)!" diff --git a/language/np3_fr_fr/strings_fr_fr.rc b/language/np3_fr_fr/strings_fr_fr.rc index 68cc36d47..454a0b718 100644 --- a/language/np3_fr_fr/strings_fr_fr.rc +++ b/language/np3_fr_fr/strings_fr_fr.rc @@ -208,6 +208,8 @@ BEGIN "Chemin spécifié par l'URL introuvable !" IDS_MUI_URL_OPEN_FILE "\nAlt + Clic pour ouvrir le fichier" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Clic pour ouvrir le lien dans le navigateur" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Préservation de l'horodatage de modification original du fichier activée\nCette option restera active pour cette session !" IDS_MUI_OUT_OFF_OCCMRK "Il n'y a pas d'autres marqueurs d'occurrence (Signet/Surlignage) !" diff --git a/language/np3_hi_in/strings_hi_in.rc b/language/np3_hi_in/strings_hi_in.rc index 37540f3a5..fe2d9dce8 100644 --- a/language/np3_hi_in/strings_hi_in.rc +++ b/language/np3_hi_in/strings_hi_in.rc @@ -208,6 +208,8 @@ BEGIN "URL निर्दिष्ट स्थान मौजूद नहीं है!" IDS_MUI_URL_OPEN_FILE "\nAlt + फ़ाईल खोलने के लिए क्लिक करें" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + ब्राउज़र में लिंक खोलने के लिए क्लिक करें" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "फ़ाईल परिवर्तन का मौलिक समय संरक्षण सक्षम है\nयह विकल्प इस सत्र के लिए बना रहेगा!" IDS_MUI_OUT_OFF_OCCMRK "उपस्तिथि चिन्हक खत्म हो रहे है (बुकमार्क/हाइलाइट)!" diff --git a/language/np3_hu_hu/strings_hu_hu.rc b/language/np3_hu_hu/strings_hu_hu.rc index baa76118a..d4999c882 100644 --- a/language/np3_hu_hu/strings_hu_hu.rc +++ b/language/np3_hu_hu/strings_hu_hu.rc @@ -208,6 +208,8 @@ BEGIN "Az URL-ben megadott útvonal nem létezik!" IDS_MUI_URL_OPEN_FILE "\nAlt + Kattintás a fájl megnyitásához" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Kattintás a böngészőben való megnyitáshoz" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Az eredeti fájl módosítási idejeének megőrzése opció be van kapcsolva\nA beállítás így marad erre a munkamenetre!" IDS_MUI_OUT_OFF_OCCMRK "Elfogytak a találatjelölők (Könyvjelző/Kiemelés)!" diff --git a/language/np3_id_id/strings_id_id.rc b/language/np3_id_id/strings_id_id.rc index 7f892e9d2..185257fc5 100644 --- a/language/np3_id_id/strings_id_id.rc +++ b/language/np3_id_id/strings_id_id.rc @@ -208,6 +208,8 @@ BEGIN "Jalur URL yang dituju tidak ditemukan!" IDS_MUI_URL_OPEN_FILE "\nAlt + Klik untuk membuka berkas" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Klik untuk membuka tautan di browser" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Mempertahankan berkas dari Modifikasi Stempel Waktu telah diaktifkan\nOpsi ini hanya akan berlangsung untuk sesi ini saja!" IDS_MUI_OUT_OFF_OCCMRK "Penanda Pengulangan Kata telah habis (Markah/Sorotan)!" diff --git a/language/np3_it_it/strings_it_it.rc b/language/np3_it_it/strings_it_it.rc index 8ab934ce9..64940ce3e 100644 --- a/language/np3_it_it/strings_it_it.rc +++ b/language/np3_it_it/strings_it_it.rc @@ -208,6 +208,8 @@ BEGIN "Il percorso specificato nella URL non è stato trovato!" IDS_MUI_URL_OPEN_FILE "\nAlt + Click per aprire il file" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Click per aprire il link nel browser" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Conservazione della data di ultima modifica originale abilitata\nQuesta opzione rimarrà attiva per questa sessione!" IDS_MUI_OUT_OFF_OCCMRK "Marcatori occorrenza in esaurimento (Segnalibro/evidenziatura)!" diff --git a/language/np3_ja_jp/strings_ja_jp.rc b/language/np3_ja_jp/strings_ja_jp.rc index be262660a..e8dad70f2 100644 --- a/language/np3_ja_jp/strings_ja_jp.rc +++ b/language/np3_ja_jp/strings_ja_jp.rc @@ -208,6 +208,8 @@ BEGIN "URL で指定されたパスが見つかりません!" IDS_MUI_URL_OPEN_FILE "\nAlt + クリック : ファイルを開きます" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + クリック : ブラウザーでリンクを開きます" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "元ファイルの更新日時のままにします\nこのセッションでのみ有効となります" IDS_MUI_OUT_OFF_OCCMRK "単語出現マーカーが枯渇しています (しおり/強調表示)!" diff --git a/language/np3_ko_kr/strings_ko_kr.rc b/language/np3_ko_kr/strings_ko_kr.rc index f891385ab..297752c35 100644 --- a/language/np3_ko_kr/strings_ko_kr.rc +++ b/language/np3_ko_kr/strings_ko_kr.rc @@ -208,6 +208,8 @@ BEGIN "URL 지정 경로를 찾을 수 없습니다!" IDS_MUI_URL_OPEN_FILE "\nAlt+클릭하여 파일을 엽니다" IDS_MUI_URL_OPEN_BROWSER "\nCtrl+클릭하여 탐색기에서 링크를 엽니다" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "원래 파일 수정 타임스탬프를 보존할 수 있습니다\n이 옵션은 이 세션에 유지됩니다!" IDS_MUI_OUT_OFF_OCCMRK "발생 마커 (북마크/강조)가 부족합니다!" diff --git a/language/np3_nl_nl/strings_nl_nl.rc b/language/np3_nl_nl/strings_nl_nl.rc index a79239abe..937930845 100644 --- a/language/np3_nl_nl/strings_nl_nl.rc +++ b/language/np3_nl_nl/strings_nl_nl.rc @@ -208,6 +208,8 @@ BEGIN "URL opgegeven pad niet gevonden!" IDS_MUI_URL_OPEN_FILE "\nAlt + Klik om het bestand te openen" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Klik om de link in de browser te openen" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Tijdstempel originele bestandswijziging behouden\nDeze optie blijft gedurende deze sessie actief!" IDS_MUI_OUT_OFF_OCCMRK "Er zijn geen andere markeringen van voorvallen (Bladwijzer/Markering)!" diff --git a/language/np3_pl_pl/strings_pl_pl.rc b/language/np3_pl_pl/strings_pl_pl.rc index 86b7d7260..aba150a00 100644 --- a/language/np3_pl_pl/strings_pl_pl.rc +++ b/language/np3_pl_pl/strings_pl_pl.rc @@ -208,6 +208,8 @@ BEGIN "URL nie znaleziono określonej ścieżki!" IDS_MUI_URL_OPEN_FILE "\nAlt + Kliknij, aby otworzyć plik" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Kliknij, aby otworzyć link w przeglądarce" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Włączono zachowanie znacznika czasu w modyfikacji pliku\nTa opcja pozostanie dla tej sesji!" IDS_MUI_OUT_OFF_OCCMRK "Kończą się znaczniki występowania (Zakładka/Podświetlenie)!" diff --git a/language/np3_pt_br/strings_pt_br.rc b/language/np3_pt_br/strings_pt_br.rc index 6ac304931..34fd9a84a 100644 --- a/language/np3_pt_br/strings_pt_br.rc +++ b/language/np3_pt_br/strings_pt_br.rc @@ -208,6 +208,8 @@ BEGIN "Caminho especificado pelo URL não encontrado!" IDS_MUI_URL_OPEN_FILE "\nAlt + Clique para abrir o arquivo" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Clique para abrir o link no navegador" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Preservação do Timestamp original de Modificação de Arquivo habilitado\nEsta opção ficará ativa durante esta sessão!" IDS_MUI_OUT_OFF_OCCMRK "Ficando sem marcadores de ocorrência (Marcador/Destacado)!" diff --git a/language/np3_pt_pt/strings_pt_pt.rc b/language/np3_pt_pt/strings_pt_pt.rc index 5c4ae6409..153d4f988 100644 --- a/language/np3_pt_pt/strings_pt_pt.rc +++ b/language/np3_pt_pt/strings_pt_pt.rc @@ -208,6 +208,8 @@ BEGIN "Caminho especificado da URL não encontrado!" IDS_MUI_URL_OPEN_FILE "\nAlt + Clique para abrir o ficheiro" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Clique para abrir a ligação no navegador" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Manter a data/hora de modificação original do ficheiro activada\nEsta opção será válida para esta sessão!" IDS_MUI_OUT_OFF_OCCMRK "Não existem outros marcadores de ocorrência (Marcador/Realce)!" diff --git a/language/np3_ru_ru/strings_ru_ru.rc b/language/np3_ru_ru/strings_ru_ru.rc index d3695d06a..89e63ccb9 100644 --- a/language/np3_ru_ru/strings_ru_ru.rc +++ b/language/np3_ru_ru/strings_ru_ru.rc @@ -208,6 +208,8 @@ BEGIN "Указанный в URL путь не найден!" IDS_MUI_URL_OPEN_FILE "\nAlt + Click, чтобы открыть файл" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Click, чтобы открыть ссылку в браузере" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Сохранение исходной метки времени изменения файла включено\nЭта опция останется включенной для текущей сессии!" IDS_MUI_OUT_OFF_OCCMRK "Маркеры вхождения (закладка/отметка) на исходе!" diff --git a/language/np3_sk_sk/strings_sk_sk.rc b/language/np3_sk_sk/strings_sk_sk.rc index 13db117ad..52bb328aa 100644 --- a/language/np3_sk_sk/strings_sk_sk.rc +++ b/language/np3_sk_sk/strings_sk_sk.rc @@ -208,6 +208,8 @@ BEGIN "URL zadaná cesta nebola nájdená!" IDS_MUI_URL_OPEN_FILE "\nAlt + kliknutím otvoríte súbor" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + kliknutím otvoríte prepojenie" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Zachovanie pôvodnej časovej pečiatky pri úprave súboru je povolené\nTáto možnosť zostane len pre túto reláciu!" IDS_MUI_OUT_OFF_OCCMRK "Dochádzajú označené výskyty (záložka/zvýraznenie)!" diff --git a/language/np3_sv_se/strings_sv_se.rc b/language/np3_sv_se/strings_sv_se.rc index 232d5b98e..1ab547e86 100644 --- a/language/np3_sv_se/strings_sv_se.rc +++ b/language/np3_sv_se/strings_sv_se.rc @@ -208,6 +208,8 @@ BEGIN "Angiven URL-sökväg existerar redan!" IDS_MUI_URL_OPEN_FILE "\nAlt + Klicka för att öppna fil" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Klicka för att öppna länken i webbläsaren" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Bevarande av tidsstämpel för filmodifiering är aktiverad\nInställningen är giltig för denna session!" IDS_MUI_OUT_OFF_OCCMRK "Inga fler markeringar (bokmärke/markering)!" diff --git a/language/np3_tr_tr/strings_tr_tr.rc b/language/np3_tr_tr/strings_tr_tr.rc index 397d27feb..d21fa064a 100644 --- a/language/np3_tr_tr/strings_tr_tr.rc +++ b/language/np3_tr_tr/strings_tr_tr.rc @@ -208,6 +208,8 @@ BEGIN "İnternet adresinde belirtilen yol bulunamadı!" IDS_MUI_URL_OPEN_FILE "\nAlt + Dosyayı açmak için tıklayın" IDS_MUI_URL_OPEN_BROWSER "\nCtrl + Bağlantıyı tarayıcıda açmak için tıklayın" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Özgün dosya değişiklik zamanının korunması seçeneği etkinleştirilmiş\nBu seçenek bu oturum boyunca etkin olacak!" IDS_MUI_OUT_OFF_OCCMRK "Yinelenme işaretleyicileri bitiyor (Yer imi/Vurgula)!" diff --git a/language/np3_vi_vn/strings_vi_vn.rc b/language/np3_vi_vn/strings_vi_vn.rc index 207fde563..00a11dabc 100644 --- a/language/np3_vi_vn/strings_vi_vn.rc +++ b/language/np3_vi_vn/strings_vi_vn.rc @@ -208,6 +208,8 @@ BEGIN "Không thể tìm thấy đường dẫn URL đã chỉ định!" IDS_MUI_URL_OPEN_FILE "\nAlt+Click để mở tệp" IDS_MUI_URL_OPEN_BROWSER "\nCtrl+Click để mở liên kết trong trình duyệt" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "Có thể bảo tồn dấu thời gian sửa đổi tệp gốc\nTùy chọn này sẽ giữ nguyên trong phiên này!" IDS_MUI_OUT_OFF_OCCMRK "Không đủ dấu đánh dấu (dấu trang/nổi bật)!" diff --git a/language/np3_zh_cn/strings_zh_cn.rc b/language/np3_zh_cn/strings_zh_cn.rc index c26973458..4a4a205e6 100644 --- a/language/np3_zh_cn/strings_zh_cn.rc +++ b/language/np3_zh_cn/strings_zh_cn.rc @@ -208,6 +208,8 @@ BEGIN "URL 指定的路径不存在!" IDS_MUI_URL_OPEN_FILE "\n按住 Alt 同时点击以打开文件" IDS_MUI_URL_OPEN_BROWSER "\n按住 Ctrl 同时点击以在浏览器中打开链接" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "已启用维持文件最后修改时间功能\n\n本选项将在当前会话期间生效" IDS_MUI_OUT_OFF_OCCMRK "书签/高亮标记已用完!" diff --git a/language/np3_zh_tw/strings_zh_tw.rc b/language/np3_zh_tw/strings_zh_tw.rc index d1238139d..a09d5151c 100644 --- a/language/np3_zh_tw/strings_zh_tw.rc +++ b/language/np3_zh_tw/strings_zh_tw.rc @@ -208,6 +208,8 @@ BEGIN "找不到 URL 指定路徑!" IDS_MUI_URL_OPEN_FILE "\n按住 Alt 同時點選以開啟檔案" IDS_MUI_URL_OPEN_BROWSER "\n按住 Ctrl 同時點選以在瀏覽器中開啟連結" + IDS_MUI_UNMATCHED_BRACE "Unmatched Brace" + IDS_MUI_NO_ENCLOSING_BRACE "No Enclosing Brace" IDS_MUI_INF_PRSVFILEMODTM "已啟用維持檔案最後修改時間功能\n\n本選項將在目前工作階段期間生效" IDS_MUI_OUT_OFF_OCCMRK "書籤/高亮標記已用完!" diff --git a/src/Edit.c b/src/Edit.c index 5d3ddf3c1..c44bb0f36 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -2622,6 +2622,45 @@ void EditHex2Char(HWND hwnd) } +//============================================================================= +// +// _FindEnclosingOpenBrace() - scan backwards to find the unmatched opening +// brace that encloses the given position. Returns brace position or -1. +// +static DocPos _FindEnclosingOpenBrace(DocPos iStartPos) +{ + int depthParen = 0; // () + int depthBracket = 0; // [] + int depthBrace = 0; // {} + + DocPos iPos = iStartPos; + while (iPos > 0) { + iPos = SciCall_PositionBefore(iPos); + const char ch = SciCall_GetCharAt(iPos); + switch (ch) { + case ')': ++depthParen; break; + case ']': ++depthBracket; break; + case '}': ++depthBrace; break; + case '(': + if (depthParen == 0) { return iPos; } + --depthParen; + break; + case '[': + if (depthBracket == 0) { return iPos; } + --depthBracket; + break; + case '{': + if (depthBrace == 0) { return iPos; } + --depthBrace; + break; + default: + break; + } + } + return (DocPos)-1; +} + + //============================================================================= // // EditFindMatchingBrace() @@ -2629,22 +2668,55 @@ void EditHex2Char(HWND hwnd) void EditFindMatchingBrace() { bool bIsAfter = false; + DocPos iBracePos = (DocPos)-1; DocPos iMatchingBracePos = (DocPos)-1; const DocPos iCurPos = SciCall_GetCurrentPos(); const char c = SciCall_GetCharAt(iCurPos); if (StrChrA(NP3_BRACES_TO_MATCH, c)) { + iBracePos = iCurPos; iMatchingBracePos = SciCall_BraceMatch(iCurPos); } else { // Try one before const DocPos iPosBefore = SciCall_PositionBefore(iCurPos); const char cb = SciCall_GetCharAt(iPosBefore); if (StrChrA(NP3_BRACES_TO_MATCH, cb)) { + iBracePos = iPosBefore; iMatchingBracePos = SciCall_BraceMatch(iPosBefore); } bIsAfter = true; } + if (iMatchingBracePos != (DocPos)-1) { iMatchingBracePos = bIsAfter ? iMatchingBracePos : SciCall_PositionAfter(iMatchingBracePos); - Sci_GotoPosChooseCaret(iMatchingBracePos); + if (SciCall_GetSelectionStart() != SciCall_GetSelectionEnd()) { + // Preserve the selection: pivot it so the caret moves to the matching + // brace while the old caret position becomes the new anchor. + UndoTransActionBegin(); + EditSetSelectionEx(iCurPos, iMatchingBracePos, -1, -1); + EndUndoTransAction(); + } else { + Sci_GotoPosChooseCaret(iMatchingBracePos); + } + } else if (iBracePos != (DocPos)-1) { + // At a brace but no match — orphan brace + SciCall_BraceBadLight(iBracePos); + ShowBraceMatchCallTip(iBracePos, IDS_MUI_UNMATCHED_BRACE); + } else { + // Not at a brace — search backwards for enclosing opener + const DocPos iEnclosing = _FindEnclosingOpenBrace(iCurPos); + if (iEnclosing != (DocPos)-1) { + const DocPos iMatch = SciCall_BraceMatch(iEnclosing); + if (iMatch != (DocPos)-1) { + Sci_GotoPosChooseCaret(iEnclosing); + } else { + // Enclosing opener has no match — orphan + SciCall_BraceBadLight(iEnclosing); + ShowBraceMatchCallTip(iEnclosing, IDS_MUI_UNMATCHED_BRACE); + Sci_GotoPosChooseCaret(iEnclosing); + } + } else { + // No enclosing brace found at all + ShowBraceMatchCallTip(iCurPos, IDS_MUI_NO_ENCLOSING_BRACE); + } } } @@ -2656,21 +2728,32 @@ void EditFindMatchingBrace() void EditSelectToMatchingBrace() { bool bIsAfter = false; + DocPos iBracePos = (DocPos)-1; DocPos iMatchingBracePos = -1; const DocPos iCurPos = SciCall_GetCurrentPos(); const char c = SciCall_GetCharAt(iCurPos); if (StrChrA(NP3_BRACES_TO_MATCH, c)) { + iBracePos = iCurPos; iMatchingBracePos = SciCall_BraceMatch(iCurPos); } else { // Try one before const DocPos iPosBefore = SciCall_PositionBefore(iCurPos); const char cb = SciCall_GetCharAt(iPosBefore); if (StrChrA(NP3_BRACES_TO_MATCH, cb)) { + iBracePos = iPosBefore; iMatchingBracePos = SciCall_BraceMatch(iPosBefore); } bIsAfter = true; } - if (iMatchingBracePos != (DocPos)-1) { + // When the caret sits on an opening brace that is also the start of an existing + // selection, the user wants to expand outward to the next enclosing pair — not + // toggle the anchor to the closing brace. + const bool bIsOpeningBrace = (c == '(' || c == '[' || c == '{'); + const bool bSelStartsHere = (SciCall_GetSelectionStart() == iCurPos) && + (SciCall_GetSelectionEnd() != iCurPos); + const bool bExpandOutward = (!bIsAfter && bIsOpeningBrace && bSelStartsHere); + + if (iMatchingBracePos != (DocPos)-1 && !bExpandOutward) { UndoTransActionBegin(); if (bIsAfter) { EditSetSelectionEx(iCurPos, iMatchingBracePos, -1, -1); @@ -2678,6 +2761,37 @@ void EditSelectToMatchingBrace() EditSetSelectionEx(iCurPos, SciCall_PositionAfter(iMatchingBracePos), -1, -1); } EndUndoTransAction(); + } else if (iBracePos != (DocPos)-1 && !bExpandOutward) { + // At a brace but no match — orphan brace + SciCall_BraceBadLight(iBracePos); + ShowBraceMatchCallTip(iBracePos, IDS_MUI_UNMATCHED_BRACE); + } else { + // Find enclosing brace pair and select (or expand outward past current selection) + const DocPos iSelStart = SciCall_GetSelectionStart(); + const DocPos iSelEnd = SciCall_GetSelectionEnd(); + const bool bHasSelection = (iSelStart != iSelEnd); + + DocPos iSearchFrom = bHasSelection ? iSelStart : iCurPos; + const DocPos iEnclosing = _FindEnclosingOpenBrace(iSearchFrom); + + if (iEnclosing != (DocPos)-1) { + const DocPos iMatch = SciCall_BraceMatch(iEnclosing); + if (iMatch != (DocPos)-1) { + // Ensure the match actually encloses the selection/cursor + if (!bHasSelection || iMatch >= iSelEnd) { + UndoTransActionBegin(); + EditSetSelectionEx(iEnclosing, SciCall_PositionAfter(iMatch), -1, -1); + EndUndoTransAction(); + } + } else { + // Enclosing opener has no match — orphan + SciCall_BraceBadLight(iEnclosing); + ShowBraceMatchCallTip(iEnclosing, IDS_MUI_UNMATCHED_BRACE); + } + } else { + // No enclosing brace found at all + ShowBraceMatchCallTip(iCurPos, IDS_MUI_NO_ENCLOSING_BRACE); + } } } diff --git a/src/Notepad3.c b/src/Notepad3.c index e3b1e4838..59f7ee87a 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -12462,6 +12462,26 @@ void ShowWrapAroundCallTip(bool forwardSearch) } +//============================================================================= +// +// ShowBraceMatchCallTip() +// +void ShowBraceMatchCallTip(DocPos pos, UINT idsMsg) +{ + static char chToolTip[80<<2] = { '\0' }; + int const delayClr = Settings2.WrapAroundTooltipTimeout; + if (delayClr >= (_MQ_TIMER_CYCLE << 3)) { + WCHAR wchToolTip[80] = { L'\0' }; + GetLngString(idsMsg, wchToolTip, COUNTOF(wchToolTip)); + WideCharToMultiByte(Encoding_SciCP, 0, wchToolTip, -1, chToolTip, (int)COUNTOF(chToolTip), NULL, NULL); + SciCall_CallTipShow(pos, chToolTip); + _DelayClearCallTip(delayClr); + } else { + Sci_CallTipCancelEx(); + } +} + + //============================================================================= // // PasteBoardTimerProc() diff --git a/src/Notepad3.h b/src/Notepad3.h index 1dbba8887..2dc0364b5 100644 --- a/src/Notepad3.h +++ b/src/Notepad3.h @@ -98,6 +98,7 @@ void ParseCommandLine(); bool CheckAutoLoadMostRecent(); void ShowZoomCallTip(); void ShowWrapAroundCallTip(bool forwardSearch); +void ShowBraceMatchCallTip(DocPos pos, UINT idsMsg); void NP3_ZoomIn(); void NP3_ZoomOut(); From 7b40e4b747b7018ee7d44c8c4830bf3c25b5a229 Mon Sep 17 00:00:00 2001 From: "METANEOCORTEX\\Kotti" Date: Tue, 5 May 2026 14:21:04 +0200 Subject: [PATCH 2/3] fix: documentation --- readme/KeyboardShortcuts.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme/KeyboardShortcuts.md b/readme/KeyboardShortcuts.md index 8036aa5c8..624804b61 100644 --- a/readme/KeyboardShortcuts.md +++ b/readme/KeyboardShortcuts.md @@ -238,8 +238,8 @@ A complete reference for the shortcuts wired into Notepad3 (`src/Notepad3.rc` ac | `F4` | Replace next | NP2 | | `Ctrl+G` | Goto line / column dialog | NP2 | | `Ctrl+Shift+F` | Search in files (grepWin) | (orig-NP2: "Recode as default") | -| `Ctrl+B` | Find matching brace | NP2 | -| `Ctrl+Shift+B` | Select to matching brace | NP2 | +| `Ctrl+B` | **Find matching brace** — if the caret is at a brace `()[]{}` jump to its match; if not at a brace, jump to the nearest enclosing opening brace. If a brace-block selection is active, the caret toggles between the two brace endpoints while preserving the selection. Shows a calltip if no match or no enclosing brace exists. | NP2+ | +| `Ctrl+Shift+B` | **Select to matching brace** — selects the brace pair enclosing the caret (inclusive of both braces). Repeated presses expand the selection outward one nesting level at a time. Pressing when the caret is at the closing brace of the current selection pivots the caret to the opening brace (same selection, reversed direction); pressing again when at the opening brace expands to the next outer pair. Shows a calltip if no match or no enclosing brace exists. | NP2+ | | `Ctrl+Alt+F2` | Expand selection to next match | (orig-NP2: `F2`) | | `Ctrl+Alt+Shift+F2` | Expand selection to previous match | (orig-NP2: `Shift+F2`) | From a63ae718e38b4a15f608e2b7ec937a5f7eaff306 Mon Sep 17 00:00:00 2001 From: "METANEOCORTEX\\Kotti" Date: Tue, 5 May 2026 14:24:20 +0200 Subject: [PATCH 3/3] fix: ToDo list --- todo/TODO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/todo/TODO.md b/todo/TODO.md index de3e4311f..6f34787c0 100644 --- a/todo/TODO.md +++ b/todo/TODO.md @@ -206,7 +206,7 @@ ### Navigation - [ ] **(Q3) Navigate Backward/Forward** - VS Code-like history navigation - [ ] **(Q2) Go to Block Start/End** - Jump to enclosing block -- [ ] **(Q2) Brace Find Enhancement** - Search backward for nearest brace when not at one +- [x] **(Q2) Brace Find Enhancement** - Search backward for nearest brace when not at one - ✅ IMPLEMENTED - Issue: [#4863](https://github.com/rizonesoft/Notepad3/issues/4863) - [ ] **(Q2) Go to Sibling Block** - Navigate between sibling code blocks - [ ] **(Q2) Touchpad Horizontal Scroll** - Direct touchpad left/right scrolling