Compare commits

...

14 Commits

Author SHA1 Message Date
Don Ho
be59048c5e Fix filling Find what length not accurate problem
+ a lot of refactoring

Ref: https://github.com/notepad-plus-plus/notepad-plus-plus/issues/16955#issuecomment-3287770729

Fix #16955, fix #16992, close #17001
2025-09-18 01:14:13 +02:00
Don Ho
7a1cde702a Adjust "Find what" tooltip position for not hidding search settings
Fix #16979, close #16988
2025-09-12 20:31:21 +02:00
Don Ho
962a17e9f6 Allow user to customize max selected chars to auto-fill "Find what" field
Add "Max Characters to Auto-Fill Find Field from Selection" option to allow users to customize max selected characters for auto-filling "Find what" field in Find dialog.
The value can be set from 1 to 16383 characters (not byte).

Note that if "Select Word Under Caret when Nothing Selected" is ON, the word's length in character will be limited also by the set value.

Fix #16955, close #16983
2025-09-11 00:13:23 +02:00
Don Ho
d4442b9d15 Enhance Ctrl-F to copy to Find What field behaviour
Fix https://github.com/notepad-plus-plus/notepad-plus-plus/pull/16976#issuecomment-3265850195
2025-09-08 16:19:40 +02:00
Don Ho
cfc3fb6cf5 Improve copy multilines to comboboxs behaviour in Find Replace Dialog
Fix https://github.com/notepad-plus-plus/notepad-plus-plus/issues/16952#issuecomment-3263821316

Close #16976
2025-09-08 13:04:41 +02:00
Alan Kilborn
5c6f89df32 Add capacity of pasting multiline into Find/Replace fields
Fix #16952, close #16956
2025-09-06 22:37:27 +02:00
xomx
de7aa5ae7a Add NPP_UAC_CREATEEMPTYFILE
+ minor fixes for FileManager::deleteFile

Follow 4b0fc8d316

Fix https://github.com/notepad-plus-plus/notepad-plus-plus/pull/16933#issuecomment-3247142370
2025-09-04 17:16:21 +02:00
PeterCJ
b3884c18af Add NPPM_GETNPPSETTINGSDIRPATH message to get Notepad++ settings directory path
Fix #16944, close #16946
2025-09-04 02:55:28 +02:00
xomx
4b0fc8d316 Improve Notepad++ UAC operations largely
This native implementation of UAC (User Account Control) operations in Notepad++ is designed not only to substitute the deprecated & problematic NppSaveAsAdminPlugin - which interferes with the FlushFileBuffers WINAPI used by Notepad++ - but also to support any future Notepad++ feature which may require elevated privileges.

When a user attempts an operation that fails due to indufficient rights, the system performs only that specific requested action with elevated privileges. After completing it, the elevated Notepad++ instance immediately exits, returning the user to his/her original Notepad++ instance seamlessly, as if nothing unusual occured.

This mechanism is independent of any Notepad++ features such as backup-snapshot or multi-instance mode. All UAC-related operations are executed at the very beginning of the wWinMain function, ensuring they are not affected by mutex handling, or other internal logic.

Importantly, this approach eliminates the need for a separate signed helper executable like NppAdminAcess.exe. Everything is handled within the main Notepad++ project, just as before.

In this commit, the NPP_UAC_SAVE, NPP_UAC_SETFILEATTRIBUTES & NPP_UAC_MOVEFILE are implemented.

Summary of the changes:

added last _dwErrorCode in:
.\PowerEditor\src\MISC\Common\FileInterface.h
.\PowerEditor\src\MISC\Common\FileInterface.cpp

FileManager::saveBuffer adjustment for the NPP_UAC_SAVE_SIGN in:
.\PowerEditor\src\ScintillaComponent\Buffer.cpp

N++ UAC ops signatures definitions & new invokeNppUacOp common func, toggleReadOnlyFlagFromFileAttributes func adjustment for the NPP_UAC_SETFILEATTRIBUTES_SIGN in:
.\PowerEditor\src\MISC\Common\Common.h
.\PowerEditor\src\MISC\Common\Common.cpp

only to fix Notepad_plus::doSave for isEndSessionCritical() in:
.\PowerEditor\src\NppIO.cpp

added getLastFileErrorState() & m_dwLastFileError in:
.\PowerEditor\src\Utf8_16.h
.\PowerEditor\src\Utf8_16.cpp

UAC ops handling at the very start of wWinMain + added new NPP_UAC_ handling nppUacSave and nppUacSetFileAttributes funcs in:
.\PowerEditor\src\winmain.cpp

Fix #886, fix #8655, fix #9561, fix #10302, fix #14990, fix #15008, fix #15137, fix #15323, close #16933
2025-09-02 19:20:59 +02:00
Don HO
dc58d41359 Enhance Column Editor
1. Change the order of GUI items to make the insert mode (dec/hex/oct/bin) more explicit.
2. Reduce the showing time of the warning baloon tip from ~10 seconds to 3.5 seconds.
3. Use ESC keystroke to cancel the warning baloon tip.

ref: https://github.com/notepad-plus-plus/notepad-plus-plus/pull/16931#issuecomment-3236582042

Note that while the baloon tip showing then clicking on the upper-right 'X', the dialog won't be closed. Instead, the baloon tip will be cancel.
Curiously, clicking on the "Cancel" button under the same context closes the dialog.
The reason could be, while the "Cancel" button being clicked, the focus is changed and the system hides the baloon tip. Whereas the click on the upper-right 'X' doesn't make the focus changed, then the system does nothing.
Anyway such behaviour is a bug, but can happen very rarily.

Close #16959
2025-08-31 12:26:19 +02:00
Don Ho
06750919ac Fix column editor egression: insert column with bad parameters
The regression was introduced by: 1a0e8bea75

Ref: https://github.com/notepad-plus-plus/notepad-plus-plus/pull/16931#issuecomment-3236873787

Close #16951
2025-08-29 18:52:55 +02:00
PeterCJ
1a0e8bea75 Use radix for GUI input fields to match the output in Column Editor
Use hex/oct/bin for GUI input fields, to match the output, and allow choosing a-f vs A-F for output.

Fix #16912, close #16931
2025-08-29 13:15:47 +02:00
PeterCJ
dab30de9c6 Fix font size inconsistencies
No fontSize definitions except in Default Style, and Default Style always = 10pt

Fix #16924, close #16928
2025-08-20 14:07:05 +02:00
Alan Kilborn
5933f791c4 Prevent stale search-result from making selection inside a multibyte character
Fix #16879, close #16897
2025-08-17 22:40:35 +02:00
56 changed files with 1324 additions and 500 deletions

View File

@ -1214,6 +1214,7 @@ Translation note:
<Item id="6909" name="Select Word Under Caret when Nothing Selected"/> <Item id="6909" name="Select Word Under Caret when Nothing Selected"/>
<Item id="6910" name="Minimum Size for Auto-Checking &quot;In selection&quot;:"/> <Item id="6910" name="Minimum Size for Auto-Checking &quot;In selection&quot;:"/>
<Item id="6913" name="Fill Find in Files Directory Field Based On Active Document"/> <Item id="6913" name="Fill Find in Files Directory Field Based On Active Document"/>
<Item id="6916" name=": Max Characters to Auto-Fill Find Field from Selection"/>
</Searching> </Searching>
<RecentFilesHistory title="Recent Files History"> <RecentFilesHistory title="Recent Files History">
@ -1865,7 +1866,8 @@ Click on &quot;?&quot; button on right to open website with User Manual."/>
<!-- Don't translate "(&quot;Non-printing characters custom color&quot;)" --> <!-- Don't translate "(&quot;Non-printing characters custom color&quot;)" -->
<npcCustomColor-tip value="Go to Style Configurator to change the default custom color for selected whitespace and non-printing characters (&quot;Non-printing characters custom color&quot;)."/> <npcCustomColor-tip value="Go to Style Configurator to change the default custom color for selected whitespace and non-printing characters (&quot;Non-printing characters custom color&quot;)."/>
<npcIncludeCcUniEol-tip value="Apply non-printing characters appearance settings to C0, C1 control and Unicode EOL (next line, line separator and paragraph separator) characters."/> <npcIncludeCcUniEol-tip value="Apply non-printing characters appearance settings to C0, C1 control and Unicode EOL (next line, line separator and paragraph separator) characters."/>
<searchingInSelThresh-tip value="Number of selected characters in edit zone to automatically check the &quot;In selection&quot; checkbox when the Find dialog is activated. The maximum value is 1024. Set the value to 0 to disable auto-checking."/> <searchingInSelThresh-tip value="Minimum number of selected characters in edit zone to automatically check the &quot;In selection&quot; checkbox when the Find dialog is activated. The maximum value is $INT_REPLACE$. Set the value to 0 to disable auto-checking."/>
<searchingFillFindWhat-tip value="Maximum number of selected characters in edit zone to fill automatically the &quot;Find what&quot; field when the Ctrl-F is triggered. The maximum value is $INT_REPLACE$, which is the maximum size of &quot;Find what&quot; field, limited by the system."/>
<verticalEdge-tip value="Add your column marker by indicating its position with a decimal number. You can define several column markers by using white space to separate the different numbers."/> <verticalEdge-tip value="Add your column marker by indicating its position with a decimal number. You can define several column markers by using white space to separate the different numbers."/>
<fileSaveAsCopySaveButton-tip value="Hold Shift while pressing Save to open the copy after saving."/> <fileSaveAsCopySaveButton-tip value="Hold Shift while pressing Save to open the copy after saving."/>
<autoIndentBasic-tip value="Ensure that the indentation of the current line (i.e. the new line created by pressing the ENTER key) matches the indentation of the previous line."/> <autoIndentBasic-tip value="Ensure that the indentation of the current line (i.e. the new line created by pressing the ENTER key) matches the indentation of the previous line."/>
@ -1889,8 +1891,9 @@ If you select advanced mode but do not edit files in the aforementioned language
<statusbar-Sel value="Sel: "/> <statusbar-Sel value="Sel: "/>
<statusbar-Sel-number value="Sel"/> <statusbar-Sel-number value="Sel"/>
<toolbar-accent-tip value="This option makes your toolbar icons follow Windows system accent color. Accent color is the highlight color used in buttons, borders, and Start menu tiles in Windows. To change it, go to Settings &gt; Personalization &gt; Colors, then select your preferred accent color."/> <toolbar-accent-tip value="This option makes your toolbar icons follow Windows system accent color. Accent color is the highlight color used in buttons, borders, and Start menu tiles in Windows. To change it, go to Settings &gt; Personalization &gt; Colors, then select your preferred accent color."/>
<max-len-on-search-tip value="Only $INT_REPLACE$ characters are allowed for the find/replace text length - your input could be truncated, and it won't be saved for the next session."/> <len-limit-exceeded-tip value="Length limit exceeded: Your input may exceed the limit allowed and could have been truncated, and it won't be saved for the next session."/>
<max-len-on-save-tip value="This search input (> $INT_REPLACE$ characters) won't be saved for the next session."/> <max-len-on-search-tip value="Your input may exceed the limit allowed and could have been truncated, and it won't be saved for the next session."/>
<max-len-on-save-tip value="The length of your input is very long and may not be saved for your next session."/>
<goto-setting-tip value="Find your setting here"/> <goto-setting-tip value="Find your setting here"/>
</MiscStrings> </MiscStrings>
</Native-Langue> </Native-Langue>

View File

@ -1214,6 +1214,7 @@ Translation note:
<Item id="6909" name="Select Word Under Caret when Nothing Selected"/> <Item id="6909" name="Select Word Under Caret when Nothing Selected"/>
<Item id="6910" name="Minimum Size for Auto-Checking &quot;In selection&quot;:"/> <Item id="6910" name="Minimum Size for Auto-Checking &quot;In selection&quot;:"/>
<Item id="6913" name="Fill Find in Files Directory Field Based On Active Document"/> <Item id="6913" name="Fill Find in Files Directory Field Based On Active Document"/>
<Item id="6916" name=": Max Characters to Auto-Fill Find Field from Selection"/>
</Searching> </Searching>
<RecentFilesHistory title="Recent Files History"> <RecentFilesHistory title="Recent Files History">
@ -1865,7 +1866,8 @@ Click on &quot;?&quot; button on right to open website with User Manual."/>
<!-- Don't translate "(&quot;Non-printing characters custom color&quot;)" --> <!-- Don't translate "(&quot;Non-printing characters custom color&quot;)" -->
<npcCustomColor-tip value="Go to Style Configurator to change the default custom color for selected whitespace and non-printing characters (&quot;Non-printing characters custom color&quot;)."/> <npcCustomColor-tip value="Go to Style Configurator to change the default custom color for selected whitespace and non-printing characters (&quot;Non-printing characters custom color&quot;)."/>
<npcIncludeCcUniEol-tip value="Apply non-printing characters appearance settings to C0, C1 control and Unicode EOL (next line, line separator and paragraph separator) characters."/> <npcIncludeCcUniEol-tip value="Apply non-printing characters appearance settings to C0, C1 control and Unicode EOL (next line, line separator and paragraph separator) characters."/>
<searchingInSelThresh-tip value="Number of selected characters in edit zone to automatically check the &quot;In selection&quot; checkbox when the Find dialog is activated. The maximum value is 1024. Set the value to 0 to disable auto-checking."/> <searchingInSelThresh-tip value="Minimum number of selected characters in edit zone to automatically check the &quot;In selection&quot; checkbox when the Find dialog is activated. The maximum value is $INT_REPLACE$. Set the value to 0 to disable auto-checking."/>
<searchingFillFindWhat-tip value="Maximum number of selected characters in edit zone to fill automatically the &quot;Find what&quot; field when the Ctrl-F is triggered. The maximum value is $INT_REPLACE$, which is the maximum size of &quot;Find what&quot; field, limited by the system."/>
<verticalEdge-tip value="Add your column marker by indicating its position with a decimal number. You can define several column markers by using white space to separate the different numbers."/> <verticalEdge-tip value="Add your column marker by indicating its position with a decimal number. You can define several column markers by using white space to separate the different numbers."/>
<fileSaveAsCopySaveButton-tip value="Hold Shift while pressing Save to open the copy after saving."/> <fileSaveAsCopySaveButton-tip value="Hold Shift while pressing Save to open the copy after saving."/>
<autoIndentBasic-tip value="Ensure that the indentation of the current line (i.e. the new line created by pressing the ENTER key) matches the indentation of the previous line."/> <autoIndentBasic-tip value="Ensure that the indentation of the current line (i.e. the new line created by pressing the ENTER key) matches the indentation of the previous line."/>
@ -1889,8 +1891,9 @@ If you select advanced mode but do not edit files in the aforementioned language
<statusbar-Sel value="Sel: "/> <statusbar-Sel value="Sel: "/>
<statusbar-Sel-number value="Sel"/> <statusbar-Sel-number value="Sel"/>
<toolbar-accent-tip value="This option makes your toolbar icons follow Windows system accent color. Accent color is the highlight color used in buttons, borders, and Start menu tiles in Windows. To change it, go to Settings &gt; Personalization &gt; Colors, then select your preferred accent color."/> <toolbar-accent-tip value="This option makes your toolbar icons follow Windows system accent color. Accent color is the highlight color used in buttons, borders, and Start menu tiles in Windows. To change it, go to Settings &gt; Personalization &gt; Colors, then select your preferred accent color."/>
<max-len-on-search-tip value="Only $INT_REPLACE$ characters are allowed for the find/replace text length - your input could be truncated, and it won't be saved for the next session."/> <len-limit-exceeded-tip value="Length limit exceeded: Your input may exceed the limit allowed and could have been truncated, and it won't be saved for the next session."/>
<max-len-on-save-tip value="This search input (> $INT_REPLACE$ characters) won't be saved for the next session."/> <max-len-on-search-tip value="Your input may exceed the limit allowed and could have been truncated, and it won't be saved for the next session."/>
<max-len-on-save-tip value="The length of your input is very long and may not be saved for your next session."/>
<goto-setting-tip value="Find your setting here"/> <goto-setting-tip value="Find your setting here"/>
</MiscStrings> </MiscStrings>
</Native-Langue> </Native-Langue>

View File

@ -1211,7 +1211,8 @@ Translation note:
<Item id="6908" name="Remplir le champ de recherche avec le texte sélectionné"/> <Item id="6908" name="Remplir le champ de recherche avec le texte sélectionné"/>
<Item id="6909" name="Sélectionner le mot sous le curseur si rien nest sélectionné"/> <Item id="6909" name="Sélectionner le mot sous le curseur si rien nest sélectionné"/>
<Item id="6910" name="Taille minimale pour lauto-coche de « Dans la sélection » :"/> <Item id="6910" name="Taille minimale pour lauto-coche de « Dans la sélection » :"/>
<Item id="6913" name="Remplir le champ Répertoire de la Recherche dans les fichiers en se basant sur la document actif"/> <Item id="6913" name="Remplir le champ de &quot;Dossier&quot; de &quot;Recherche dans les fichiers&quot; avec chemin du fichier actif"/>
<Item id="6916" name=" : Nombre max. de caractères sélectionnés à copier dans le champ de recherche"/>
</Searching> </Searching>
<RecentFilesHistory title="Fichiers récents"> <RecentFilesHistory title="Fichiers récents">
@ -1860,7 +1861,8 @@ Cliquez sur le bouton « ? » à droite pour ouvrir le site web du manuel utilis
<!-- Don't translate "(&quot;Non-printing characters custom color&quot;)" --> <!-- Don't translate "(&quot;Non-printing characters custom color&quot;)" -->
<npcCustomColor-tip value="Aller dans le Configurateur de style pour changer la couleur personnalisée par défaut pour la sélection des caractères blancs et des caractères non-imprimables (« Couleur personnalisée des caractères non-imprimables »)."/> <npcCustomColor-tip value="Aller dans le Configurateur de style pour changer la couleur personnalisée par défaut pour la sélection des caractères blancs et des caractères non-imprimables (« Couleur personnalisée des caractères non-imprimables »)."/>
<npcIncludeCcUniEol-tip value="Applique les paramètres dapparence des caractères non-imprimables aux contrôles C0, C1 et aux caractères Unicode EOL (ligne suivante, séparateur de ligne et séparateur de paragraphe)."/> <npcIncludeCcUniEol-tip value="Applique les paramètres dapparence des caractères non-imprimables aux contrôles C0, C1 et aux caractères Unicode EOL (ligne suivante, séparateur de ligne et séparateur de paragraphe)."/>
<searchingInSelThresh-tip value="Nombre de caractères sélectionnés dans la zone dédition pour cocher automatiquement la case « Dans sélection » quand la fenêtre de recherche est activée. La valeur maximale est 1024. Mettre la valeur à 0 pour désactiver lauto-coche."/> <searchingInSelThresh-tip value="Nombre minimal de caractères sélectionnés dans la zone dédition pour cocher automatiquement la case « Dans sélection » quand la fenêtre de recherche est activée. La valeur maximale est $INT_REPLACE$. Mettre la valeur à 0 pour désactiver lauto-coche."/>
<searchingFillFindWhat-tip value="Nombre maximal de caractères sélectionnés dans la zone de texte à utiliser pour remplir automatiquement le champ « Rechercher » lors de l'activation de la combinaison Ctrl+F. La valeur maximale est $INT_REPLACE$, soit la taille maximale du champ « Rechercher », limitée par le système."/>
<verticalEdge-tip value="Ajoutez votre marqueur de colonne en indiquant sa position avec un nombre entier. Vous pouvez définir plusieurs marqueurs de colonne en utilisant un espace pour séparer les différents nombres."/> <verticalEdge-tip value="Ajoutez votre marqueur de colonne en indiquant sa position avec un nombre entier. Vous pouvez définir plusieurs marqueurs de colonne en utilisant un espace pour séparer les différents nombres."/>
<fileSaveAsCopySaveButton-tip value="Maintenez Shift en appuyant sur Enregistrer pour ouvrir une copie après enregistrement."/> <fileSaveAsCopySaveButton-tip value="Maintenez Shift en appuyant sur Enregistrer pour ouvrir une copie après enregistrement."/>
<autoIndentBasic-tip value="Assurez-vous que la ligne courante (c'est-à-dire la nouvelle ligne saisie en appuyant sur ENTRÉE) a la même indentation que la ligne précédente."/> <autoIndentBasic-tip value="Assurez-vous que la ligne courante (c'est-à-dire la nouvelle ligne saisie en appuyant sur ENTRÉE) a la même indentation que la ligne précédente."/>
@ -1884,8 +1886,9 @@ Si vous sélectionnez le mode avancé sans modifier les fichiers des langues men
<statusbar-Sel value="Sel : "/> <statusbar-Sel value="Sel : "/>
<statusbar-Sel-number value="Sel"/> <statusbar-Sel-number value="Sel"/>
<toolbar-accent-tip value="Cette option permet aux icônes de votre barre d'outils d'adopter la couleur d'accentuation du système Windows. La couleur d'accentuation est la couleur de surbrillance utilisée pour les boutons, les bordures et les tuiles du menu Démarrer sous Windows. Pour la modifier, accédez à Paramètres &gt; Personnalisation &gt; Couleurs, puis sélectionnez votre couleur d'accentuation préférée."/> <toolbar-accent-tip value="Cette option permet aux icônes de votre barre d'outils d'adopter la couleur d'accentuation du système Windows. La couleur d'accentuation est la couleur de surbrillance utilisée pour les boutons, les bordures et les tuiles du menu Démarrer sous Windows. Pour la modifier, accédez à Paramètres &gt; Personnalisation &gt; Couleurs, puis sélectionnez votre couleur d'accentuation préférée."/>
<max-len-on-search-tip value="Seuls $INT_REPLACE$ caractères sont autorisés pour la longueur du texte de recherche/remplacement - votre saisie pourrait être tronquée et ne serait pas enregistrée pour la session suivante."/> <len-limit-exceeded-tip value="Limite de longueur dépassée : Votre saisie peut dépasser la limite autorisée et avoir été tronquée, et elle ne sera pas enregistrée pour la prochaine session."/>
<max-len-on-save-tip value="Cette entrée de recherche (> $INT_REPLACE$ caractères) ne sera pas enregistrée pour la prochaine session."/> <max-len-on-search-tip value="Votre saisie peut dépasser la limite autorisée et avoir été tronquée, et elle ne sera pas enregistrée pour la prochaine session."/>
<max-len-on-save-tip value="La longueur de votre saisie est très longue et il se peut qu'elle ne soit pas enregistrée pour votre prochaine session."/>
<goto-setting-tip value="Réglage du paramètre ici"/> <goto-setting-tip value="Réglage du paramètre ici"/>
</MiscStrings> </MiscStrings>
</Native-Langue> </Native-Langue>

View File

@ -1167,6 +1167,8 @@
<Item id="6908" name="用選取詞填充尋找與取代對話方塊中的尋找內容"/> <Item id="6908" name="用選取詞填充尋找與取代對話方塊中的尋找內容"/>
<Item id="6909" name="在沒有任何選取時,選取游標下的字串"/> <Item id="6909" name="在沒有任何選取時,選取游標下的字串"/>
<Item id="6910" name="啟動自動勾選核取方塊「僅尋找選取範圍」的最小值:"/> <Item id="6910" name="啟動自動勾選核取方塊「僅尋找選取範圍」的最小值:"/>
<Item id="6913" name="根據目前啟用文件的路徑自動填入「在多個檔案中尋找」的「資料夾」欄"/>
<Item id="6916" name=":從選定內容中自動填入查找欄位的最大字元數"/>
</Searching> </Searching>
<RecentFilesHistory title="最近使用的檔案"> <RecentFilesHistory title="最近使用的檔案">
@ -1686,7 +1688,8 @@
1. 修改這些選項需要重新開啟已開啟的大型文件以達到預期的效果。 1. 修改這些選項需要重新開啟已開啟的大型文件以達到預期的效果。
2. 如果「停用自動換行」被啟動,在開啟一個大型文件時,「自動換行」將對所有文件停用。 你可以通過選單「檢視-&gt;自動換行」重新啟動這個功能。"/> 2. 如果「停用自動換行」被啟動,在開啟一個大型文件時,「自動換行」將對所有文件停用。 你可以通過選單「檢視-&gt;自動換行」重新啟動這個功能。"/>
<searchingInSelThresh-tip value="在尋找與取代對話方塊啟動時,為啟動自動勾選核取方塊「僅尋找選取範圍」在編輯區中選取的字符數量。 最大值為 1024。 將值設置為 0 將停止自動勾選功能。"/> <searchingInSelThresh-tip value="在尋找與取代對話方塊啟動時,為啟動自動勾選核取方塊「僅尋找選取範圍」在編輯區中選取的最小字符數量。 最大值為 $INT_REPLACE$。 將值設置為 0 將停止自動勾選功能。"/>
<searchingFillFindWhat-tip value="在尋找與取代對話方塊啟動時,為啟動自動填入「尋找內容」欄位,以編輯區域中選定字元的最大值(最多 $INT_REPLACE 個字元)。此值是「尋找內容」欄位的最大長度,由系統限制。"/>
<verticalEdge-tip value="如欲添加列標記可以在下面以數字指示其列位置。使用空格分隔不同數字來定義多個列標記。"/> <verticalEdge-tip value="如欲添加列標記可以在下面以數字指示其列位置。使用空格分隔不同數字來定義多個列標記。"/>
<autoIndentBasic-tip value="確保目前行(即按 ENTER 鍵所打的新行)的縮排與上一行的縮排相同。"/> <autoIndentBasic-tip value="確保目前行(即按 ENTER 鍵所打的新行)的縮排與上一行的縮排相同。"/>
<autoIndentAdvanced-tip value="啟用為「類 C Python C <autoIndentAdvanced-tip value="啟用為「類 C Python C
@ -1708,8 +1711,9 @@ C、C++、Java、C#、Objective-C、PHP、JavaScript、JSP、CSS、Perl、Rust
<statusbar-Sel value="選取:"/> <statusbar-Sel value="選取:"/>
<statusbar-Sel-number value="選取"/> <statusbar-Sel-number value="選取"/>
<toolbar-accent-tip value="此選項可讓您的工具列圖示遵循 Windows 系統強調色。強調色是 Windows 中的按鈕、邊框和開始功能表圖塊所使用的反白顯示顏色。要更改它,請轉到「設定」&gt;「個性化」&gt;「顏色」,然後選擇您喜歡的強調色。"/> <toolbar-accent-tip value="此選項可讓您的工具列圖示遵循 Windows 系統強調色。強調色是 Windows 中的按鈕、邊框和開始功能表圖塊所使用的反白顯示顏色。要更改它,請轉到「設定」&gt;「個性化」&gt;「顏色」,然後選擇您喜歡的強調色。"/>
<max-len-on-search-tip value="尋找/取代文字長度僅允許 $INT_REPLACE$ 個字元 - 您的輸入可能會被截斷,此搜尋輸入也將不會保存以供下次 Notepad++ 啟動時使用。"/> <len-limit-exceeded-tip value="已超出長度限制:輸入內容可能超出允許的限制並已被截斷,此輸入也將不會保存以供下次 Notepad++ 啟動時使用。"/>
<max-len-on-save-tip value="此搜尋輸入( > $INT_REPLACE$ 個字元)將不會保存以供下次 Notepad++ 啟動時使用。"/> <max-len-on-search-tip value="輸入內容可能超出允許的限制並已被截斷,此輸入也將不會保存以供下次 Notepad++ 啟動時使用。"/>
<max-len-on-save-tip value="輸入內容過長,可能無法保存以供下次 Notepad++ 啟動時使用。"/>
<goto-setting-tip value="相關的偏好設定在此"/> <goto-setting-tip value="相關的偏好設定在此"/>
</MiscStrings> </MiscStrings>
</Native-Langue> </Native-Langue>

View File

@ -1053,7 +1053,7 @@ Credits:
<WidgetStyle name="Caret colour" styleID="2069" fgColor="37A8ED" /> <WidgetStyle name="Caret colour" styleID="2069" fgColor="37A8ED" />
<WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="37A8ED" /> <WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="37A8ED" />
<WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" /> <WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" />
<WidgetStyle name="Line number margin" styleID="33" fgColor="E5C138" bgColor="4C4A41" fontName="" fontStyle="0" fontSize="8" /> <WidgetStyle name="Line number margin" styleID="33" fgColor="E5C138" bgColor="4C4A41" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Bookmark margin" styleID="0" bgColor="4C4A41" /> <WidgetStyle name="Bookmark margin" styleID="0" bgColor="4C4A41" />
<WidgetStyle name="Change History margin" styleID="0" bgColor="4C4A41" /> <WidgetStyle name="Change History margin" styleID="0" bgColor="4C4A41" />
<WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" /> <WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" />
@ -1094,6 +1094,6 @@ Credits:
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="BDAE9D" bgColor="2A211C" /> <WidgetStyle name="Document map" styleID="0" fgColor="BDAE9D" bgColor="2A211C" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="BDAE9D" bgColor="2A211C" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="BDAE9D" bgColor="2A211C" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1043,7 +1043,7 @@ Credits:
<WidgetStyle name="Caret colour" styleID="2069" fgColor="FFFFFF" /> <WidgetStyle name="Caret colour" styleID="2069" fgColor="FFFFFF" />
<WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" /> <WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" />
<WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="8" /> <WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" /> <WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" />
@ -1084,6 +1084,6 @@ Credits:
<WidgetStyle name="URL hovered" styleID="0" fgColor="BDAE9D" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="BDAE9D" />
<WidgetStyle name="Document map" styleID="0" fgColor="F8F8F8" bgColor="0C1021" /> <WidgetStyle name="Document map" styleID="0" fgColor="F8F8F8" bgColor="0C1021" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="F8F8F8" bgColor="0C1021" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="F8F8F8" bgColor="0C1021" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1043,7 +1043,7 @@ Credits:
<WidgetStyle name="Caret colour" styleID="2069" fgColor="A7A7A7" /> <WidgetStyle name="Caret colour" styleID="2069" fgColor="A7A7A7" />
<WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="A7A7A7" /> <WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="A7A7A7" />
<WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" /> <WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" />
<WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="8" /> <WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" /> <WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" />
@ -1084,6 +1084,6 @@ Credits:
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="C3BE98" bgColor="1A0F0B" /> <WidgetStyle name="Document map" styleID="0" fgColor="C3BE98" bgColor="1A0F0B" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="C3BE98" bgColor="1A0F0B" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="C3BE98" bgColor="1A0F0B" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1162,7 +1162,7 @@ Installation : Copy this file to "%APPDATA%\Notepad++\themes" and in a portable
<WidgetStyle name="Caret colour" styleID="2069" fgColor="A7A7A7" /> <WidgetStyle name="Caret colour" styleID="2069" fgColor="A7A7A7" />
<WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="A7A7A7" /> <WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="A7A7A7" />
<WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" /> <WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" />
<WidgetStyle name="Line number margin" styleID="33" fgColor="8F8F8F" bgColor="363636" fontName="" fontStyle="0" fontSize="9" /> <WidgetStyle name="Line number margin" styleID="33" fgColor="8F8F8F" bgColor="363636" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Bookmark margin" styleID="0" bgColor="363636" /> <WidgetStyle name="Bookmark margin" styleID="0" bgColor="363636" />
<WidgetStyle name="Change History margin" styleID="0" bgColor="363636" /> <WidgetStyle name="Change History margin" styleID="0" bgColor="363636" />
<WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" /> <WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" />
@ -1203,6 +1203,6 @@ Installation : Copy this file to "%APPDATA%\Notepad++\themes" and in a portable
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="C7C7C7" bgColor="2E2E2E" /> <WidgetStyle name="Document map" styleID="0" fgColor="C7C7C7" bgColor="2E2E2E" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="C7C7C7" bgColor="2E2E2E" fontName="Source Code Pro" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="C7C7C7" bgColor="2E2E2E" fontName="Source Code Pro" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1822,6 +1822,6 @@ License: GPL2
<WidgetStyle name="Document map" styleID="0" fgColor="000000" bgColor="FFFFFF" /> <WidgetStyle name="Document map" styleID="0" fgColor="000000" bgColor="FFFFFF" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Non-printing characters custom color" styleID="0" fgColor="5F5F5F" /> <WidgetStyle name="Non-printing characters custom color" styleID="0" fgColor="5F5F5F" />
<WidgetStyle name="Global override" styleID="0" fgColor="DCDCCC" bgColor="3F3F3F" fontName="Consolas" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="DCDCCC" bgColor="3F3F3F" fontName="Consolas" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1038,7 +1038,7 @@ https://notepad-plus-plus.org/donate/
</LexerStyles> </LexerStyles>
<GlobalStyles> <GlobalStyles>
<!-- Attention : Don't modify the name of styleID="0" --> <!-- Attention : Don't modify the name of styleID="0" -->
<WidgetStyle name="Default Style" styleID="32" fgColor="FFFFFF" bgColor="000000" fontName="Courier New" fontStyle="0" fontSize="9" /> <WidgetStyle name="Default Style" styleID="32" fgColor="FFFFFF" bgColor="000000" fontName="Courier New" fontStyle="0" fontSize="10" />
<WidgetStyle name="Indent guideline style" styleID="37" fgColor="C0C0C0" bgColor="000000" fontName="" fontStyle="0" fontSize="" /> <WidgetStyle name="Indent guideline style" styleID="37" fgColor="C0C0C0" bgColor="000000" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Brace highlight style" styleID="34" fgColor="00FF00" bgColor="000000" fontName="" fontStyle="1" fontSize="" /> <WidgetStyle name="Brace highlight style" styleID="34" fgColor="00FF00" bgColor="000000" fontName="" fontStyle="1" fontSize="" />
<WidgetStyle name="Bad brace colour" styleID="35" fgColor="FF0000" bgColor="000000" fontName="" fontStyle="1" fontSize="" /> <WidgetStyle name="Bad brace colour" styleID="35" fgColor="FF0000" bgColor="000000" fontName="" fontStyle="1" fontSize="" />
@ -1091,6 +1091,6 @@ https://notepad-plus-plus.org/donate/
<WidgetStyle name="Document map" styleID="0" fgColor="FF8000" bgColor="FFFFFF" /> <WidgetStyle name="Document map" styleID="0" fgColor="FF8000" bgColor="FFFFFF" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Non-printing characters custom color" styleID="0" fgColor="FF8080" /> <WidgetStyle name="Non-printing characters custom color" styleID="0" fgColor="FF8080" />
<WidgetStyle name="Global override" styleID="0" fgColor="FFFFFF" bgColor="000000" fontName="Courier New" fontStyle="0" fontSize="9" /> <WidgetStyle name="Global override" styleID="0" fgColor="FFFFFF" bgColor="000000" fontName="Courier New" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1062,6 +1062,6 @@ so your enhanced file can be included in Notepad++ future release.
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="000000" bgColor="FFB0FF" /> <WidgetStyle name="Document map" styleID="0" fgColor="000000" bgColor="FFB0FF" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="FFFF80" bgColor="FFB0FF" fontName="Courier New" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="FFFF80" bgColor="FFB0FF" fontName="Courier New" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1219,6 +1219,6 @@ Installation:
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="B7975D" bgColor="2B0F01" /> <WidgetStyle name="Document map" styleID="0" fgColor="B7975D" bgColor="2B0F01" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="B7975D" bgColor="2B0F01" fontName="Consolas" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="B7975D" bgColor="2B0F01" fontName="Consolas" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1048,7 +1048,7 @@ Credits:
<WidgetStyle name="Caret colour" styleID="2069" fgColor="FFFFFF" /> <WidgetStyle name="Caret colour" styleID="2069" fgColor="FFFFFF" />
<WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" /> <WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" />
<WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="8" /> <WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" /> <WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" />
@ -1089,6 +1089,6 @@ Credits:
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="FFFFFF" bgColor="222C28" /> <WidgetStyle name="Document map" styleID="0" fgColor="FFFFFF" bgColor="222C28" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="FFFFFF" bgColor="222C28" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="FFFFFF" bgColor="222C28" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1064,7 +1064,7 @@ Credits:
<WidgetStyle name="Caret colour" styleID="2069" fgColor="F8F8F0" /> <WidgetStyle name="Caret colour" styleID="2069" fgColor="F8F8F0" />
<WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="F8F8F0" /> <WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="F8F8F0" />
<WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" /> <WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" />
<WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="8" /> <WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" /> <WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" />
@ -1105,6 +1105,6 @@ Credits:
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="F8F8F2" bgColor="272822" /> <WidgetStyle name="Document map" styleID="0" fgColor="F8F8F2" bgColor="272822" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="F8F8F2" bgColor="272822" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="F8F8F2" bgColor="272822" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1219,6 +1219,6 @@ Installation:
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="F2C476" bgColor="58693D" /> <WidgetStyle name="Document map" styleID="0" fgColor="F2C476" bgColor="58693D" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="F2C476" bgColor="58693D" fontName="Consolas" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="F2C476" bgColor="58693D" fontName="Consolas" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1216,6 +1216,6 @@ Installation:
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="000000" bgColor="BA9C80" /> <WidgetStyle name="Document map" styleID="0" fgColor="000000" bgColor="BA9C80" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="000000" bgColor="BA9C80" fontName="Consolas" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="000000" bgColor="BA9C80" fontName="Consolas" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1121,6 +1121,6 @@ Notepad++ Custom Style
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="E0E2E4" bgColor="293134" /> <WidgetStyle name="Document map" styleID="0" fgColor="E0E2E4" bgColor="293134" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="E0E2E4" bgColor="293134" fontName="Courier New" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="E0E2E4" bgColor="293134" fontName="Courier New" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1060,7 +1060,7 @@ Credits:
<WidgetStyle name="Caret colour" styleID="2069" fgColor="8BA7A7" /> <WidgetStyle name="Caret colour" styleID="2069" fgColor="8BA7A7" />
<WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="8BA7A7" /> <WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="8BA7A7" />
<WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" /> <WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" />
<WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="8" /> <WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" /> <WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" />
@ -1101,6 +1101,6 @@ Credits:
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="F8F8F8" bgColor="0B161D" /> <WidgetStyle name="Document map" styleID="0" fgColor="F8F8F8" bgColor="0B161D" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="F8F8F8" bgColor="0B161D" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="F8F8F8" bgColor="0B161D" fontName="DejaVu Sans Mono" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -899,7 +899,7 @@ http://sourceforge.net/donate/index.php?group_id=95717
<WidgetStyle name="Caret colour" styleID="2069" fgColor="FFFFFF" /> <WidgetStyle name="Caret colour" styleID="2069" fgColor="FFFFFF" />
<WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Edge colour" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="Edge colour" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Line number margin" styleID="33" fgColor="FFFFFF" bgColor="1F4661" fontName="" fontStyle="0" fontSize="8" /> <WidgetStyle name="Line number margin" styleID="33" fgColor="FFFFFF" bgColor="1F4661" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Bookmark margin" styleID="0" bgColor="1F4661" /> <WidgetStyle name="Bookmark margin" styleID="0" bgColor="1F4661" />
<WidgetStyle name="Change History margin" styleID="0" bgColor="1F4661" /> <WidgetStyle name="Change History margin" styleID="0" bgColor="1F4661" />
<WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" /> <WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" />
@ -940,6 +940,6 @@ http://sourceforge.net/donate/index.php?group_id=95717
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="FFFFFF" bgColor="112435" /> <WidgetStyle name="Document map" styleID="0" fgColor="FFFFFF" bgColor="112435" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="FFFF80" bgColor="FF8000" fontName="Courier New" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="FFFF80" bgColor="FF8000" fontName="Courier New" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1227,6 +1227,6 @@ Installation:
<WidgetStyle name="URL hovered" styleID="0" fgColor="808040" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="808040" />
<WidgetStyle name="Document map" styleID="0" fgColor="657B83" bgColor="FDF6E3" /> <WidgetStyle name="Document map" styleID="0" fgColor="657B83" bgColor="FDF6E3" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="657B83" bgColor="FDF6E3" fontName="Consolas" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="657B83" bgColor="FDF6E3" fontName="Consolas" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1619,6 +1619,6 @@ Installation:
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="839496" bgColor="002B36" /> <WidgetStyle name="Document map" styleID="0" fgColor="839496" bgColor="002B36" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="839496" bgColor="002B36" fontName="Consolas" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="839496" bgColor="002B36" fontName="Consolas" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1049,7 +1049,7 @@ Credits:
<WidgetStyle name="Caret colour" styleID="2069" fgColor="A7A7A7" /> <WidgetStyle name="Caret colour" styleID="2069" fgColor="A7A7A7" />
<WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="A7A7A7" /> <WidgetStyle name="Multi-edit carets color" styleID="0" fgColor="A7A7A7" />
<WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" /> <WidgetStyle name="Edge colour" styleID="0" fgColor="EEEEEC" />
<WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="8" /> <WidgetStyle name="Line number margin" styleID="33" fgColor="EEEEEC" bgColor="2E3436" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Bookmark margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" /> <WidgetStyle name="Change History margin" styleID="0" bgColor="2E3436" />
<WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" /> <WidgetStyle name="Change History modified" styleID="0" fgColor="FF8000" bgColor="FF8000" />
@ -1090,6 +1090,6 @@ Credits:
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="F8F8F8" bgColor="141414" /> <WidgetStyle name="Document map" styleID="0" fgColor="F8F8F8" bgColor="141414" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="F8F8F8" bgColor="141414" fontName="Consolas" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="F8F8F8" bgColor="141414" fontName="Consolas" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1060,6 +1060,6 @@ http://sourceforge.net/donate/index.php?group_id=95717
<WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="FFFFFF" />
<WidgetStyle name="Document map" styleID="0" fgColor="FFFFFF" bgColor="000000" /> <WidgetStyle name="Document map" styleID="0" fgColor="FFFFFF" bgColor="000000" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="FFFF80" bgColor="FF8000" fontName="Courier New" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="FFFF80" bgColor="FF8000" fontName="Courier New" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1789,6 +1789,6 @@ License: GPL2
<WidgetStyle name="URL hovered" styleID="0" fgColor="A3DCA3" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="A3DCA3" />
<WidgetStyle name="Document map" styleID="0" fgColor="000000" bgColor="FFFFFF" /> <WidgetStyle name="Document map" styleID="0" fgColor="000000" bgColor="FFFFFF" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="DCDCCC" bgColor="3F3F3F" fontName="Consolas" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="DCDCCC" bgColor="3F3F3F" fontName="Consolas" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -1216,6 +1216,6 @@ Installation:
<WidgetStyle name="URL hovered" styleID="0" fgColor="808040" /> <WidgetStyle name="URL hovered" styleID="0" fgColor="808040" />
<WidgetStyle name="Document map" styleID="0" fgColor="5F5F00" bgColor="D7D7AF" /> <WidgetStyle name="Document map" styleID="0" fgColor="5F5F00" bgColor="D7D7AF" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="808080" />
<WidgetStyle name="Global override" styleID="0" fgColor="5F5F00" bgColor="D7D7AF" fontName="Consolas" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="5F5F00" bgColor="D7D7AF" fontName="Consolas" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -955,6 +955,29 @@ bool str2Clipboard(const wstring &str2cpy, HWND hwnd)
return true; return true;
} }
std::wstring strFromClipboard()
{
std::wstring clipboardText;
if (::OpenClipboard(NULL))
{
if (::IsClipboardFormatAvailable(CF_UNICODETEXT))
{
HANDLE hClipboardData = ::GetClipboardData(CF_UNICODETEXT);
if (hClipboardData)
{
wchar_t* pWc = static_cast<wchar_t*>(::GlobalLock(hClipboardData));
if (pWc)
{
clipboardText = pWc;
::GlobalUnlock(hClipboardData);
}
}
}
::CloseClipboard();
}
return clipboardText;
}
bool buf2Clipboard(const std::vector<Buffer*>& buffers, bool isFullPath, HWND hwnd) bool buf2Clipboard(const std::vector<Buffer*>& buffers, bool isFullPath, HWND hwnd)
{ {
const wstring crlf = L"\r\n"; const wstring crlf = L"\r\n";
@ -1537,7 +1560,25 @@ bool toggleReadOnlyFlagFromFileAttributes(const wchar_t* fileFullPath, bool& isC
} }
else else
{ {
// probably the ERROR_ACCESS_DENIED (5) (TODO: UAC-prompt candidate) if (::GetLastError() == ERROR_ACCESS_DENIED)
{
// try to set elevated
// (notepad++.exe #UAC-SETFILEATTRIBUTES# attrib_flags_number_str dest_file_path)
wstring strCmdLineParams = NPP_UAC_SETFILEATTRIBUTES_SIGN;
strCmdLineParams += L" \"" + to_wstring(dwFileAttribs) + L"\" \"";
strCmdLineParams += fileFullPath;
strCmdLineParams += L"\"";
DWORD dwNppUacOpError = invokeNppUacOp(strCmdLineParams);
if (dwNppUacOpError == NO_ERROR)
{
isChangedToReadOnly = (dwFileAttribs & FILE_ATTRIBUTE_READONLY) != 0;
return true;
}
else
{
::SetLastError(dwNppUacOpError); // set that as our current thread one for a possible reporting later
}
}
return false; return false;
} }
} }
@ -2095,7 +2136,7 @@ bool isCoreWindows()
return isCoreWindows; return isCoreWindows;
} }
bool ControlInfoTip::init(HINSTANCE hInst, HWND ctrl2attached, HWND ctrl2attachedParent, const wstring& tipStr, bool isRTL, unsigned int remainTimeMillisecond /* = 0 */) bool ControlInfoTip::init(HINSTANCE hInst, HWND ctrl2attached, HWND ctrl2attachedParent, const wstring& tipStr, bool isRTL, unsigned int remainTimeMillisecond /* = 0 */, int maxWidth /* = 200 */)
{ {
_hWndInfoTip = CreateWindowEx(isRTL ? WS_EX_LAYOUTRTL : 0, TOOLTIPS_CLASS, NULL, _hWndInfoTip = CreateWindowEx(isRTL ? WS_EX_LAYOUTRTL : 0, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON, WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON,
@ -2120,7 +2161,7 @@ bool ControlInfoTip::init(HINSTANCE hInst, HWND ctrl2attached, HWND ctrl2attache
return false; return false;
} }
SendMessage(_hWndInfoTip, TTM_SETMAXTIPWIDTH, 0, 200); SendMessage(_hWndInfoTip, TTM_SETMAXTIPWIDTH, 0, maxWidth);
SendMessage(_hWndInfoTip, TTM_ACTIVATE, TRUE, 0); SendMessage(_hWndInfoTip, TTM_ACTIVATE, TRUE, 0);
if (remainTimeMillisecond) if (remainTimeMillisecond)
@ -2129,14 +2170,22 @@ bool ControlInfoTip::init(HINSTANCE hInst, HWND ctrl2attached, HWND ctrl2attache
return true; return true;
} }
void ControlInfoTip::show() const void ControlInfoTip::show(showPosition pos) const
{ {
if (!isValid()) return; if (!isValid()) return;
RECT rcComboBox; RECT rcComboBox;
GetWindowRect(reinterpret_cast<HWND>(_toolInfo.uId), &rcComboBox); GetWindowRect(reinterpret_cast<HWND>(_toolInfo.uId), &rcComboBox);
int xPos = rcComboBox.left + (rcComboBox.right - rcComboBox.left) / 2; int xPos = 0;
if (pos == beginning)
xPos = rcComboBox.left + 15;
else if (pos == middle)
xPos = rcComboBox.left + (rcComboBox.right - rcComboBox.left) / 2;
else // (pos == end)
xPos = rcComboBox.left + (rcComboBox.right - rcComboBox.left) - 15;
int yPos = rcComboBox.top + 25; int yPos = rcComboBox.top + 25;
SendMessage(_hWndInfoTip, TTM_TRACKPOSITION, 0, MAKELPARAM(xPos, yPos)); SendMessage(_hWndInfoTip, TTM_TRACKPOSITION, 0, MAKELPARAM(xPos, yPos));
@ -2154,3 +2203,40 @@ void ControlInfoTip::hide()
} }
#pragma warning(default:4996) #pragma warning(default:4996)
DWORD invokeNppUacOp(std::wstring& strCmdLineParams)
{
if ((strCmdLineParams.length() == 0) || (strCmdLineParams.length() > (USHRT_MAX / sizeof(WCHAR))))
{
// no cmdline or it exceeds the current max WinOS 32767 WCHARs
return ERROR_INVALID_PARAMETER;
}
wchar_t wszNppFullPath[MAX_PATH]{};
::SetLastError(NO_ERROR);
if (!::GetModuleFileName(NULL, wszNppFullPath, MAX_PATH) || (::GetLastError() == ERROR_INSUFFICIENT_BUFFER))
{
return ::GetLastError();
}
SHELLEXECUTEINFOW sei{};
sei.cbSize = sizeof(SHELLEXECUTEINFOW);
sei.lpVerb = L"runas"; // UAC prompt
sei.nShow = SW_SHOWNORMAL;
sei.fMask = SEE_MASK_NOCLOSEPROCESS; // sei.hProcess member receives the launched process handle
sei.lpFile = wszNppFullPath;
sei.lpParameters = strCmdLineParams.c_str();
if (!::ShellExecuteExW(&sei))
return ::GetLastError();
// wait for the elevated Notepad++ process to finish
DWORD dwError = NO_ERROR;
if (sei.hProcess) // beware - do not check here for the INVALID_HANDLE_VALUE (valid GetCurrentProcess() pseudohandle)
{
::WaitForSingleObject(sei.hProcess, INFINITE);
::GetExitCodeProcess(sei.hProcess, &dwError);
::CloseHandle(sei.hProcess);
}
return dwError;
}

View File

@ -169,6 +169,7 @@ std::wstring stringTakeWhileAdmissable(const std::wstring& input, const std::wst
double stodLocale(const std::wstring& str, _locale_t loc, size_t* idx = NULL); double stodLocale(const std::wstring& str, _locale_t loc, size_t* idx = NULL);
bool str2Clipboard(const std::wstring &str2cpy, HWND hwnd); bool str2Clipboard(const std::wstring &str2cpy, HWND hwnd);
std::wstring strFromClipboard();
class Buffer; class Buffer;
bool buf2Clipboard(const std::vector<Buffer*>& buffers, bool isFullPath, HWND hwnd); bool buf2Clipboard(const std::vector<Buffer*>& buffers, bool isFullPath, HWND hwnd);
@ -310,7 +311,7 @@ public:
hide(); hide();
} }
}; };
bool init(HINSTANCE hInst, HWND ctrl2attached, HWND ctrl2attachedParent, const std::wstring& tipStr, bool isRTL, unsigned int remainTimeMillisecond = 0); // remainTimeMillisecond = 0: no timeout bool init(HINSTANCE hInst, HWND ctrl2attached, HWND ctrl2attachedParent, const std::wstring& tipStr, bool isRTL, unsigned int remainTimeMillisecond = 0, int maxWidth = 200); // remainTimeMillisecond = 0: no timeout
bool isValid() const { bool isValid() const {
return _hWndInfoTip != nullptr; return _hWndInfoTip != nullptr;
@ -320,7 +321,8 @@ public:
return _hWndInfoTip; return _hWndInfoTip;
}; };
void show() const; enum showPosition {beginning, middle, end};
void show(showPosition pos = middle) const;
void hide(); void hide();
@ -331,3 +333,10 @@ private:
ControlInfoTip(const ControlInfoTip&) = delete; ControlInfoTip(const ControlInfoTip&) = delete;
ControlInfoTip& operator=(const ControlInfoTip&) = delete; ControlInfoTip& operator=(const ControlInfoTip&) = delete;
}; };
#define NPP_UAC_SAVE_SIGN L"#UAC-SAVE#"
#define NPP_UAC_SETFILEATTRIBUTES_SIGN L"#UAC-SETFILEATTRIBUTES#"
#define NPP_UAC_MOVEFILE_SIGN L"#UAC-MOVEFILE#"
#define NPP_UAC_CREATEEMPTYFILE_SIGN L"#UAC-CREATEEMPTYFILE#"
DWORD invokeNppUacOp(std::wstring& strCmdLineParams);

View File

@ -54,8 +54,11 @@ Win32_IO_File::Win32_IO_File(const wchar_t *fname)
{ {
bool isFromNetwork = PathIsNetworkPath(fname); bool isFromNetwork = PathIsNetworkPath(fname);
if (isFromNetwork && isTimeoutReached) // The file doesn't exist, and the file is a network file, plus the network problem has been detected due to timeout if (isFromNetwork && isTimeoutReached) // The file doesn't exist, and the file is a network file, plus the network problem has been detected due to timeout
{
_dwErrorCode = ERROR_FILE_NOT_FOUND; // store
return; // In this case, we don't call createFile to prevent hanging return; // In this case, we don't call createFile to prevent hanging
} }
}
_hFile = ::CreateFileW(fname, _accessParam, _shareParam, NULL, dispParam, _attribParam, NULL); _hFile = ::CreateFileW(fname, _accessParam, _shareParam, NULL, dispParam, _attribParam, NULL);
@ -68,6 +71,9 @@ Win32_IO_File::Win32_IO_File(const wchar_t *fname)
_hFile = ::CreateFileW(fname, _accessParam, _shareParam, NULL, dispParam, _attribParam, NULL); _hFile = ::CreateFileW(fname, _accessParam, _shareParam, NULL, dispParam, _attribParam, NULL);
} }
if (_hFile == INVALID_HANDLE_VALUE)
_dwErrorCode = ::GetLastError(); // store
if (fileExists && (dispParam == CREATE_ALWAYS) && (_hFile != INVALID_HANDLE_VALUE)) if (fileExists && (dispParam == CREATE_ALWAYS) && (_hFile != INVALID_HANDLE_VALUE))
{ {
// restore back the original creation date & attributes // restore back the original creation date & attributes
@ -91,7 +97,7 @@ Win32_IO_File::Win32_IO_File(const wchar_t *fname)
else else
{ {
msg += " failed to open, CreateFileW ErrorCode: "; msg += " failed to open, CreateFileW ErrorCode: ";
msg += std::to_string(::GetLastError()); msg += std::to_string(_dwErrorCode);
} }
writeLog(nppIssueLog.c_str(), msg.c_str()); writeLog(nppIssueLog.c_str(), msg.c_str());
} }
@ -100,11 +106,13 @@ Win32_IO_File::Win32_IO_File(const wchar_t *fname)
void Win32_IO_File::close() void Win32_IO_File::close()
{ {
_dwErrorCode = NO_ERROR; // reset
if (isOpened()) if (isOpened())
{ {
NppParameters& nppParam = NppParameters::getInstance(); NppParameters& nppParam = NppParameters::getInstance();
DWORD flushError = NOERROR; DWORD flushError = NO_ERROR;
if (_written) if (_written)
{ {
if (!::FlushFileBuffers(_hFile)) if (!::FlushFileBuffers(_hFile))
@ -159,7 +167,14 @@ Please try using another storage and also check if your saved data is not corrup
} }
} }
} }
::CloseHandle(_hFile);
_dwErrorCode = flushError; // store possible flushing error 1st
if (!::CloseHandle(_hFile))
{
if (!flushError)
_dwErrorCode = ::GetLastError(); // store
}
_hFile = INVALID_HANDLE_VALUE; _hFile = INVALID_HANDLE_VALUE;
@ -194,6 +209,8 @@ Please try using another storage and also check if your saved data is not corrup
bool Win32_IO_File::write(const void *wbuf, size_t buf_size) bool Win32_IO_File::write(const void *wbuf, size_t buf_size)
{ {
_dwErrorCode = NO_ERROR; // reset
if (!isOpened() || (wbuf == nullptr)) if (!isOpened() || (wbuf == nullptr))
return false; return false;
@ -203,6 +220,7 @@ bool Win32_IO_File::write(const void *wbuf, size_t buf_size)
size_t bytes_left_to_write = buf_size; size_t bytes_left_to_write = buf_size;
BOOL success = FALSE; BOOL success = FALSE;
DWORD writeError = NO_ERROR; // use also a local var here to be 100% thread-safe
do do
{ {
@ -219,6 +237,10 @@ bool Win32_IO_File::write(const void *wbuf, size_t buf_size)
bytes_left_to_write -= static_cast<size_t>(bytes_written); bytes_left_to_write -= static_cast<size_t>(bytes_written);
total_bytes_written += static_cast<size_t>(bytes_written); total_bytes_written += static_cast<size_t>(bytes_written);
} }
else
{
writeError = ::GetLastError();
}
} while (success && bytes_left_to_write); } while (success && bytes_left_to_write);
NppParameters& nppParam = NppParameters::getInstance(); NppParameters& nppParam = NppParameters::getInstance();
@ -234,11 +256,11 @@ bool Win32_IO_File::write(const void *wbuf, size_t buf_size)
std::string msg = _path; std::string msg = _path;
msg += " written failed: "; msg += " written failed: ";
std::wstring lastErrorMsg = GetLastErrorAsString(::GetLastError()); std::wstring lastErrorMsg = GetLastErrorAsString(writeError);
msg += wstring2string(lastErrorMsg, CP_UTF8); msg += wstring2string(lastErrorMsg, CP_UTF8);
writeLog(nppIssueLog.c_str(), msg.c_str()); writeLog(nppIssueLog.c_str(), msg.c_str());
} }
_dwErrorCode = writeError; // store
return false; return false;
} }
else else

View File

@ -48,6 +48,10 @@ public:
return write(str.c_str(), str.length()); return write(str.c_str(), str.length());
}; };
DWORD getLastErrorCode() {
return _dwErrorCode;
};
private: private:
HANDLE _hFile {INVALID_HANDLE_VALUE}; HANDLE _hFile {INVALID_HANDLE_VALUE};
bool _written {false}; bool _written {false};
@ -56,4 +60,6 @@ private:
const DWORD _accessParam { GENERIC_READ | GENERIC_WRITE }; const DWORD _accessParam { GENERIC_READ | GENERIC_WRITE };
const DWORD _shareParam { FILE_SHARE_READ | FILE_SHARE_WRITE }; const DWORD _shareParam { FILE_SHARE_READ | FILE_SHARE_WRITE };
const DWORD _attribParam { FILE_ATTRIBUTE_NORMAL }; const DWORD _attribParam { FILE_ATTRIBUTE_NORMAL };
DWORD _dwErrorCode{ NO_ERROR };
}; };

View File

@ -1025,6 +1025,19 @@ enum Platform { PF_UNKNOWN, PF_X86, PF_X64, PF_IA64, PF_ARM64 };
// Return toolbar icon set choice as an integer value. Here are 5 possible values: // Return toolbar icon set choice as an integer value. Here are 5 possible values:
// 0 (Fluent UI: small), 1 (Fluent UI: large), 2 (Filled Fluent UI: small), 3 (Filled Fluent UI: large) and 4 (Standard icons: small). // 0 (Fluent UI: small), 1 (Fluent UI: large), 2 (Filled Fluent UI: small), 3 (Filled Fluent UI: large) and 4 (Standard icons: small).
#define NPPM_GETNPPSETTINGSDIRPATH (NPPMSG + 119)
// int NPPM_GETNPPSETTINGSDIRPATH(size_t strLen, wchar_t *settingsDirPath)
// Get path for the active Notepad++ settings: it will use -settingsDir path if that's defined; if not, it will use Cloud directory if that's defined;
// if not, it will use the AppData settings directory, or finally the installation path. This allows plugins to have one interface to find out
// where the active Notepad++ settings are stored, whichever location they are currently set to.
// wParam[in]: strLen - size of allocated buffer "settingsDirPath"
// lParam[out]: settingsDirPath - Users should call it with settingsDirPath be NULL to get the required number of wchar_t (not including the terminating nul character),
// allocate settingsDirPath buffer with the return value + 1, then call it again to get the path.
// Returns the number of wchar_t copied/to copy. If the return value is 0, then the "strLen" is not enough to copy the path, or the settings path could not be determined.
//
// Note: This message is for the active Notepad++ configuration location. If you are looking for the settings directory for plugins (...\Plugins\Config\),
// use NPPM_GETPLUGINSCONFIGDIR instead.
// For RUNCOMMAND_USER // For RUNCOMMAND_USER
#define VAR_NOT_RECOGNIZED 0 #define VAR_NOT_RECOGNIZED 0
#define FULL_CURRENT_PATH 1 #define FULL_CURRENT_PATH 1

View File

@ -503,20 +503,11 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
case NPPM_LAUNCHFINDINFILESDLG: case NPPM_LAUNCHFINDINFILESDLG:
{ {
// Find in files function code should be here due to the number of parameters (2) cannot be passed via WM_COMMAND // Find in files function code should be here due to the number of parameters (2) cannot be passed via WM_COMMAND
constexpr int strSize = FINDREPLACE_MAXLENGTH;
bool isFirstTime = !_findReplaceDlg.isCreated(); bool isFirstTime = !_findReplaceDlg.isCreated();
_findReplaceDlg.doDialog(FIND_DLG, _nativeLangSpeaker.isRTL()); _findReplaceDlg.doDialog(FIND_DLG, _nativeLangSpeaker.isRTL());
const NppGUI& nppGui = nppParam.getNppGUI(); _findReplaceDlg.setSearchTextWithSettings();
if (nppGui._fillFindFieldWithSelected)
{
auto str = std::make_unique<wchar_t[]>(strSize);
std::fill_n(str.get(), strSize, L'\0');
_pEditView->getGenericSelectedText(str.get(), strSize, nppGui._fillFindFieldSelectCaret);
_findReplaceDlg.setSearchText(str.get());
}
if (isFirstTime) if (isFirstTime)
_nativeLangSpeaker.changeFindReplaceDlgLang(_findReplaceDlg); _nativeLangSpeaker.changeFindReplaceDlgLang(_findReplaceDlg);
@ -528,17 +519,14 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
case NPPM_INTERNAL_FINDINPROJECTS: case NPPM_INTERNAL_FINDINPROJECTS:
{ {
constexpr int strSize = FINDREPLACE_MAXLENGTH;
auto str = std::make_unique<wchar_t[]>(strSize);
std::fill_n(str.get(), strSize, L'\0');
bool isFirstTime = not _findReplaceDlg.isCreated(); bool isFirstTime = not _findReplaceDlg.isCreated();
_findReplaceDlg.doDialog(FIND_DLG, _nativeLangSpeaker.isRTL()); _findReplaceDlg.doDialog(FIND_DLG, _nativeLangSpeaker.isRTL());
_pEditView->getGenericSelectedText(str.get(), strSize); _findReplaceDlg.setSearchTextWithSettings();
_findReplaceDlg.setSearchText(str.get());
if (isFirstTime) if (isFirstTime)
_nativeLangSpeaker.changeDlgLang(_findReplaceDlg.getHSelf(), "Find"); _nativeLangSpeaker.changeDlgLang(_findReplaceDlg.getHSelf(), "Find");
_findReplaceDlg.launchFindInProjectsDlg(); _findReplaceDlg.launchFindInProjectsDlg();
_findReplaceDlg.setProjectCheckmarks(NULL, (int) wParam); _findReplaceDlg.setProjectCheckmarks(NULL, (int) wParam);
return TRUE; return TRUE;
@ -546,18 +534,13 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
case NPPM_INTERNAL_FINDINFINDERDLG: case NPPM_INTERNAL_FINDINFINDERDLG:
{ {
constexpr int strSize = FINDREPLACE_MAXLENGTH;
auto str = std::make_unique<wchar_t[]>(strSize);
std::fill_n(str.get(), strSize, L'\0');
Finder *launcher = reinterpret_cast<Finder *>(wParam); Finder *launcher = reinterpret_cast<Finder *>(wParam);
bool isFirstTime = !_findInFinderDlg.isCreated(); bool isFirstTime = !_findInFinderDlg.isCreated();
_findInFinderDlg.doDialog(launcher, _nativeLangSpeaker.isRTL()); _findInFinderDlg.doDialog(launcher, _nativeLangSpeaker.isRTL());
_pEditView->getGenericSelectedText(str.get(), strSize); _findReplaceDlg.setSearchTextWithSettings();
_findReplaceDlg.setSearchText(str.get());
setFindReplaceFolderFilter(NULL, NULL); setFindReplaceFolderFilter(NULL, NULL);
if (isFirstTime) if (isFirstTime)
@ -1028,9 +1011,15 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
wchar_t *pTchar = reinterpret_cast<wchar_t *>(lParam); wchar_t *pTchar = reinterpret_cast<wchar_t *>(lParam);
if (message == NPPM_GETCURRENTWORD) if (message == NPPM_GETCURRENTWORD)
_pEditView->getGenericSelectedText(str.get(), strSize); {
auto txtW = _pEditView->getSelectedTextToWChar();
if (txtW)
wcscpy_s(str.get(), strSize, txtW);
}
else if (message == NPPM_GETCURRENTLINESTR) else if (message == NPPM_GETCURRENTLINESTR)
{
_pEditView->getLine(_pEditView->getCurrentLineNumber(), str.get(), strSize); _pEditView->getLine(_pEditView->getCurrentLineNumber(), str.get(), strSize);
}
// For the compatibility reason, if wParam is 0, then we assume the size of wstring buffer (lParam) is large enough. // For the compatibility reason, if wParam is 0, then we assume the size of wstring buffer (lParam) is large enough.
// otherwise we check if the wstring buffer size is enough for the wstring to copy. // otherwise we check if the wstring buffer size is enough for the wstring to copy.
@ -1060,7 +1049,10 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
int hasSlash = 0; int hasSlash = 0;
_pEditView->getGenericSelectedText(str.get(), strSize); // this is either the selected text, or the word under the cursor if there is no selection auto txtW = _pEditView->getSelectedTextToWChar(); // this is either the selected text, or the word under the cursor if there is no selection
if (txtW)
wcscpy_s(str.get(), strSize, txtW);
hasSlash = FALSE; hasSlash = FALSE;
for (int i = 0; str[i] != 0; i++) for (int i = 0; str[i] != 0; i++)
if (CharacterIs(str[i], L"\\/")) if (CharacterIs(str[i], L"\\/"))
@ -3218,6 +3210,23 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
return settingsOnCloudPath.length(); return settingsOnCloudPath.length();
} }
case NPPM_GETNPPSETTINGSDIRPATH:
{
// get the path (-settingsDir, Cloud directory, AppData or NppDir selection handled by _userPath, returned by .getUserPath())
wstring settingsDirPath = nppParam.getUserPath();
// if the LPARAM is a big enough non-null pointer, populate that memory with the path string
if (lParam != 0)
{
if (settingsDirPath.length() >= static_cast<size_t>(wParam))
return 0;
lstrcpy(reinterpret_cast<wchar_t*>(lParam), settingsDirPath.c_str());
}
// the message returns the string length
return settingsDirPath.length();
}
case NPPM_SETLINENUMBERWIDTHMODE: case NPPM_SETLINENUMBERWIDTHMODE:
{ {
if (lParam != LINENUMWIDTH_DYNAMIC && lParam != LINENUMWIDTH_CONSTANT) if (lParam != LINENUMWIDTH_DYNAMIC && lParam != LINENUMWIDTH_CONSTANT)

View File

@ -439,7 +439,7 @@ void Notepad_plus::command(int id)
auto pBinText = std::make_unique<char[]>(strSize); auto pBinText = std::make_unique<char[]>(strSize);
std::fill_n(pBinText.get(), strSize, '\0'); std::fill_n(pBinText.get(), strSize, '\0');
_pEditView->getSelectedText(pBinText.get(), textLen + 1); _pEditView->getSelectedTextToMultiChar(pBinText.get(), textLen + 1);
// Open the clipboard and empty it. // Open the clipboard and empty it.
if (!::OpenClipboard(NULL)) if (!::OpenClipboard(NULL))
@ -1356,16 +1356,6 @@ void Notepad_plus::command(int id)
case IDM_SEARCH_REPLACE : case IDM_SEARCH_REPLACE :
case IDM_SEARCH_MARK : case IDM_SEARCH_MARK :
{ {
const int strSize = FINDREPLACE_MAXLENGTH;
auto str = std::make_unique<wchar_t[]>(strSize);
std::fill_n(str.get(), strSize, L'\0');
const NppGUI& nppGui = (NppParameters::getInstance()).getNppGUI();
if (nppGui._fillFindFieldWithSelected)
{
_pEditView->getGenericSelectedText(str.get(), strSize, nppGui._fillFindFieldSelectCaret);
}
bool isFirstTime = !_findReplaceDlg.isCreated(); bool isFirstTime = !_findReplaceDlg.isCreated();
DIALOG_TYPE dlgID = FIND_DLG; DIALOG_TYPE dlgID = FIND_DLG;
@ -1375,13 +1365,7 @@ void Notepad_plus::command(int id)
dlgID = MARK_DLG; dlgID = MARK_DLG;
_findReplaceDlg.doDialog(dlgID, _nativeLangSpeaker.isRTL()); _findReplaceDlg.doDialog(dlgID, _nativeLangSpeaker.isRTL());
if (nppGui._fillFindFieldWithSelected) _findReplaceDlg.setSearchTextWithSettings();
{
if (lstrlen(str.get()) <= FINDREPLACE_INSELECTION_THRESHOLD_DEFAULT)
{
_findReplaceDlg.setSearchText(str.get());
}
}
setFindReplaceFolderFilter(NULL, NULL); setFindReplaceFolderFilter(NULL, NULL);
@ -1398,10 +1382,6 @@ void Notepad_plus::command(int id)
case IDM_SEARCH_FINDINCREMENT : case IDM_SEARCH_FINDINCREMENT :
{ {
const int strSize = FINDREPLACE_MAXLENGTH;
auto str = std::make_unique<wchar_t[]>(strSize);
std::fill_n(str.get(), strSize, L'\0');
static bool isFirstTime = true; static bool isFirstTime = true;
if (isFirstTime) if (isFirstTime)
{ {
@ -1409,9 +1389,9 @@ void Notepad_plus::command(int id)
isFirstTime = false; isFirstTime = false;
} }
_pEditView->getGenericSelectedText(str.get(), strSize, false); auto str = _pEditView->getSelectedTextToWChar(false);
if (0 != str[0]) // the selected text is not empty, then use it if (str) // the selected text is not empty, then use it
_incrementFindDlg.setSearchText(str.get(), _pEditView->getCurrentBuffer()->getUnicodeMode() != uni8Bit); _incrementFindDlg.setSearchText(str, _pEditView->getCurrentBuffer()->getUnicodeMode() != uni8Bit);
_incrementFindDlg.display(); _incrementFindDlg.display();
} }
@ -1459,13 +1439,11 @@ void Notepad_plus::command(int id)
if (isFirstTime) if (isFirstTime)
_findReplaceDlg.doDialog(FIND_DLG, _nativeLangSpeaker.isRTL(), false); _findReplaceDlg.doDialog(FIND_DLG, _nativeLangSpeaker.isRTL(), false);
const int strSize = FINDREPLACE_MAXLENGTH; const wchar_t* str = _findReplaceDlg.setSearchTextWithSettings();
auto str = std::make_unique<wchar_t[]>(strSize); if (!str) return;
std::fill_n(str.get(), strSize, L'\0');
_findReplaceDlg._env->_str2Search = str;
_pEditView->getGenericSelectedText(str.get(), strSize);
_findReplaceDlg.setSearchText(str.get());
_findReplaceDlg._env->_str2Search = str.get();
setFindReplaceFolderFilter(NULL, NULL); setFindReplaceFolderFilter(NULL, NULL);
if (isFirstTime) if (isFirstTime)
_nativeLangSpeaker.changeFindReplaceDlgLang(_findReplaceDlg); _nativeLangSpeaker.changeFindReplaceDlgLang(_findReplaceDlg);
@ -1475,7 +1453,7 @@ void Notepad_plus::command(int id)
op._whichDirection = (id == IDM_SEARCH_SETANDFINDNEXT?DIR_DOWN:DIR_UP); op._whichDirection = (id == IDM_SEARCH_SETANDFINDNEXT?DIR_DOWN:DIR_UP);
FindStatus status = FSNoMessage; FindStatus status = FSNoMessage;
_findReplaceDlg.processFindNext(str.get(), &op, &status); _findReplaceDlg.processFindNext(str, &op, &status);
if (status == FSEndReached) if (status == FSEndReached)
{ {
wstring msg = _nativeLangSpeaker.getLocalizedStrFromID("find-status-end-reached", FIND_STATUS_END_REACHED_TEXT); wstring msg = _nativeLangSpeaker.getLocalizedStrFromID("find-status-end-reached", FIND_STATUS_END_REACHED_TEXT);
@ -1514,10 +1492,8 @@ void Notepad_plus::command(int id)
case IDM_SEARCH_VOLATILE_FINDNEXT : case IDM_SEARCH_VOLATILE_FINDNEXT :
case IDM_SEARCH_VOLATILE_FINDPREV : case IDM_SEARCH_VOLATILE_FINDPREV :
{ {
const int strSize = FINDREPLACE_MAXLENGTH; auto str = _pEditView->getSelectedTextToWChar();
auto str = std::make_unique<wchar_t[]>(strSize); if (!str) return;
std::fill_n(str.get(), strSize, L'\0');
_pEditView->getGenericSelectedText(str.get(), strSize);
FindOption op; FindOption op;
op._isMatchCase = false; op._isMatchCase = false;
@ -1527,7 +1503,7 @@ void Notepad_plus::command(int id)
op._whichDirection = (id == IDM_SEARCH_VOLATILE_FINDNEXT ? DIR_DOWN : DIR_UP); op._whichDirection = (id == IDM_SEARCH_VOLATILE_FINDNEXT ? DIR_DOWN : DIR_UP);
FindStatus status = FSNoMessage; FindStatus status = FSNoMessage;
_findReplaceDlg.processFindNext(str.get(), &op, &status); _findReplaceDlg.processFindNext(str, &op, &status);
if (status == FSEndReached) if (status == FSEndReached)
{ {
wstring msg = _nativeLangSpeaker.getLocalizedStrFromID("find-status-end-reached", FIND_STATUS_END_REACHED_TEXT); wstring msg = _nativeLangSpeaker.getLocalizedStrFromID("find-status-end-reached", FIND_STATUS_END_REACHED_TEXT);
@ -1559,26 +1535,11 @@ void Notepad_plus::command(int id)
else // (id == IDM_SEARCH_MARKALLEXT5) else // (id == IDM_SEARCH_MARKALLEXT5)
styleID = SCE_UNIVERSAL_FOUND_STYLE_EXT5; styleID = SCE_UNIVERSAL_FOUND_STYLE_EXT5;
const int strSize = FINDREPLACE_MAXLENGTH; auto selectedText = _pEditView->getSelectedTextToWChar(true);
auto selectedText = std::make_unique<wchar_t[]>(strSize);
std::fill_n(selectedText.get(), strSize, L'\0');
auto wordOnCaret = std::make_unique<wchar_t[]>(strSize); if (selectedText)
std::fill_n(wordOnCaret.get(), strSize, L'\0');
_pEditView->getGenericSelectedText(selectedText.get(), strSize, false);
_pEditView->getGenericWordOnCaretPos(wordOnCaret.get(), strSize);
if (selectedText[0] == '\0')
{ {
if (lstrlen(wordOnCaret.get()) > 0) _findReplaceDlg.markAll(selectedText, styleID);
{
_findReplaceDlg.markAll(wordOnCaret.get(), styleID);
}
}
else
{
_findReplaceDlg.markAll(selectedText.get(), styleID);
} }
} }
break; break;
@ -3505,20 +3466,16 @@ void Notepad_plus::command(int id)
case IDM_ABOUT: case IDM_ABOUT:
{ {
bool doAboutDlg = false; bool doAboutDlg = false;
const int maxSelLen = 64;
auto textLen = _pEditView->execute(SCI_GETSELTEXT, 0, 0); auto textLen = _pEditView->execute(SCI_GETSELTEXT, 0, 0);
if (textLen <= 0) if (textLen <= 0)
doAboutDlg = true; doAboutDlg = true;
if (textLen > maxSelLen)
doAboutDlg = true;
if (!doAboutDlg) if (!doAboutDlg)
{ {
char author[maxSelLen+1] = ""; int iQuote = -1;
_pEditView->getSelectedText(author, maxSelLen + 1); auto authorW = _pEditView->getSelectedTextToWChar();
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); if (authorW)
const wchar_t * authorW = wmc.char2wchar(author, _nativeLangSpeaker.getLangEncoding()); iQuote = getQuoteIndexFrom(authorW);
int iQuote = getQuoteIndexFrom(authorW);
if (iQuote == -1) if (iQuote == -1)
{ {

View File

@ -683,9 +683,12 @@ bool Notepad_plus::doSave(BufferID id, const wchar_t * filename, bool isCopy)
} }
else if (res == SavingStatus::SaveWritingFailed) else if (res == SavingStatus::SaveWritingFailed)
{ {
wstring errorMessage = GetLastErrorAsString(GetLastError()); if (!(NppParameters::getInstance()).isEndSessionCritical()) // can we report to the user?
{
wstring errorMessage = GetLastErrorAsString(::GetLastError());
::MessageBox(_pPublicInterface->getHSelf(), errorMessage.c_str(), L"Save failed", MB_OK | MB_ICONWARNING); ::MessageBox(_pPublicInterface->getHSelf(), errorMessage.c_str(), L"Save failed", MB_OK | MB_ICONWARNING);
} }
}
else if (res == SavingStatus::SaveOpenFailed) else if (res == SavingStatus::SaveOpenFailed)
{ {
Buffer* buf = MainFileManager.getBufferByID(id); Buffer* buf = MainFileManager.getBufferByID(id);

View File

@ -420,8 +420,8 @@ BOOL Notepad_plus::notify(SCNotification *notification)
{ {
if (nppGui._smartHiliteOnAnotherView) if (nppGui._smartHiliteOnAnotherView)
{ {
wchar_t selectedText[1024]; auto selectedText = _pEditView->getSelectedTextToWChar(false);
_pEditView->getGenericSelectedText(selectedText, sizeof(selectedText) / sizeof(wchar_t), false); if (selectedText)
_smartHighlighter.highlightViewWithWord(notifyView, selectedText); _smartHighlighter.highlightViewWithWord(notifyView, selectedText);
} }
break; break;

View File

@ -2649,13 +2649,15 @@ void NppParameters::feedColumnEditorParameters(TiXmlNode *node)
if (strVal) if (strVal)
{ {
if (lstrcmp(strVal, L"hex") == 0) if (lstrcmp(strVal, L"hex") == 0)
_columnEditParam._formatChoice = 1; _columnEditParam._formatChoice = BASE_16;
else if (lstrcmp(strVal, L"hexuc") == 0)
_columnEditParam._formatChoice = BASE_16_UPPERCASE;
else if (lstrcmp(strVal, L"oct") == 0) else if (lstrcmp(strVal, L"oct") == 0)
_columnEditParam._formatChoice = 2; _columnEditParam._formatChoice = BASE_08;
else if (lstrcmp(strVal, L"bin") == 0) else if (lstrcmp(strVal, L"bin") == 0)
_columnEditParam._formatChoice = 3; _columnEditParam._formatChoice = BASE_02;
else // "dec" else // "dec"
_columnEditParam._formatChoice = 0; _columnEditParam._formatChoice = BASE_10;
} }
strVal = (childNode->ToElement())->Attribute(L"leadingChoice"); strVal = (childNode->ToElement())->Attribute(L"leadingChoice");
@ -4370,11 +4372,13 @@ bool NppParameters::writeColumnEditorSettings() const
(numberNode.ToElement())->SetAttribute(L"increase", _columnEditParam._increaseNum); (numberNode.ToElement())->SetAttribute(L"increase", _columnEditParam._increaseNum);
(numberNode.ToElement())->SetAttribute(L"repeat", _columnEditParam._repeatNum); (numberNode.ToElement())->SetAttribute(L"repeat", _columnEditParam._repeatNum);
wstring format = L"dec"; wstring format = L"dec";
if (_columnEditParam._formatChoice == 1) if (_columnEditParam._formatChoice == BASE_16)
format = L"hex"; format = L"hex";
else if (_columnEditParam._formatChoice == 2) else if (_columnEditParam._formatChoice == BASE_16_UPPERCASE)
format = L"hexuc";
else if (_columnEditParam._formatChoice == BASE_08)
format = L"oct"; format = L"oct";
else if (_columnEditParam._formatChoice == 3) else if (_columnEditParam._formatChoice == BASE_02)
format = L"bin"; format = L"bin";
(numberNode.ToElement())->SetAttribute(L"formatChoice", format); (numberNode.ToElement())->SetAttribute(L"formatChoice", format);
wstring leading = L"none"; wstring leading = L"none";
@ -6181,6 +6185,17 @@ void NppParameters::feedGUIParameters(TiXmlNode *node)
_nppGUI._inSelectionAutocheckThreshold = FINDREPLACE_INSELECTION_THRESHOLD_DEFAULT; _nppGUI._inSelectionAutocheckThreshold = FINDREPLACE_INSELECTION_THRESHOLD_DEFAULT;
} }
int fillFindWhatThresh;
if (element->Attribute(L"fillFindWhatThreshold", &fillFindWhatThresh) &&
(fillFindWhatThresh >= 1 && fillFindWhatThresh <= FINDREPLACE_MAXLENGTH - 1))
{
_nppGUI._fillFindWhatThreshold = fillFindWhatThresh;
}
else
{
_nppGUI._fillFindWhatThreshold = FILL_FINDWHAT_THRESHOLD_DEFAULT;
}
const wchar_t* optFillDirFieldFromActiveDoc = element->Attribute(L"fillDirFieldFromActiveDoc"); const wchar_t* optFillDirFieldFromActiveDoc = element->Attribute(L"fillDirFieldFromActiveDoc");
if (optFillDirFieldFromActiveDoc) if (optFillDirFieldFromActiveDoc)
{ {
@ -7823,6 +7838,7 @@ void NppParameters::createXmlTreeFromGUIParams()
GUIConfigElement->SetAttribute(L"confirmReplaceInAllOpenDocs", _nppGUI._confirmReplaceInAllOpenDocs ? L"yes" : L"no"); GUIConfigElement->SetAttribute(L"confirmReplaceInAllOpenDocs", _nppGUI._confirmReplaceInAllOpenDocs ? L"yes" : L"no");
GUIConfigElement->SetAttribute(L"replaceStopsWithoutFindingNext", _nppGUI._replaceStopsWithoutFindingNext ? L"yes" : L"no"); GUIConfigElement->SetAttribute(L"replaceStopsWithoutFindingNext", _nppGUI._replaceStopsWithoutFindingNext ? L"yes" : L"no");
GUIConfigElement->SetAttribute(L"inSelectionAutocheckThreshold", _nppGUI._inSelectionAutocheckThreshold); GUIConfigElement->SetAttribute(L"inSelectionAutocheckThreshold", _nppGUI._inSelectionAutocheckThreshold);
GUIConfigElement->SetAttribute(L"fillFindWhatThreshold", _nppGUI._fillFindWhatThreshold);
GUIConfigElement->SetAttribute(L"fillDirFieldFromActiveDoc", _nppGUI._fillDirFieldFromActiveDoc ? L"yes" : L"no"); GUIConfigElement->SetAttribute(L"fillDirFieldFromActiveDoc", _nppGUI._fillDirFieldFromActiveDoc ? L"yes" : L"no");
} }

View File

@ -164,7 +164,10 @@ const int COPYDATA_FULL_CMDLINE = 3;
#define NPP_STYLING_FILESIZE_LIMIT_DEFAULT (200 * 1024 * 1024) // 200MB+ file won't be styled #define NPP_STYLING_FILESIZE_LIMIT_DEFAULT (200 * 1024 * 1024) // 200MB+ file won't be styled
#define FINDREPLACE_MAXLENGTH 16384 // the maximum length of the string (decrease 1 for '\0') to search in the editor
const int FINDREPLACE_INSELECTION_THRESHOLD_DEFAULT = 1024; const int FINDREPLACE_INSELECTION_THRESHOLD_DEFAULT = 1024;
const int FILL_FINDWHAT_THRESHOLD_DEFAULT = 1024;
const wchar_t fontSizeStrs[][3] = {L"", L"5", L"6", L"7", L"8", L"9", L"10", L"11", L"12", L"14", L"16", L"18", L"20", L"22", L"24", L"26", L"28"}; const wchar_t fontSizeStrs[][3] = {L"", L"5", L"6", L"7", L"8", L"9", L"10", L"11", L"12", L"14", L"16", L"18", L"20", L"22", L"24", L"26", L"28"};
@ -906,6 +909,7 @@ struct NppGUI final
bool _confirmReplaceInAllOpenDocs = true; bool _confirmReplaceInAllOpenDocs = true;
bool _replaceStopsWithoutFindingNext = false; bool _replaceStopsWithoutFindingNext = false;
int _inSelectionAutocheckThreshold = FINDREPLACE_INSELECTION_THRESHOLD_DEFAULT; int _inSelectionAutocheckThreshold = FINDREPLACE_INSELECTION_THRESHOLD_DEFAULT;
int _fillFindWhatThreshold = FILL_FINDWHAT_THRESHOLD_DEFAULT;
bool _fillDirFieldFromActiveDoc = false; bool _fillDirFieldFromActiveDoc = false;
bool _muteSounds = false; bool _muteSounds = false;
bool _enableFoldCmdToggable = false; bool _enableFoldCmdToggable = false;
@ -1320,7 +1324,7 @@ struct ColumnEditorParam final
int _initialNum = -1; int _initialNum = -1;
int _increaseNum = -1; int _increaseNum = -1;
int _repeatNum = -1; int _repeatNum = -1;
int _formatChoice = 0; // 0:Dec 1:Hex 2:Oct 3:Bin int _formatChoice = 0; // 0:Dec 1:Hex 2:Oct 3:Bin 4:HexUpperCase
leadingChoice _leadingChoice = noneLeading; leadingChoice _leadingChoice = noneLeading;
}; };

View File

@ -65,6 +65,15 @@ namespace // anonymous
return defvalue; // fallback unknown return defvalue; // fallback unknown
} }
// local helper to get the current system time in milliseconds since Unix epoch (January 1, 1970)
ULONGLONG GetUnixSysTimeInMilliseconds()
{
FILETIME ft;
::GetSystemTimeAsFileTime(&ft); // 100-nanosecond intervals since January 1, 1601 (UTC)
ULONGLONG ullTime = (((ULONGLONG)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
const ULONGLONG EPOCH_DIFF = 116444736000000000ULL; // difference between Jan 1, 1601 and Jan 1, 1970 in 100-ns intervals
return (ullTime - EPOCH_DIFF) / 10000; // subtract the diff and convert to milliseconds
}
} // anonymous namespace } // anonymous namespace
using namespace std; using namespace std;
@ -1070,21 +1079,23 @@ bool FileManager::reloadBufferDeferred(BufferID id)
bool FileManager::deleteFile(BufferID id) bool FileManager::deleteFile(BufferID id)
{ {
if (id == BUFFER_INVALID)
return false;
const Buffer* buf = getBufferByID(id); const Buffer* buf = getBufferByID(id);
wstring fileNamePath = buf->getFullPathName(); wstring fileNamePath = buf->getFullPathName();
if (!doesFileExist(fileNamePath.c_str()))
return false;
// Make sure to form a string with double '\0' terminator. // Make sure to form a string with double '\0' terminator.
fileNamePath.append(1, '\0'); fileNamePath.append(1, '\0');
if (!doesFileExist(fileNamePath.c_str()))
return false;
SHFILEOPSTRUCT fileOpStruct = {}; SHFILEOPSTRUCT fileOpStruct = {};
fileOpStruct.hwnd = NULL; fileOpStruct.hwnd = NULL;
fileOpStruct.pFrom = fileNamePath.c_str(); fileOpStruct.pFrom = fileNamePath.c_str();
fileOpStruct.pTo = NULL; fileOpStruct.pTo = NULL;
fileOpStruct.wFunc = FO_DELETE; fileOpStruct.wFunc = FO_DELETE;
fileOpStruct.fFlags = FOF_ALLOWUNDO; fileOpStruct.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION; // FOF_NOCONFIRMATION - prevent possible redundant shell-dlg (Notepad++ uses its own delete-confirmation dlg)
fileOpStruct.fAnyOperationsAborted = false; fileOpStruct.fAnyOperationsAborted = false;
fileOpStruct.hNameMappings = NULL; fileOpStruct.hNameMappings = NULL;
fileOpStruct.lpszProgressTitle = NULL; fileOpStruct.lpszProgressTitle = NULL;
@ -1095,11 +1106,29 @@ bool FileManager::deleteFile(BufferID id)
bool FileManager::moveFile(BufferID id, const wchar_t* newFileName) bool FileManager::moveFile(BufferID id, const wchar_t* newFileName)
{ {
if (id == BUFFER_INVALID)
return false;
Buffer* buf = getBufferByID(id); Buffer* buf = getBufferByID(id);
const wchar_t* fileNamePath = buf->getFullPathName(); const wchar_t* fileNamePath = buf->getFullPathName();
if (::MoveFileEx(fileNamePath, newFileName, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH) == 0) if (!::MoveFileExW(fileNamePath, newFileName, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH))
{
if (::GetLastError() != ERROR_ACCESS_DENIED)
return false; return false;
// ERROR_ACCESS_DENIED, try to move elevated
// (notepad++.exe #UAC-MOVEFILE# original_file_path new_file_path)
wstring strCmdLineParams = NPP_UAC_MOVEFILE_SIGN;
strCmdLineParams += L" \"";
strCmdLineParams += fileNamePath;
strCmdLineParams += L"\" \"";
strCmdLineParams += newFileName;
strCmdLineParams += L"\"";
DWORD dwNppUacOpError = invokeNppUacOp(strCmdLineParams);
if (dwNppUacOpError != NO_ERROR)
return false;
}
buf->setFileName(newFileName); buf->setFileName(newFileName);
return true; return true;
} }
@ -1323,7 +1352,7 @@ SavingStatus FileManager::saveBuffer(BufferID id, const wchar_t* filename, bool
Buffer* buffer = getBufferByID(id); Buffer* buffer = getBufferByID(id);
bool isHiddenOrSys = false; bool isHiddenOrSys = false;
wchar_t fullpath[MAX_PATH] = { 0 }; wchar_t fullpath[MAX_PATH]{};
if (isWin32NamespacePrefixedFileName(filename)) if (isWin32NamespacePrefixedFileName(filename))
{ {
// use directly the raw file name, skip the GetFullPathName WINAPI // use directly the raw file name, skip the GetFullPathName WINAPI
@ -1338,7 +1367,7 @@ SavingStatus FileManager::saveBuffer(BufferID id, const wchar_t* filename, bool
} }
} }
wchar_t dirDest[MAX_PATH]; wchar_t dirDest[MAX_PATH]{};
wcscpy_s(dirDest, MAX_PATH, fullpath); wcscpy_s(dirDest, MAX_PATH, fullpath);
::PathRemoveFileSpecW(dirDest); ::PathRemoveFileSpecW(dirDest);
@ -1379,8 +1408,27 @@ SavingStatus FileManager::saveBuffer(BufferID id, const wchar_t* filename, bool
int encoding = buffer->getEncoding(); int encoding = buffer->getEncoding();
if (UnicodeConvertor.openFile(fullpath)) wstring strTempFile = L"";
if (!UnicodeConvertor.openFile(fullpath))
{ {
if (NppParameters::getInstance().isEndSessionCritical())
return SavingStatus::SaveOpenFailed; // cannot continue to the UAC-prompt at the Windows logoff/reboot/shutdown time
if (UnicodeConvertor.getLastFileErrorState() != ERROR_ACCESS_DENIED)
return SavingStatus::SaveOpenFailed; // cannot be solved by the UAC-prompt
// ERROR_ACCESS_DENIED, swap to temporary file copy for the UAC elevation way
wchar_t wszBuf[MAX_PATH + 1]{};
if (::GetTempPath(MAX_PATH, wszBuf) == 0)
return SavingStatus::SaveOpenFailed; // cannot continue
strTempFile = wszBuf;
strTempFile += L"npp-" + std::to_wstring(GetUnixSysTimeInMilliseconds()) + L".tmp"; // make unique temporary filename
if (!UnicodeConvertor.openFile(strTempFile.c_str()))
return SavingStatus::SaveOpenFailed; // cannot continue, weird
}
_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, buffer->_doc); //generate new document _pscratchTilla->execute(SCI_SETDOCPOINTER, 0, buffer->_doc); //generate new document
size_t lengthDoc = _pscratchTilla->getCurrentDocLen(); size_t lengthDoc = _pscratchTilla->getCurrentDocLen();
@ -1420,15 +1468,34 @@ SavingStatus FileManager::saveBuffer(BufferID id, const wchar_t* filename, bool
UnicodeConvertor.closeFile(); UnicodeConvertor.closeFile();
if (isHiddenOrSys && strTempFile.empty())
::SetFileAttributes(fullpath, attributes.dwFileAttributes);
// Error, we didn't write the entire document to disk. // Error, we didn't write the entire document to disk.
if (!isWrittenSuccessful) if (!isWrittenSuccessful)
{ {
_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, _scratchDocDefault); _pscratchTilla->execute(SCI_SETDOCPOINTER, 0, _scratchDocDefault);
if (!strTempFile.empty())
::DeleteFileW(strTempFile.c_str());
return SavingStatus::SaveWritingFailed; return SavingStatus::SaveWritingFailed;
} }
if (isHiddenOrSys) if (!strTempFile.empty())
::SetFileAttributes(fullpath, attributes.dwFileAttributes); {
// elevated saving/overwriting of the original file by the help of the tempfile
// (notepad++.exe #UAC-SAVE# temp_file_path dest_file_path)
wstring strCmdLineParams = NPP_UAC_SAVE_SIGN;
strCmdLineParams += L" \"" + strTempFile + L"\" \"";
strCmdLineParams += fullpath;
strCmdLineParams += L"\"";
DWORD dwNppUacOpError = invokeNppUacOp(strCmdLineParams);
if (dwNppUacOpError != NO_ERROR)
{
::DeleteFileW(strTempFile.c_str()); // ensure no failed op remnant
::SetLastError(dwNppUacOpError); // set that as our current thread one for reporting later
return SavingStatus::SaveWritingFailed;
}
}
if (isCopy) // "Save a Copy As..." command if (isCopy) // "Save a Copy As..." command
{ {
@ -1460,7 +1527,6 @@ SavingStatus FileManager::saveBuffer(BufferID id, const wchar_t* filename, bool
buffer->setStatus(DOC_REGULAR); buffer->setStatus(DOC_REGULAR);
buffer->checkFileState(); buffer->checkFileState();
_pscratchTilla->execute(SCI_SETSAVEPOINT); _pscratchTilla->execute(SCI_SETSAVEPOINT);
_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, _scratchDocDefault); _pscratchTilla->execute(SCI_SETDOCPOINTER, 0, _scratchDocDefault);
@ -1474,11 +1540,6 @@ SavingStatus FileManager::saveBuffer(BufferID id, const wchar_t* filename, bool
return SavingStatus::SaveOK; return SavingStatus::SaveOK;
} }
else
{
return SavingStatus::SaveOpenFailed;
}
}
size_t FileManager::nextUntitledNewNumber() const size_t FileManager::nextUntitledNewNumber() const
{ {
@ -2023,7 +2084,23 @@ BufferID FileManager::getBufferFromDocument(Document doc)
bool FileManager::createEmptyFile(const wchar_t* path) bool FileManager::createEmptyFile(const wchar_t* path)
{ {
Win32_IO_File file(path); Win32_IO_File file(path);
return file.isOpened(); if (!file.isOpened())
{
if (file.getLastErrorCode() != ERROR_ACCESS_DENIED)
return false;
// ERROR_ACCESS_DENIED, try the same but elevated
// (notepad++.exe #UAC-CREATEEMPTYFILE# new_empty_file_path)
wstring strCmdLineParams = NPP_UAC_CREATEEMPTYFILE_SIGN;
strCmdLineParams += L" \"";
strCmdLineParams += path;
strCmdLineParams += L"\"";
DWORD dwNppUacOpError = invokeNppUacOp(strCmdLineParams);
if (dwNppUacOpError != NO_ERROR)
return false;
}
return true;
} }

View File

@ -53,7 +53,7 @@ wstring getTextFromCombo(HWND hCombo)
auto str = std::make_unique<wchar_t[]>(strSize); auto str = std::make_unique<wchar_t[]>(strSize);
std::fill_n(str.get(), strSize, L'\0'); std::fill_n(str.get(), strSize, L'\0');
::SendMessage(hCombo, WM_GETTEXT, FINDREPLACE_MAXLENGTH - 1, reinterpret_cast<LPARAM>(str.get())); ::SendMessage(hCombo, WM_GETTEXT, FINDREPLACE_MAXLENGTH, reinterpret_cast<LPARAM>(str.get()));
return wstring(str.get()); return wstring(str.get());
} }
@ -63,7 +63,7 @@ void delLeftWordInEdit(HWND hEdit)
auto str = std::make_unique<wchar_t[]>(strSize); auto str = std::make_unique<wchar_t[]>(strSize);
std::fill_n(str.get(), strSize, L'\0'); std::fill_n(str.get(), strSize, L'\0');
::SendMessage(hEdit, WM_GETTEXT, FINDREPLACE_MAXLENGTH - 1, reinterpret_cast<LPARAM>(str.get())); ::SendMessage(hEdit, WM_GETTEXT, FINDREPLACE_MAXLENGTH, reinterpret_cast<LPARAM>(str.get()));
WORD cursor = 0; WORD cursor = 0;
::SendMessage(hEdit, EM_GETSEL, (WPARAM)&cursor, 0); ::SendMessage(hEdit, EM_GETSEL, (WPARAM)&cursor, 0);
WORD wordstart = cursor; WORD wordstart = cursor;
@ -248,6 +248,20 @@ void Searching::displaySectionCentered(size_t posStart, size_t posEnd, Scintilla
// Adjust so that we see the entire match; primarily horizontally // Adjust so that we see the entire match; primarily horizontally
pEditView->execute(SCI_SCROLLRANGE, posStart, posEnd); pEditView->execute(SCI_SCROLLRANGE, posStart, posEnd);
// make sure won't start/end the selection in the middle of a multibyte character,
// or in between a CR/LF pair for Windows files
// (needed for stale search-results where user has made doc edits after the search)
if (posStart > 0)
{
posStart = pEditView->execute(SCI_POSITIONBEFORE, posStart);
posStart = pEditView->execute(SCI_POSITIONAFTER, posStart);
}
if (posEnd > 0)
{
posEnd = pEditView->execute(SCI_POSITIONBEFORE, posEnd);
posEnd = pEditView->execute(SCI_POSITIONAFTER, posEnd);
}
// Move cursor to end of result and select result // Move cursor to end of result and select result
pEditView->execute(SCI_GOTOPOS, posEnd); pEditView->execute(SCI_GOTOPOS, posEnd);
pEditView->execute(SCI_SETANCHOR, posStart); pEditView->execute(SCI_SETANCHOR, posStart);
@ -1565,8 +1579,8 @@ intptr_t CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA
HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT);
HWND hReplaceCombo = ::GetDlgItem(_hSelf, IDREPLACEWITH); HWND hReplaceCombo = ::GetDlgItem(_hSelf, IDREPLACEWITH);
::SendMessage(hFindCombo, CB_LIMITTEXT, FINDREPLACE_MAXLENGTH - 1, 0); ::SendMessage(hFindCombo, CB_LIMITTEXT, FINDREPLACE_MAXLENGTH * 2 - 1, 0);
::SendMessage(hReplaceCombo, CB_LIMITTEXT, FINDREPLACE_MAXLENGTH - 1, 0); ::SendMessage(hReplaceCombo, CB_LIMITTEXT, FINDREPLACE_MAXLENGTH * 2 - 1, 0);
HWND hFiltersCombo = ::GetDlgItem(_hSelf, IDD_FINDINFILES_FILTERS_COMBO); HWND hFiltersCombo = ::GetDlgItem(_hSelf, IDD_FINDINFILES_FILTERS_COMBO);
HWND hDirCombo = ::GetDlgItem(_hSelf, IDD_FINDINFILES_DIR_COMBO); HWND hDirCombo = ::GetDlgItem(_hSelf, IDD_FINDINFILES_DIR_COMBO);
@ -1958,20 +1972,23 @@ intptr_t CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA
if (HIWORD(wParam) == CBN_EDITUPDATE) if (HIWORD(wParam) == CBN_EDITUPDATE)
{ {
HWND hComboBox = ::GetDlgItem(_hSelf, LOWORD(wParam)); HWND hComboBox = ::GetDlgItem(_hSelf, LOWORD(wParam));
LRESULT length = ::GetWindowTextLength(hComboBox); HWND hEdit = GetWindow(hComboBox, GW_CHILD);
if (!hEdit)
return FALSE;
static int maxLength = (int)SendMessage(hEdit, EM_GETLIMITTEXT, 0, 0);
LRESULT length = ::GetWindowTextLength(hEdit);
if (length >= FINDREPLACE_MAXLENGTH - 1) if (length >= maxLength) // should be (FINDREPLACE_MAXLENGTH * 2 - 1)
{ {
if (!_maxLenOnSearchTip.isValid()) // Create the tooltip and add the tool ONLY ONCE if (!_maxLenOnSearchTip.isValid()) // Create the tooltip and add the tool ONLY ONCE
{ {
NativeLangSpeaker* pNativeSpeaker = nppParamInst.getNativeLangSpeaker(); NativeLangSpeaker* pNativeSpeaker = nppParamInst.getNativeLangSpeaker();
wstring tip = pNativeSpeaker->getLocalizedStrFromID("max-len-on-search-tip", L"Only $INT_REPLACE$ characters are allowed for the find/replace text length - your input could be truncated, and it won't be saved for the next session."); wstring tip = pNativeSpeaker->getLocalizedStrFromID("len-limit-exceeded-tip", L"Length limit exceeded: Your input may exceed the limit allowed and could have been truncated, and it won't be saved for the next session.");
tip = stringReplace(tip, L"$INT_REPLACE$", std::to_wstring(FINDREPLACE_MAXLENGTH - 1));
static wstring maxLenOnSearchTip = tip; static wstring maxLenOnSearchTip = tip;
bool isSuccessful = _maxLenOnSearchTip.init(_hInst, hComboBox, _hSelf, maxLenOnSearchTip.c_str(), _isRTL); bool isSuccessful = _maxLenOnSearchTip.init(_hInst, hComboBox, _hSelf, maxLenOnSearchTip.c_str(), _isRTL, 0, 170);
if (!isSuccessful) if (!isSuccessful)
{ {
@ -1980,19 +1997,39 @@ intptr_t CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA
NppDarkMode::setDarkTooltips(_maxLenOnSearchTip.getTipHandle(), NppDarkMode::ToolTipsType::tooltip); NppDarkMode::setDarkTooltips(_maxLenOnSearchTip.getTipHandle(), NppDarkMode::ToolTipsType::tooltip);
} }
_maxLenOnSearchTip.show(); _maxLenOnSearchTip.show(ControlInfoTip::showPosition::beginning);
}
else if (length > FINDREPLACE_MAXLENGTH - 1)
{
if (!_maxLenOnSearchTip.isValid()) // Create the tooltip and add the tool ONLY ONCE
{
NativeLangSpeaker* pNativeSpeaker = nppParamInst.getNativeLangSpeaker();
wstring tip = pNativeSpeaker->getLocalizedStrFromID("max-len-on-search-tip", L"Your input may exceed the limit allowed and could have been truncated, and it won't be saved for the next session.");
static wstring maxLenOnSearchTip = tip;
bool isSuccessful = _maxLenOnSearchTip.init(_hInst, hComboBox, _hSelf, maxLenOnSearchTip.c_str(), _isRTL, 0, 170);
if (!isSuccessful)
{
return FALSE;
}
NppDarkMode::setDarkTooltips(_maxLenOnSearchTip.getTipHandle(), NppDarkMode::ToolTipsType::tooltip);
}
_maxLenOnSearchTip.show(ControlInfoTip::showPosition::beginning);
} }
else if (length >= FINDREPLACE_MAXLENGTH2SAVE - 1) // FINDREPLACE_MAXLENGTH2SAVE < length < FINDREPLACE_MAXLENGTH else if (length >= FINDREPLACE_MAXLENGTH2SAVE - 1) // FINDREPLACE_MAXLENGTH2SAVE < length < FINDREPLACE_MAXLENGTH
{ {
if (!_maxLenOnSearchTip.isValid()) // Create the tooltip and add the tool ONLY ONCE if (!_maxLenOnSearchTip.isValid()) // Create the tooltip and add the tool ONLY ONCE
{ {
NativeLangSpeaker* pNativeSpeaker = nppParamInst.getNativeLangSpeaker(); NativeLangSpeaker* pNativeSpeaker = nppParamInst.getNativeLangSpeaker();
wstring tip = pNativeSpeaker->getLocalizedStrFromID("max-len-on-save-tip", L"This search input (> $INT_REPLACE$ characters) won't be saved for the next session"); wstring tip = pNativeSpeaker->getLocalizedStrFromID("max-len-on-save-tip", L"The length of your input is very long and may not be saved for your next session.");
tip = stringReplace(tip, L"$INT_REPLACE$", std::to_wstring(FINDREPLACE_MAXLENGTH2SAVE - 1));
static wstring maxLenOnSaveTip = tip; static wstring maxLenOnSaveTip = tip;
bool isSuccessful = _maxLenOnSearchTip.init(_hInst, hComboBox, _hSelf, maxLenOnSaveTip.c_str(), _isRTL); bool isSuccessful = _maxLenOnSearchTip.init(_hInst, hComboBox, _hSelf, maxLenOnSaveTip.c_str(), _isRTL, 0, 170);
if (!isSuccessful) if (!isSuccessful)
{ {
@ -2001,7 +2038,7 @@ intptr_t CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA
NppDarkMode::setDarkTooltips(_maxLenOnSearchTip.getTipHandle(), NppDarkMode::ToolTipsType::tooltip); NppDarkMode::setDarkTooltips(_maxLenOnSearchTip.getTipHandle(), NppDarkMode::ToolTipsType::tooltip);
} }
_maxLenOnSearchTip.show(); _maxLenOnSearchTip.show(ControlInfoTip::showPosition::beginning);
} }
else else
{ {
@ -4030,14 +4067,18 @@ int FindReplaceDlg::regexBackwardMsgBox()
return msgboxID; return msgboxID;
} }
void FindReplaceDlg::setSearchText(wchar_t * txt2find) void FindReplaceDlg::setSearchText(const wchar_t * txt2find)
{ {
HWND hCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); HWND hCombo = ::GetDlgItem(_hSelf, IDFINDWHAT);
if (txt2find && txt2find[0]) if (txt2find && txt2find[0])
{ {
// We got a valid search string // We got a valid search string
::SendMessage(hCombo, CB_SETCURSEL, static_cast<WPARAM>(-1), 0); // remove selection - to allow using down arrow to get to last searched word HWND hEdit = GetWindow(hCombo, GW_CHILD);
::SetDlgItemText(_hSelf, IDFINDWHAT, txt2find); if (hEdit)
{
::SendMessage(hEdit, EM_SETSEL, 0, static_cast<WPARAM>(-1)); // Select all text
::SendMessage(hEdit, EM_REPLACESEL, TRUE, (LPARAM)txt2find);
}
} }
::SendMessage(hCombo, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); // select all text - fast edit ::SendMessage(hCombo, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); // select all text - fast edit
} }
@ -4905,7 +4946,7 @@ LRESULT FAR PASCAL FindReplaceDlg::comboEditProc(HWND hwnd, UINT message, WPARAM
else if ((message == WM_KEYDOWN) && (wParam == VK_DOWN) && (::SendMessage(hwndCombo, CB_GETCURSEL, 0, 0) == CB_ERR)) else if ((message == WM_KEYDOWN) && (wParam == VK_DOWN) && (::SendMessage(hwndCombo, CB_GETCURSEL, 0, 0) == CB_ERR))
{ {
// down key on unselected combobox item -> store current edit text as draft // down key on unselected combobox item -> store current edit text as draft
::SendMessage(hwndCombo, WM_GETTEXT, FINDREPLACE_MAXLENGTH - 1, reinterpret_cast<LPARAM>(draftString.get())); ::SendMessage(hwndCombo, WM_GETTEXT, FINDREPLACE_MAXLENGTH, reinterpret_cast<LPARAM>(draftString.get()));
} }
else if ((message == WM_KEYDOWN) && (wParam == VK_UP) && (::SendMessage(hwndCombo, CB_GETCURSEL, 0, 0) == CB_ERR)) else if ((message == WM_KEYDOWN) && (wParam == VK_UP) && (::SendMessage(hwndCombo, CB_GETCURSEL, 0, 0) == CB_ERR))
{ {
@ -4917,11 +4958,38 @@ LRESULT FAR PASCAL FindReplaceDlg::comboEditProc(HWND hwnd, UINT message, WPARAM
{ {
// up key on top selected combobox item -> restore draft to edit text // up key on top selected combobox item -> restore draft to edit text
::SendMessage(hwndCombo, CB_SETCURSEL, WPARAM(-1), 0); ::SendMessage(hwndCombo, CB_SETCURSEL, WPARAM(-1), 0);
::SendMessage(hwndCombo, WM_SETTEXT, FINDREPLACE_MAXLENGTH - 1, reinterpret_cast<LPARAM>(draftString.get())); ::SendMessage(hwndCombo, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(draftString.get()));
::SendMessage(hwndCombo, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); ::SendMessage(hwndCombo, CB_SETEDITSEL, 0, MAKELPARAM(0, -1));
return 0; return 0;
} }
else if (message == WM_PASTE)
{
// needed to allow CR (i.e., multiline) into combobox text;
// (the default functionality terminates the paste at the first CR character)
HWND hParent = ::GetParent(hwndCombo);
HWND hFindWhatCombo = ::GetDlgItem(hParent, IDFINDWHAT);
HWND hReplaceWithCombo = ::GetDlgItem(hParent, IDREPLACEWITH);
if ((hwndCombo == hFindWhatCombo) || (hwndCombo == hReplaceWithCombo))
{
CLIPFORMAT cfColumnSelect = static_cast<CLIPFORMAT>(::RegisterClipboardFormat(L"MSDEVColumnSelect"));
if (!::IsClipboardFormatAvailable(cfColumnSelect))
{
wstring clipboardText = strFromClipboard();
if (!clipboardText.empty())
{
HWND hEdit = GetWindow(hwndCombo, GW_CHILD);
if (hEdit)
{
::SendMessage(hEdit, EM_REPLACESEL, TRUE, (LPARAM)clipboardText.c_str());
}
}
}
return 0;
}
}
return CallWindowProc(originalComboEditProc, hwnd, message, wParam, lParam); return CallWindowProc(originalComboEditProc, hwnd, message, wParam, lParam);
} }
@ -5312,7 +5380,7 @@ bool FindReplaceDlg::replaceInProjectsConfirmCheck()
return confirmed; return confirmed;
} }
bool FindReplaceDlg::replaceInOpenDocsConfirmCheck(void) bool FindReplaceDlg::replaceInOpenDocsConfirmCheck()
{ {
bool confirmed = false; bool confirmed = false;
@ -5330,6 +5398,26 @@ bool FindReplaceDlg::replaceInOpenDocsConfirmCheck(void)
return confirmed; return confirmed;
} }
// return NULL if nothing to set in find field.
// Otherwise return string pointer (wchar_t *) in which the selected text was copied.
// Note that the string pointer don't need to and should not be deallocated.
const wchar_t* FindReplaceDlg::setSearchTextWithSettings()
{
const NppGUI& nppGui = NppParameters::getInstance().getNppGUI();
if (nppGui._fillFindFieldWithSelected)
{
Sci_Position selStrCharNum = 0;
const wchar_t* selStr = (*_ppEditView)->getSelectedTextToWChar(nppGui._fillFindFieldSelectCaret, &selStrCharNum);
if (selStr && selStrCharNum <= nppGui._fillFindWhatThreshold)
{
setSearchText(selStr);
return selStr;
}
}
return nullptr;
}
wstring Finder::getHitsString(int count) const wstring Finder::getHitsString(int count) const
{ {
NativeLangSpeaker *pNativeSpeaker = (NppParameters::getInstance()).getNativeLangSpeaker(); NativeLangSpeaker *pNativeSpeaker = (NppParameters::getInstance()).getNativeLangSpeaker();
@ -6239,12 +6327,11 @@ void FindIncrementDlg::markSelectedTextInc(bool enable, FindOption *opt)
if (range.cpMin == range.cpMax) if (range.cpMin == range.cpMax)
return; return;
const int strSize = FINDREPLACE_MAXLENGTH; auto text2Find = (*(_pFRDlg->_ppEditView))->getSelectedTextToWChar(false); //do not expand selection (false)
auto text2Find = std::make_unique<wchar_t[]>(strSize); if (!text2Find)
std::fill_n(text2Find.get(), strSize, L'\0'); return;
(*(_pFRDlg->_ppEditView))->getGenericSelectedText(text2Find.get(), FINDREPLACE_MAXLENGTH, false); //do not expand selection (false) opt->_str2Search = text2Find;
opt->_str2Search = text2Find.get();
_pFRDlg->markAllInc(opt); _pFRDlg->markAllInc(opt);
} }

View File

@ -29,7 +29,6 @@
#define FIND_INVALID_REGULAR_EXPRESSION -2 #define FIND_INVALID_REGULAR_EXPRESSION -2
#define FINDREPLACE_MAXLENGTH 16384 // the maximum length of the string (decrease 1 for '\0') to search in the editor
#define FINDREPLACE_MAXLENGTH2SAVE 2048 // the maximum length of the string (decrease 1 for '\0') to save in the config.xml file #define FINDREPLACE_MAXLENGTH2SAVE 2048 // the maximum length of the string (decrease 1 for '\0') to save in the config.xml file
#define FINDTEMPSTRING_MAXSIZE 1024*1024 #define FINDTEMPSTRING_MAXSIZE 1024*1024
@ -288,7 +287,7 @@ public :
void replaceAllInOpenedDocs(); void replaceAllInOpenedDocs();
void findAllIn(InWhat op); void findAllIn(InWhat op);
void setSearchText(wchar_t * txt2find); void setSearchText(const wchar_t * txt2find);
void gotoNextFoundResult(int direction = 0) const { void gotoNextFoundResult(int direction = 0) const {
if (_pFinder) _pFinder->gotoNextFoundResult(direction); if (_pFinder) _pFinder->gotoNextFoundResult(direction);
@ -337,14 +336,13 @@ public :
_tab.getCurrentTitle(label, MAX_PATH); _tab.getCurrentTitle(label, MAX_PATH);
::SetWindowText(_hSelf, label); ::SetWindowText(_hSelf, label);
} }
void beginNewFilesSearch()
{ void beginNewFilesSearch() {
_pFinder->beginNewFilesSearch(); _pFinder->beginNewFilesSearch();
_pFinder->addSearchLine(getText2search().c_str()); _pFinder->addSearchLine(getText2search().c_str());
} }
void finishFilesSearch(int count, int searchedCount, bool searchedEntireNotSelection) void finishFilesSearch(int count, int searchedCount, bool searchedEntireNotSelection) {
{
_pFinder->finishFilesSearch(count, searchedCount, searchedEntireNotSelection, _env); _pFinder->finishFilesSearch(count, searchedCount, searchedEntireNotSelection, _env);
} }
@ -422,6 +420,7 @@ public :
DIALOG_TYPE getCurrentStatus() {return _currentStatus;}; DIALOG_TYPE getCurrentStatus() {return _currentStatus;};
Finder* getFinderFrom(HWND hwnd); Finder* getFinderFrom(HWND hwnd);
int regexBackwardMsgBox(); int regexBackwardMsgBox();
const wchar_t* setSearchTextWithSettings();
protected : protected :
void resizeDialogElements(); void resizeDialogElements();
@ -527,7 +526,7 @@ private:
void drawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); void drawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
bool replaceInFilesConfirmCheck(const std::wstring& directory, const std::wstring& fileTypes); bool replaceInFilesConfirmCheck(const std::wstring& directory, const std::wstring& fileTypes);
bool replaceInProjectsConfirmCheck(); bool replaceInProjectsConfirmCheck();
bool replaceInOpenDocsConfirmCheck(void); bool replaceInOpenDocsConfirmCheck();
ContextMenu _swapPopupMenu; ContextMenu _swapPopupMenu;
enum SwapButtonStatus {swap, down, up} _swapButtonStatus = swap; enum SwapButtonStatus {swap, down, up} _swapButtonStatus = swap;

View File

@ -2793,48 +2793,61 @@ char * ScintillaEditView::getWordOnCaretPos(char * txt, size_t size)
return getWordFromRange(txt, size, range.first, range.second); return getWordFromRange(txt, size, range.first, range.second);
} }
wchar_t * ScintillaEditView::getGenericWordOnCaretPos(wchar_t * txt, int size)
{
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance();
size_t cp = execute(SCI_GETCODEPAGE);
char *txtA = new char[size + 1];
getWordOnCaretPos(txtA, size);
const wchar_t * txtW = wmc.char2wchar(txtA, cp); char * ScintillaEditView::getSelectedTextToMultiChar(char * txt, size_t size, bool expand)
wcscpy_s(txt, size, txtW);
delete [] txtA;
return txt;
}
char * ScintillaEditView::getSelectedText(char * txt, size_t size, bool expand)
{ {
if (!size) if (!size)
return NULL; return NULL;
Sci_CharacterRangeFull range = getSelection(); Sci_CharacterRangeFull range = getSelection();
if (range.cpMax == range.cpMin && expand) if (range.cpMax == range.cpMin && expand)
{ {
expandWordSelection(); expandWordSelection();
range = getSelection(); range = getSelection();
} }
if (!(static_cast<Sci_Position>(size) > (range.cpMax - range.cpMin))) //there must be atleast 1 byte left for zero terminator if (!(static_cast<Sci_Position>(size) > (range.cpMax - range.cpMin))) //there must be atleast 1 byte left for zero terminator
{ {
range.cpMax = range.cpMin + size -1; //keep room for zero terminator range.cpMax = range.cpMin + size -1; //keep room for zero terminator
} }
//getText(txt, range.cpMin, range.cpMax);
return getWordFromRange(txt, size, range.cpMin, range.cpMax); return getWordFromRange(txt, size, range.cpMin, range.cpMax);
} }
wchar_t * ScintillaEditView::getGenericSelectedText(wchar_t * txt, int size, bool expand) // get the selected text & selected text character number (not the multi-chars lenghth for the allocation, if selCharNumber is not nul).
// This function returns the pointer of wide char string (wchar_t *) that we don't need to and should not deallocate.
const wchar_t * ScintillaEditView::getSelectedTextToWChar(bool expand, Sci_Position* selCharNumber)
{ {
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance();
size_t cp = execute(SCI_GETCODEPAGE); size_t cp = execute(SCI_GETCODEPAGE);
char *txtA = new char[size + 1]; char *txtA = nullptr;
getSelectedText(txtA, size, expand);
Sci_CharacterRangeFull range = getSelection();
if (range.cpMax == range.cpMin && expand)
{
expandWordSelection();
range = getSelection();
}
auto selNum = execute(SCI_COUNTCHARACTERS, range.cpMin, range.cpMax);
// return the selected string's character number
if (selCharNumber)
*selCharNumber = selNum;
if (selNum == 0)
return nullptr;
// then get the selected string's total bytes (without counting the last NULL char)
auto neededByte = execute(SCI_GETSELTEXT, 0, NULL);
txtA = new char[neededByte + 1];
execute(SCI_GETSELTEXT, 0, reinterpret_cast<LPARAM>(txtA));
const wchar_t * txtW = wmc.char2wchar(txtA, cp); const wchar_t * txtW = wmc.char2wchar(txtA, cp);
wcscpy_s(txt, size, txtW);
delete [] txtA; delete [] txtA;
return txt;
return txtW;
} }
intptr_t ScintillaEditView::searchInTarget(const wchar_t * text2Find, size_t lenOfText2Find, size_t fromPos, size_t toPos) const intptr_t ScintillaEditView::searchInTarget(const wchar_t * text2Find, size_t lenOfText2Find, size_t fromPos, size_t toPos) const
@ -3919,15 +3932,19 @@ void ScintillaEditView::columnReplace(ColumnModeInfos & cmi, size_t initial, siz
//Defined in ScintillaEditView.h : //Defined in ScintillaEditView.h :
//const UCHAR MASK_FORMAT = 0x03; //const UCHAR MASK_FORMAT = 0x03;
UCHAR f = format & MASK_FORMAT; bool useUppercase = false;
int base = 10; int base = 10;
if (f == BASE_16) if (format == BASE_16)
base = 16; base = 16;
else if (f == BASE_08) else if (format == BASE_08)
base = 8; base = 8;
else if (f == BASE_02) else if (format == BASE_02)
base = 2; base = 2;
else if (format == BASE_16_UPPERCASE)
{
base = 16;
useUppercase = true;
}
const int stringSize = 512; const int stringSize = 512;
char str[stringSize]; char str[stringSize];
@ -3966,7 +3983,7 @@ void ScintillaEditView::columnReplace(ColumnModeInfos & cmi, size_t initial, siz
cmi[i]._selLpos += totalDiff; cmi[i]._selLpos += totalDiff;
cmi[i]._selRpos += totalDiff; cmi[i]._selRpos += totalDiff;
variedFormatNumber2String<char>(str, stringSize, numbers.at(i), base, kib, lead); variedFormatNumber2String<char>(str, stringSize, numbers.at(i), base, useUppercase, kib, lead);
const bool hasVirtualSpc = cmi[i]._nbVirtualAnchorSpc > 0; const bool hasVirtualSpc = cmi[i]._nbVirtualAnchorSpc > 0;
if (hasVirtualSpc) // if virtual space is present, then insert space if (hasVirtualSpc) // if virtual space is present, then insert space

View File

@ -109,12 +109,7 @@ enum TextCase : UCHAR
RANDOMCASE RANDOMCASE
}; };
const UCHAR MASK_FORMAT = 0x03; enum : UCHAR { BASE_10 = 0, BASE_16 = 1, BASE_08 = 2, BASE_02 = 3, BASE_16_UPPERCASE = 4 };
const UCHAR BASE_10 = 0x00; // Dec
const UCHAR BASE_16 = 0x01; // Hex
const UCHAR BASE_08 = 0x02; // Oct
const UCHAR BASE_02 = 0x03; // Bin
const int MARK_BOOKMARK = 20; const int MARK_BOOKMARK = 20;
const int MARK_HIDELINESBEGIN = 19; const int MARK_HIDELINESBEGIN = 19;
@ -252,7 +247,7 @@ const std::vector<std::vector<const char*>> g_nonPrintingChars =
size_t getNbDigits(size_t aNum, size_t base); size_t getNbDigits(size_t aNum, size_t base);
template<typename T> template<typename T>
T* variedFormatNumber2String(T* str, size_t strLen, size_t number, size_t base, size_t nbDigits, ColumnEditorParam::leadingChoice lead) T* variedFormatNumber2String(T* str, size_t strLen, size_t number, size_t base, bool useUpper, size_t nbDigits, ColumnEditorParam::leadingChoice lead)
{ {
if (nbDigits == 0 || nbDigits >= strLen) return NULL; if (nbDigits == 0 || nbDigits >= strLen) return NULL;
@ -293,6 +288,8 @@ T* variedFormatNumber2String(T* str, size_t strLen, size_t number, size_t base,
else if (base == 16) else if (base == 16)
{ {
std::stringstream stream; std::stringstream stream;
if (useUpper)
stream << std::uppercase;
stream << std::hex << number; stream << std::hex << number;
numberStr = stream.str(); numberStr = stream.str();
} }
@ -467,10 +464,10 @@ public:
void getVisibleStartAndEndPosition(intptr_t* startPos, intptr_t* endPos); void getVisibleStartAndEndPosition(intptr_t* startPos, intptr_t* endPos);
char * getWordFromRange(char * txt, size_t size, size_t pos1, size_t pos2); char * getWordFromRange(char * txt, size_t size, size_t pos1, size_t pos2);
char * getSelectedText(char * txt, size_t size, bool expand = true); char * getSelectedTextToMultiChar(char * txt, size_t size, bool expand = true);
const wchar_t* getSelectedTextToWChar(bool expand = true, Sci_Position* selCharNumber = nullptr);
char * getWordOnCaretPos(char * txt, size_t size); char * getWordOnCaretPos(char * txt, size_t size);
wchar_t * getGenericWordOnCaretPos(wchar_t * txt, int size);
wchar_t * getGenericSelectedText(wchar_t * txt, int size, bool expand = true);
intptr_t searchInTarget(const wchar_t * Text2Find, size_t lenOfText2Find, size_t fromPos, size_t toPos) const; intptr_t searchInTarget(const wchar_t * Text2Find, size_t lenOfText2Find, size_t fromPos, size_t toPos) const;
void appendGenericText(const wchar_t * text2Append) const; void appendGenericText(const wchar_t * text2Append) const;
void addGenericText(const wchar_t * text2Append) const; void addGenericText(const wchar_t * text2Append) const;

View File

@ -151,12 +151,7 @@ void SmartHighlighter::highlightView(ScintillaEditView * pHighlightView, Scintil
return; return;
} }
char * text2Find = new char[textlen + 1]; const wchar_t * text2FindW = pHighlightView->getSelectedTextToWChar(false); //do not expand selection (false)
pHighlightView->getSelectedText(text2Find, textlen + 1, false); //do not expand selection (false)
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance();
UINT cp = static_cast<UINT>(pHighlightView->execute(SCI_GETCODEPAGE));
const wchar_t * text2FindW = wmc.char2wchar(text2Find, cp);
highlightViewWithWord(pHighlightView, text2FindW); highlightViewWithWord(pHighlightView, text2FindW);
@ -171,6 +166,4 @@ void SmartHighlighter::highlightView(ScintillaEditView * pHighlightView, Scintil
// Hightlight the unfocused view even if it's a clone, as it might be in a different area of the document // Hightlight the unfocused view even if it's a clone, as it might be in a different area of the document
highlightViewWithWord(unfocusView, text2FindW); highlightViewWithWord(unfocusView, text2FindW);
} }
delete[] text2Find;
} }

View File

@ -42,21 +42,23 @@ void ColumnEditorDlg::display(bool toShow) const
intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
{ {
static HBRUSH hRedBrush = nullptr;
static int whichFlashRed = 0;
constexpr COLORREF rgbRed = RGB(255, 0, 0);
static HWND hCurrentBalloonTip = nullptr;
switch (message) switch (message)
{ {
case WM_INITDIALOG : case WM_INITDIALOG :
{ {
hRedBrush = CreateSolidBrush(rgbRed); // Create red brush once
ColumnEditorParam colEditParam = NppParameters::getInstance()._columnEditParam; ColumnEditorParam colEditParam = NppParameters::getInstance()._columnEditParam;
NppDarkMode::autoSubclassAndThemeChildControls(_hSelf); NppDarkMode::autoSubclassAndThemeChildControls(_hSelf);
::SetDlgItemText(_hSelf, IDC_COL_TEXT_EDIT, colEditParam._insertedTextContent.c_str()); ::SetDlgItemText(_hSelf, IDC_COL_TEXT_EDIT, colEditParam._insertedTextContent.c_str());
if (colEditParam._initialNum != -1) setNumericFields(colEditParam);
::SetDlgItemInt(_hSelf, IDC_COL_INITNUM_EDIT, colEditParam._initialNum, FALSE);
if (colEditParam._increaseNum != -1)
::SetDlgItemInt(_hSelf, IDC_COL_INCREASENUM_EDIT, colEditParam._increaseNum, FALSE);
if (colEditParam._repeatNum != -1)
::SetDlgItemInt(_hSelf, IDC_COL_REPEATNUM_EDIT, colEditParam._repeatNum, FALSE);
::SendDlgItemMessage(_hSelf, IDC_COL_LEADING_COMBO, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"None")); ::SendDlgItemMessage(_hSelf, IDC_COL_LEADING_COMBO, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"None"));
::SendDlgItemMessage(_hSelf, IDC_COL_LEADING_COMBO, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Zeros")); ::SendDlgItemMessage(_hSelf, IDC_COL_LEADING_COMBO, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Zeros"));
@ -72,15 +74,22 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
::SendMessage(::GetDlgItem(_hSelf, IDC_COL_LEADING_COMBO), CB_SETCURSEL, curSel, 0); ::SendMessage(::GetDlgItem(_hSelf, IDC_COL_LEADING_COMBO), CB_SETCURSEL, curSel, 0);
int format = IDC_COL_DEC_RADIO; int format = IDC_COL_DEC_RADIO;
if (colEditParam._formatChoice == 1) if ((colEditParam._formatChoice == BASE_16) || (colEditParam._formatChoice == BASE_16_UPPERCASE)) // either BASE_16 or BASE_16_UC
format = IDC_COL_HEX_RADIO; format = IDC_COL_HEX_RADIO;
else if (colEditParam._formatChoice == 2) else if (colEditParam._formatChoice == BASE_08)
format = IDC_COL_OCT_RADIO; format = IDC_COL_OCT_RADIO;
else if (colEditParam._formatChoice == 3) else if (colEditParam._formatChoice == BASE_02)
format = IDC_COL_BIN_RADIO; format = IDC_COL_BIN_RADIO;
::SendDlgItemMessage(_hSelf, format, BM_SETCHECK, TRUE, 0); ::SendDlgItemMessage(_hSelf, format, BM_SETCHECK, TRUE, 0);
// populate the Hex-Case dropdown and activate correct case
::SendDlgItemMessage(_hSelf, IDC_COL_HEXUC_COMBO, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"a-f"));
::SendDlgItemMessage(_hSelf, IDC_COL_HEXUC_COMBO, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"A-F"));
UCHAR uc = (colEditParam._formatChoice == BASE_16_UPPERCASE) ? 1 : 0;
::SendDlgItemMessage(_hSelf, IDC_COL_HEXUC_COMBO, CB_SETCURSEL, uc, 0); // activate correct case
EnableWindow(GetDlgItem(_hSelf, IDC_COL_HEXUC_COMBO), format == IDC_COL_HEX_RADIO); // enable combobox only if hex is chosen
switchTo(colEditParam._mainChoice); switchTo(colEditParam._mainChoice);
goToCenter(SWP_SHOWWINDOW | SWP_NOSIZE); goToCenter(SWP_SHOWWINDOW | SWP_NOSIZE);
@ -89,6 +98,12 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
case WM_CTLCOLOREDIT: case WM_CTLCOLOREDIT:
{ {
int id = GetDlgCtrlID(reinterpret_cast<HWND>(lParam));
if (id == whichFlashRed)
{
SetBkColor((HDC)wParam, rgbRed);
return (LRESULT)hRedBrush;
}
return NppDarkMode::onCtlColorCtrl(reinterpret_cast<HDC>(wParam)); return NppDarkMode::onCtlColorCtrl(reinterpret_cast<HDC>(wParam));
} }
@ -152,9 +167,19 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
{ {
switch (LOWORD(wParam)) switch (LOWORD(wParam))
{ {
case IDCANCEL : // Close case IDCANCEL: // in case of ESC keystroke
{
if (hCurrentBalloonTip && IsWindowVisible(hCurrentBalloonTip)) // if current baloon tip shown, just hide it
{
ShowWindow(hCurrentBalloonTip, SW_HIDE);
}
else // if current baloon tip doesn't show, we hide Column Editor dialog
{
display(false); display(false);
}
return TRUE; return TRUE;
}
case IDOK: case IDOK:
{ {
@ -228,9 +253,33 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
} }
else else
{ {
size_t initialNumber = ::GetDlgItemInt(_hSelf, IDC_COL_INITNUM_EDIT, NULL, TRUE); ColumnEditorParam colEditParam = NppParameters::getInstance()._columnEditParam;
size_t increaseNumber = ::GetDlgItemInt(_hSelf, IDC_COL_INCREASENUM_EDIT, NULL, TRUE);
size_t repeat = ::GetDlgItemInt(_hSelf, IDC_COL_REPEATNUM_EDIT, NULL, TRUE); ::GetDlgItemText(_hSelf, IDC_COL_INITNUM_EDIT, str, stringSize);
int initialNumber = getNumericFieldValueFromText(colEditParam._formatChoice, str, stringSize);
if (initialNumber == -1)
{
whichFlashRed = sendValidationErrorMessage(IDC_COL_INITNUM_EDIT, colEditParam._formatChoice, str);
return TRUE;
}
::GetDlgItemText(_hSelf, IDC_COL_INCREASENUM_EDIT, str, stringSize);
int increaseNumber = getNumericFieldValueFromText(colEditParam._formatChoice, str, stringSize);
if (increaseNumber == -1)
{
whichFlashRed = sendValidationErrorMessage(IDC_COL_INCREASENUM_EDIT, colEditParam._formatChoice, str);
return TRUE;
}
::GetDlgItemText(_hSelf, IDC_COL_REPEATNUM_EDIT, str, stringSize);
int repeat = getNumericFieldValueFromText(colEditParam._formatChoice, str, stringSize);
if (repeat == -1)
{
whichFlashRed = sendValidationErrorMessage(IDC_COL_REPEATNUM_EDIT, colEditParam._formatChoice, str);
return TRUE;
}
if (repeat == 0) if (repeat == 0)
{ {
repeat = 1; // Without this we might get an infinite loop while calculating the set "numbers" below. repeat = 1; // Without this we might get an infinite loop while calculating the set "numbers" below.
@ -268,7 +317,7 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
const size_t kiMaxSize = 1 + (size_t)endLine - (size_t)cursorLine; const size_t kiMaxSize = 1 + (size_t)endLine - (size_t)cursorLine;
while (numbers.size() < kiMaxSize) while (numbers.size() < kiMaxSize)
{ {
for (size_t i = 0; i < repeat; i++) for (int i = 0; i < repeat; i++)
{ {
numbers.push_back(curNumber); numbers.push_back(curNumber);
@ -281,15 +330,19 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
constexpr int lineAllocatedLen = 1024; constexpr int lineAllocatedLen = 1024;
wchar_t* line = new wchar_t[lineAllocatedLen]; wchar_t* line = new wchar_t[lineAllocatedLen];
UCHAR f = format & MASK_FORMAT;
size_t base = 10; size_t base = 10;
if (f == BASE_16) bool useUppercase = false;
if (format == BASE_16)
base = 16; base = 16;
else if (f == BASE_08) else if (format == BASE_08)
base = 8; base = 8;
else if (f == BASE_02) else if (format == BASE_02)
base = 2; base = 2;
else if (format == BASE_16_UPPERCASE)
{
base = 16;
useUppercase = true;
}
size_t endNumber = *numbers.rbegin(); size_t endNumber = *numbers.rbegin();
size_t nbEnd = getNbDigits(endNumber, base); size_t nbEnd = getNbDigits(endNumber, base);
@ -317,7 +370,7 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
// //
// Calcule wstring // Calcule wstring
// //
variedFormatNumber2String<wchar_t>(str, stringSize, numbers.at(i - cursorLine), base, nb, getLeading()); variedFormatNumber2String<wchar_t>(str, stringSize, numbers.at(i - cursorLine), base, useUppercase, nb, getLeading());
if (lineEndCol < cursorCol) if (lineEndCol < cursorCol)
{ {
@ -359,13 +412,16 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
case IDC_COL_BIN_RADIO: case IDC_COL_BIN_RADIO:
{ {
ColumnEditorParam& colEditParam = NppParameters::getInstance()._columnEditParam; ColumnEditorParam& colEditParam = NppParameters::getInstance()._columnEditParam;
colEditParam._formatChoice = 0; // dec colEditParam._formatChoice = BASE_10; // dec
if (wParam == IDC_COL_HEX_RADIO) if (LOWORD(wParam) == IDC_COL_HEX_RADIO)
colEditParam._formatChoice = 1; colEditParam._formatChoice = getHexCase(); // will pick appropriate UC or LC version of hex
else if (wParam == IDC_COL_OCT_RADIO) else if (LOWORD(wParam) == IDC_COL_OCT_RADIO)
colEditParam._formatChoice = 2; colEditParam._formatChoice = BASE_08;
else if (wParam == IDC_COL_BIN_RADIO) else if (LOWORD(wParam) == IDC_COL_BIN_RADIO)
colEditParam._formatChoice = 3; colEditParam._formatChoice = BASE_02;
setNumericFields(colEditParam); // reformat the field text to be based on the new radix
EnableWindow(GetDlgItem(_hSelf, IDC_COL_HEXUC_COMBO), LOWORD(wParam) == IDC_COL_HEX_RADIO); // enable combobox only if hex is chosen
return TRUE; return TRUE;
} }
@ -399,7 +455,14 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
return TRUE; return TRUE;
} }
int num = ::GetDlgItemInt(_hSelf, LOWORD(wParam), NULL, TRUE); int num = getNumericFieldValueFromText(colEditParam._formatChoice, str, stringSize);
if (num == -1)
{
num = colEditParam._initialNum;
setNumericFields(colEditParam); // reformat the strings to eliminate error
whichFlashRed = sendValidationErrorMessage(LOWORD(wParam), colEditParam._formatChoice, str);
}
colEditParam._initialNum = num; colEditParam._initialNum = num;
return TRUE; return TRUE;
} }
@ -413,7 +476,14 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
return TRUE; return TRUE;
} }
int num = ::GetDlgItemInt(_hSelf, LOWORD(wParam), NULL, TRUE); int num = getNumericFieldValueFromText(colEditParam._formatChoice, str, stringSize);
if (num == -1)
{
num = colEditParam._increaseNum;
setNumericFields(colEditParam); // reformat the strings to eliminate error
whichFlashRed = sendValidationErrorMessage(LOWORD(wParam), colEditParam._formatChoice, str);
}
colEditParam._increaseNum = num; colEditParam._increaseNum = num;
return TRUE; return TRUE;
} }
@ -427,7 +497,14 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
return TRUE; return TRUE;
} }
int num = ::GetDlgItemInt(_hSelf, LOWORD(wParam), NULL, TRUE); int num = getNumericFieldValueFromText(colEditParam._formatChoice, str, stringSize);
if (num == -1)
{
num = colEditParam._repeatNum;
setNumericFields(colEditParam); // reformat the strings to eliminate error
whichFlashRed = sendValidationErrorMessage(LOWORD(wParam), colEditParam._formatChoice, str);
}
colEditParam._repeatNum = num; colEditParam._repeatNum = num;
return TRUE; return TRUE;
} }
@ -443,6 +520,15 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
colEditParam._leadingChoice = getLeading(); colEditParam._leadingChoice = getLeading();
return TRUE; return TRUE;
} }
else if(LOWORD(wParam) == IDC_COL_HEXUC_COMBO)
{
ColumnEditorParam& colEditParam = NppParameters::getInstance()._columnEditParam;
if ((colEditParam._formatChoice & BASE_16) == BASE_16 )
colEditParam._formatChoice = getHexCase();
setNumericFields(colEditParam); // want the GUI fields to update case when combobox changes
return TRUE;
}
} }
break; break;
} }
@ -452,6 +538,51 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
break; break;
} }
case WM_TIMER:
{
static int idRedraw = 0;
if (wParam == IDT_COL_FLASH_TIMER)
{
KillTimer(_hSelf, IDT_COL_FLASH_TIMER);
idRedraw = whichFlashRed; // keep the ID for the one whose flash is ending...
whichFlashRed = 0; // must be 0 before the redraw, otherwise it will maintain color
redrawDlgItem(idRedraw, true); // redraw the just the one that was flashed
// Remember the latest/current baloon tip handle
hCurrentBalloonTip = [](HWND hEditControl) -> HWND {
HWND hTooltip = FindWindowEx(NULL, NULL, L"tooltips_class32", NULL);
while (hTooltip)
{
HWND hParent = GetParent(hTooltip);
if (hParent == hEditControl || hParent == GetParent(hEditControl))
{
return hTooltip;
}
hTooltip = FindWindowEx(NULL, hTooltip, L"tooltips_class32", NULL);
}
return NULL;
}(GetDlgItem(_hSelf, idRedraw));
}
if (wParam == IDC_COL_BALLONTIP_TIMER)
{
KillTimer(_hSelf, IDC_COL_BALLONTIP_TIMER);
SendMessage(GetDlgItem(_hSelf, idRedraw), EM_HIDEBALLOONTIP, 0, 0);
}
break;
}
case WM_DESTROY:
{
DeleteObject(hRedBrush);
break;
}
default : default :
return FALSE; return FALSE;
} }
@ -492,16 +623,23 @@ void ColumnEditorDlg::switchTo(bool toText)
UCHAR ColumnEditorDlg::getFormat() UCHAR ColumnEditorDlg::getFormat()
{ {
UCHAR f = 0; // Dec by default UCHAR f = BASE_10; // Dec by default
if (isCheckedOrNot(IDC_COL_HEX_RADIO)) if (isCheckedOrNot(IDC_COL_HEX_RADIO))
f = 1; f = getHexCase(); // will give BASE_16 or BASE_16_UC, depending on case selector
else if (isCheckedOrNot(IDC_COL_OCT_RADIO)) else if (isCheckedOrNot(IDC_COL_OCT_RADIO))
f = 2; f = BASE_08;
else if (isCheckedOrNot(IDC_COL_BIN_RADIO)) else if (isCheckedOrNot(IDC_COL_BIN_RADIO))
f = 3; f = BASE_02;
return f; return f;
} }
UCHAR ColumnEditorDlg::getHexCase()
{
int curSel = static_cast<int>(::SendDlgItemMessage(_hSelf, IDC_COL_HEXUC_COMBO, CB_GETCURSEL, 0, 0));
return (curSel == 1) ? BASE_16_UPPERCASE : BASE_16;
}
ColumnEditorParam::leadingChoice ColumnEditorDlg::getLeading() ColumnEditorParam::leadingChoice ColumnEditorDlg::getLeading()
{ {
ColumnEditorParam::leadingChoice leading = ColumnEditorParam::noneLeading; ColumnEditorParam::leadingChoice leading = ColumnEditorParam::noneLeading;
@ -527,3 +665,147 @@ ColumnEditorParam::leadingChoice ColumnEditorDlg::getLeading()
} }
return leading; return leading;
} }
void ColumnEditorDlg::setNumericFields(const ColumnEditorParam& colEditParam)
{
if (colEditParam._formatChoice == BASE_10)
{
if (colEditParam._initialNum != -1)
::SetDlgItemInt(_hSelf, IDC_COL_INITNUM_EDIT, colEditParam._initialNum, FALSE);
else
::SetDlgItemText(_hSelf, IDC_COL_INITNUM_EDIT, L"");
if (colEditParam._increaseNum != -1)
::SetDlgItemInt(_hSelf, IDC_COL_INCREASENUM_EDIT, colEditParam._increaseNum, FALSE);
else
::SetDlgItemText(_hSelf, IDC_COL_INCREASENUM_EDIT, L"");
if (colEditParam._repeatNum != -1)
::SetDlgItemInt(_hSelf, IDC_COL_REPEATNUM_EDIT, colEditParam._repeatNum, FALSE);
else
::SetDlgItemText(_hSelf, IDC_COL_REPEATNUM_EDIT, L"");
}
else
{
size_t base = 10;
switch (colEditParam._formatChoice)
{
case BASE_16: // hex
case BASE_16_UPPERCASE: // or hex w/ uppercase A-F
base = 16;
break;
case BASE_08: // oct
base = 8;
break;
case BASE_02: // bin
base = 2;
break;
default:
base = 10;
break;
}
bool useUpper = (colEditParam._formatChoice == BASE_16_UPPERCASE);
constexpr int stringSize = 1024;
wchar_t str[stringSize]{};
if (colEditParam._initialNum != -1)
{
variedFormatNumber2String<wchar_t>(str, stringSize, colEditParam._initialNum, base, useUpper, getNbDigits(colEditParam._initialNum, base), getLeading());
::SetDlgItemText(_hSelf, IDC_COL_INITNUM_EDIT, str);
}
else
::SetDlgItemText(_hSelf, IDC_COL_INITNUM_EDIT, L"");
if (colEditParam._increaseNum != -1)
{
variedFormatNumber2String<wchar_t>(str, stringSize, colEditParam._increaseNum, base, useUpper, getNbDigits(colEditParam._increaseNum, base), getLeading());
::SetDlgItemText(_hSelf, IDC_COL_INCREASENUM_EDIT, str);
}
else
::SetDlgItemText(_hSelf, IDC_COL_INCREASENUM_EDIT, L"");
if (colEditParam._repeatNum != -1)
{
variedFormatNumber2String<wchar_t>(str, stringSize, colEditParam._repeatNum, base, useUpper, getNbDigits(colEditParam._repeatNum, base), getLeading());
::SetDlgItemText(_hSelf, IDC_COL_REPEATNUM_EDIT, str);
}
else
::SetDlgItemText(_hSelf, IDC_COL_REPEATNUM_EDIT, L"");
}
return;
}
// Convert the string to an integer, depending on base
int ColumnEditorDlg::getNumericFieldValueFromText(int formatChoice, wchar_t str[], size_t /*stringSize*/)
{
int num = 0;
int base = 0;
switch (formatChoice)
{
case BASE_16:
case BASE_16_UPPERCASE:
base = 16;
break;
case BASE_08:
base = 8;
break;
case BASE_02:
base = 2;
break;
default:
base = 10;
break;
}
// convert string in base to int value; on error, return -1
wchar_t* pEnd = nullptr;
num = static_cast<int>(std::wcstol(str, &pEnd, base));
if (pEnd == nullptr || *pEnd != L'\0')
{
return -1;
}
return num;
}
int ColumnEditorDlg::sendValidationErrorMessage(int whichFlashRed, int formatChoice, wchar_t str[])
{
wchar_t wcMsg[1024];
const wchar_t *wcRadixNote;
EDITBALLOONTIP ebt;
ebt.cbStruct = sizeof(EDITBALLOONTIP);
ebt.pszTitle = L"Invalid Numeric Entry";
switch (formatChoice)
{
case BASE_16:
case BASE_16_UPPERCASE:
wcRadixNote = L"Hex numbers use 0-9, A-F!";
break;
case BASE_08:
wcRadixNote = L"Oct numbers only use 0-7!";
break;
case BASE_02:
wcRadixNote = L"Bin numbers only use 0-1!";
break;
default:
wcRadixNote = L"Decimal numbers only use 0-9!";
break;
}
if (str[0])
{
swprintf_s(wcMsg, L"Entered string \"%s\":\r\n%s", str, wcRadixNote);
ebt.pszText = wcMsg;
}
ebt.ttiIcon = TTI_ERROR_LARGE; // tooltip icon
SendMessage(GetDlgItem(_hSelf, whichFlashRed), EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt);
SetTimer(_hSelf, IDT_COL_FLASH_TIMER, 250, NULL);
SetTimer(_hSelf, IDC_COL_BALLONTIP_TIMER, 3500, NULL);
redrawDlgItem(whichFlashRed);
return whichFlashRed;
}

View File

@ -45,10 +45,14 @@ public :
void switchTo(bool toText); void switchTo(bool toText);
UCHAR getFormat(); UCHAR getFormat();
ColumnEditorParam::leadingChoice getLeading(); ColumnEditorParam::leadingChoice getLeading();
UCHAR getHexCase();
protected : protected :
intptr_t CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) override; intptr_t CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) override;
private : private :
ScintillaEditView **_ppEditView = nullptr; ScintillaEditView **_ppEditView = nullptr;
void setNumericFields(const ColumnEditorParam& colEditParam);
int getNumericFieldValueFromText(int formatChoice, wchar_t str[], size_t stringSize);
int sendValidationErrorMessage(int whichFlashRed, int formatChoice, wchar_t str[]);
}; };

View File

@ -25,27 +25,28 @@ EXSTYLE WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE
CAPTION "Column / Multi-Selection Editor" CAPTION "Column / Multi-Selection Editor"
FONT 8, L"MS Shell Dlg", 0, 0, 0x0 FONT 8, L"MS Shell Dlg", 0, 0, 0x0
BEGIN BEGIN
CONTROL "&Text to Insert",IDC_COL_TEXT_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP | WS_GROUP,13,6,124,10 CONTROL "&Text to Insert",IDC_COL_TEXT_RADIO,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,6,124,10
CONTROL "&Number to Insert",IDC_COL_NUM_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP | WS_GROUP,13,68,204,10 CONTROL "&Number to Insert",IDC_COL_NUM_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,68,204,10
GROUPBOX "",IDC_COL_TEXT_GRP_STATIC,8,14,124,46 GROUPBOX "",IDC_COL_TEXT_GRP_STATIC,8,14,124,46
EDITTEXT IDC_COL_TEXT_EDIT,20,32,97,12,ES_AUTOHSCROLL EDITTEXT IDC_COL_TEXT_EDIT,20,32,97,12,ES_AUTOHSCROLL
GROUPBOX "",IDC_COL_NUM_GRP_STATIC,8,77,204,130 GROUPBOX "Format",IDC_COL_FORMAT_GRP_STATIC,16,86,188,44,BS_CENTER
RTEXT "&Initial number:",IDC_COL_INITNUM_STATIC,10,89,76,8 CONTROL "&Dec",IDC_COL_DEC_RADIO,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,27,99,50,10
EDITTEXT IDC_COL_INITNUM_EDIT,90,87,38,12,ES_NUMBER CONTROL "&Hex",IDC_COL_HEX_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,110,99,50,10
RTEXT "Increase b&y:",IDC_COL_INCRNUM_STATIC,10,106,75,8 CONTROL "&Oct",IDC_COL_OCT_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,27,114,50,10
EDITTEXT IDC_COL_INCREASENUM_EDIT,90,104,38,12,ES_NUMBER CONTROL "&Bin",IDC_COL_BIN_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,110,114,50,10
RTEXT "&Repeat:",IDC_COL_REPEATNUM_STATIC,10,123,75,8 COMBOBOX IDC_COL_HEXUC_COMBO,150,97,40,10,CBS_DROPDOWNLIST | WS_TABSTOP
EDITTEXT IDC_COL_REPEATNUM_EDIT,90,121,38,12,ES_NUMBER
RTEXT "&Leading:",IDC_COL_LEADING_STATIC,10,140,75,8
COMBOBOX IDC_COL_LEADING_COMBO,90,138,100,30,CBS_DROPDOWNLIST | WS_TABSTOP
GROUPBOX "Format",IDC_COL_FORMAT_GRP_STATIC,16,155,188,44,BS_CENTER GROUPBOX "",IDC_COL_NUM_GRP_STATIC,8,77,204,130
CONTROL "&Dec",IDC_COL_DEC_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,27,168,70,10 RTEXT "&Initial number:",IDC_COL_INITNUM_STATIC,10,140,76,8
CONTROL "&Hex",IDC_COL_HEX_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,122,168,70,10 EDITTEXT IDC_COL_INITNUM_EDIT,90,138,38,12
CONTROL "&Oct",IDC_COL_OCT_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,27,183,70,10 RTEXT "Increase b&y:",IDC_COL_INCRNUM_STATIC,10,157,75,8
CONTROL "&Bin",IDC_COL_BIN_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,122,183,70,10 EDITTEXT IDC_COL_INCREASENUM_EDIT,90,155,38,12
RTEXT "&Repeat:",IDC_COL_REPEATNUM_STATIC,10,174,75,8
EDITTEXT IDC_COL_REPEATNUM_EDIT,90,172,38,12
RTEXT "&Leading:",IDC_COL_LEADING_STATIC,10,191,75,8
COMBOBOX IDC_COL_LEADING_COMBO,90,189,100,30,CBS_DROPDOWNLIST | WS_TABSTOP
DEFPUSHBUTTON "OK",IDOK,142,18,70,14 DEFPUSHBUTTON "OK",IDOK,142,18,70,14
PUSHBUTTON "Cancel",IDCANCEL,142,36,70,14 PUSHBUTTON "Cancel",IDCANCEL,142,36,70,14

View File

@ -37,4 +37,7 @@
#define IDC_COL_REPEATNUM_EDIT (IDD_COLUMNEDIT + 17) #define IDC_COL_REPEATNUM_EDIT (IDD_COLUMNEDIT + 17)
#define IDC_COL_LEADING_STATIC (IDD_COLUMNEDIT + 18) #define IDC_COL_LEADING_STATIC (IDD_COLUMNEDIT + 18)
#define IDC_COL_LEADING_COMBO (IDD_COLUMNEDIT + 19) #define IDC_COL_LEADING_COMBO (IDD_COLUMNEDIT + 19)
#define IDC_COL_HEXUC_COMBO (IDD_COLUMNEDIT + 20)
#define IDT_COL_FLASH_TIMER (IDD_COLUMNEDIT + 21)
#define IDC_COL_BALLONTIP_TIMER (IDD_COLUMNEDIT + 22)
#endif// COLUMNEDITOR_RC_H #endif// COLUMNEDITOR_RC_H

View File

@ -292,6 +292,7 @@ Utf8_16_Write::Utf8_16_Write()
m_pNewBuf = NULL; m_pNewBuf = NULL;
m_bFirstWrite = true; m_bFirstWrite = true;
m_nBufSize = 0; m_nBufSize = 0;
m_dwLastFileError = NO_ERROR;
} }
Utf8_16_Write::~Utf8_16_Write() Utf8_16_Write::~Utf8_16_Write()
@ -301,11 +302,14 @@ Utf8_16_Write::~Utf8_16_Write()
bool Utf8_16_Write::openFile(const wchar_t *name) bool Utf8_16_Write::openFile(const wchar_t *name)
{ {
m_pFile = std::make_unique<Win32_IO_File>(name); m_dwLastFileError = NO_ERROR;
m_pFile = std::make_unique<Win32_IO_File>(name);
if (!m_pFile) if (!m_pFile)
return false; return false;
m_dwLastFileError = m_pFile->getLastErrorCode();
if (!m_pFile->isOpened()) if (!m_pFile->isOpened())
{ {
m_pFile = nullptr; m_pFile = nullptr;
@ -319,11 +323,11 @@ bool Utf8_16_Write::openFile(const wchar_t *name)
bool Utf8_16_Write::writeFile(const void* p, size_t _size) bool Utf8_16_Write::writeFile(const void* p, size_t _size)
{ {
m_dwLastFileError = NO_ERROR;
// no file open // no file open
if (!m_pFile) if (!m_pFile)
{
return false; return false;
}
if (m_bFirstWrite) if (m_bFirstWrite)
{ {
@ -332,16 +336,22 @@ bool Utf8_16_Write::writeFile(const void* p, size_t _size)
case uniUTF8: case uniUTF8:
{ {
if (!m_pFile->write(k_Boms[m_eEncoding], 3)) if (!m_pFile->write(k_Boms[m_eEncoding], 3))
{
m_dwLastFileError = m_pFile->getLastErrorCode();
return false; return false;
} }
}
break; break;
case uni16BE: case uni16BE:
case uni16LE: case uni16LE:
{ {
if (!m_pFile->write(k_Boms[m_eEncoding], 2)) if (!m_pFile->write(k_Boms[m_eEncoding], 2))
{
m_dwLastFileError = m_pFile->getLastErrorCode();
return false; return false;
} }
}
break; break;
default: default:
@ -365,7 +375,7 @@ bool Utf8_16_Write::writeFile(const void* p, size_t _size)
// Normal write // Normal write
if (m_pFile->write(p, _size)) if (m_pFile->write(p, _size))
isOK = true; isOK = true;
m_dwLastFileError = m_pFile->getLastErrorCode();
} }
break; break;
@ -391,6 +401,7 @@ bool Utf8_16_Write::writeFile(const void* p, size_t _size)
{ {
if (!m_pFile->write(buf, bufIndex * sizeof(utf16))) if (!m_pFile->write(buf, bufIndex * sizeof(utf16)))
{ {
m_dwLastFileError = m_pFile->getLastErrorCode();
delete[] buf; delete[] buf;
return 0; return 0;
} }
@ -399,7 +410,6 @@ bool Utf8_16_Write::writeFile(const void* p, size_t _size)
} }
isOK = true; isOK = true;
delete[] buf; delete[] buf;
} }
break; break;
@ -506,8 +516,16 @@ void Utf8_16_Write::closeFile()
} }
if (m_pFile) if (m_pFile)
{
m_pFile->close(); // explicit closing for getting the possible flushing/closing error code
m_dwLastFileError = m_pFile->getLastErrorCode();
m_pFile = nullptr; m_pFile = nullptr;
} }
else
{
m_dwLastFileError = NO_ERROR;
}
}
//================================================================= //=================================================================

View File

@ -148,11 +148,14 @@ public:
size_t convert(char* p, size_t _size); size_t convert(char* p, size_t _size);
char* getNewBuf() { return reinterpret_cast<char*>(m_pNewBuf); } char* getNewBuf() { return reinterpret_cast<char*>(m_pNewBuf); }
DWORD getLastFileErrorState() { return m_dwLastFileError; }
protected: protected:
UniMode m_eEncoding; UniMode m_eEncoding;
std::unique_ptr<Win32_IO_File> m_pFile; std::unique_ptr<Win32_IO_File> m_pFile;
ubyte* m_pNewBuf; ubyte* m_pNewBuf;
size_t m_nBufSize; size_t m_nBufSize;
bool m_bFirstWrite; bool m_bFirstWrite;
DWORD m_dwLastFileError;
}; };

View File

@ -1039,7 +1039,7 @@ void CustomFileDialog::setSaveAsCopy(bool isSavingAsCopy)
} }
} }
bool CustomFileDialog::getOpenTheCopyAfterSaveAsCopy(void) bool CustomFileDialog::getOpenTheCopyAfterSaveAsCopy()
{ {
return (_impl->_savingAsCopyInfo & SAVE_AS_COPY_OPEN) != 0; return (_impl->_savingAsCopyInfo & SAVE_AS_COPY_OPEN) != 0;
} }
@ -1077,7 +1077,7 @@ wstring CustomFileDialog::doSaveDlg()
CurrentDirBackup backup; CurrentDirBackup backup;
_impl->addFlags(FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_FORCEFILESYSTEM); _impl->addFlags(FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_FORCEFILESYSTEM | FOS_NOTESTFILECREATE);
bool bOk = _impl->show(); bool bOk = _impl->show();
return bOk ? _impl->getResultFilename() : L""; return bOk ? _impl->getResultFilename() : L"";
} }

View File

@ -38,7 +38,7 @@ public:
void setCheckbox(const wchar_t* text, bool isActive = true); void setCheckbox(const wchar_t* text, bool isActive = true);
void setExtIndex(int extTypeIndex); void setExtIndex(int extTypeIndex);
void setSaveAsCopy(bool isSavingAsCopy); void setSaveAsCopy(bool isSavingAsCopy);
bool getOpenTheCopyAfterSaveAsCopy(void); bool getOpenTheCopyAfterSaveAsCopy();
void enableFileTypeCheckbox(const std::wstring& text, bool value); void enableFileTypeCheckbox(const std::wstring& text, bool value);
bool getFileTypeCheckboxValue() const; bool getFileTypeCheckboxValue() const;

View File

@ -422,18 +422,23 @@ IDD_PREFERENCE_SUB_SEARCHING DIALOGEX 115, 10, 460, 205
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
FONT 8, "MS Shell Dlg", 0, 0, 0x1 FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN BEGIN
GROUPBOX "When Find Dialog is Invoked", IDD_FILL_FIND_FIELD_GRP_STATIC, 31, 4, 323, 85, BS_CENTER GROUPBOX "When Find Dialog is Invoked",IDD_FILL_FIND_FIELD_GRP_STATIC,31,4,330,102,BS_CENTER
RTEXT "Minimum Size for Auto-Checking ""In selection"":",IDC_INSELECTION_THRESHOLD_STATIC,37,16,210,8 RTEXT "Minimum Size for Auto-Checking ""In selection"":",IDC_INSELECTION_THRESHOLD_STATIC,37,16,210,8
LTEXT "(?)",IDC_INSELECTION_THRESH_QUESTION_BUTTON,283, 16,10,8,SS_NOTIFY
EDITTEXT IDC_INSELECTION_THRESHOLD_EDIT,250,15,27,12,ES_CENTER | ES_NUMBER EDITTEXT IDC_INSELECTION_THRESHOLD_EDIT,250,15,27,12,ES_CENTER | ES_NUMBER
LTEXT "(?)",IDC_INSELECTION_THRESH_QUESTION_BUTTON,283,16,10,8,SS_NOTIFY
CONTROL "Fill Find in Files Directory Field Based On Active Document",IDC_CHECK_FILL_DIR_FIELD_FROM_ACTIVE_DOC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,43,311,8
CONTROL "Fill Find Field with Selected Text",IDC_CHECK_FILL_FIND_FIELD_WITH_SELECTED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,59,300,10 CONTROL "Fill Find Field with Selected Text",IDC_CHECK_FILL_FIND_FIELD_WITH_SELECTED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,59,300,10
CONTROL "Select Word Under Caret when Nothing Selected", IDC_CHECK_FILL_FIND_FIELD_SELECT_CARET, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 52, 73, 275, 10 LTEXT "(?)",IDC_FILLFINDWHAT_THRESH_QUESTION_BUTTON,52,73,10,8,SS_NOTIFY
CONTROL "Fill Find in Files Directory Field Based On Active Document", IDC_CHECK_FILL_DIR_FIELD_FROM_ACTIVE_DOC, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 37, 44, 311, 8 EDITTEXT IDC_FILLFINDWHAT_THRESHOLD_EDIT,64,72,27,12,ES_CENTER | ES_NUMBER
CONTROL "Use Monospaced font in Find dialog (Need to restart Notepad++)", IDC_CHECK_MONOSPACEDFONT_FINDDLG, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 37, 104, 350, 10 LTEXT ": Max Characters to Auto-Fill Find Field from Selection",IDC_FILLFINDWHAT_THRESHOLD_STATIC,92,73,260,8
CONTROL "Find dialog remains open after search that outputs to results window", IDC_CHECK_FINDDLG_ALWAYS_VISIBLE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 37, 119, 350, 10 CONTROL "Select Word Under Caret when Nothing Selected",IDC_CHECK_FILL_FIND_FIELD_SELECT_CARET,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,88,275,10
CONTROL "Confirm Replace All in All Opened Documents", IDC_CHECK_CONFIRMREPLOPENDOCS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 37, 134, 350, 10
CONTROL "Replace: Don't move to the following occurrence", IDC_CHECK_REPLACEANDSTOP, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 37, 149, 350, 10 CONTROL "Use Monospaced font in Find dialog (Need to restart Notepad++)",IDC_CHECK_MONOSPACEDFONT_FINDDLG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,117,350,10
CONTROL "Search Result window: show only one entry per found line if possible", IDC_CHECK_SHOWONCEPERFOUNDLINE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 37, 164, 350, 10 CONTROL "Find dialog remains open after search that outputs to results window",IDC_CHECK_FINDDLG_ALWAYS_VISIBLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,132,350,10
CONTROL "Confirm Replace All in All Opened Documents",IDC_CHECK_CONFIRMREPLOPENDOCS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,147,350,10
CONTROL "Replace: Don't move to the following occurrence",IDC_CHECK_REPLACEANDSTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,162,350,10
CONTROL "Search Result window: show only one entry per found line if possible",IDC_CHECK_SHOWONCEPERFOUNDLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,177,350,10
END END
IDD_PREFERENCE_SUB_BACKUP DIALOGEX 115, 10, 460, 205 IDD_PREFERENCE_SUB_BACKUP DIALOGEX 115, 10, 460, 205

View File

@ -311,6 +311,8 @@ intptr_t CALLBACK PreferenceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM
NppDarkMode::setDarkTooltips(_performanceSubDlg._largeFileRestrictionTip, NppDarkMode::ToolTipsType::tooltip); NppDarkMode::setDarkTooltips(_performanceSubDlg._largeFileRestrictionTip, NppDarkMode::ToolTipsType::tooltip);
if (_searchingSubDlg._tipInSelThresh != nullptr) if (_searchingSubDlg._tipInSelThresh != nullptr)
NppDarkMode::setDarkTooltips(_searchingSubDlg._tipInSelThresh, NppDarkMode::ToolTipsType::tooltip); NppDarkMode::setDarkTooltips(_searchingSubDlg._tipInSelThresh, NppDarkMode::ToolTipsType::tooltip);
if (_searchingSubDlg._tipFillFindWhatThresh != nullptr)
NppDarkMode::setDarkTooltips(_searchingSubDlg._tipFillFindWhatThresh, NppDarkMode::ToolTipsType::tooltip);
if (_indentationSubDlg._tipAutoIndentBasic) if (_indentationSubDlg._tipAutoIndentBasic)
NppDarkMode::setDarkTooltips(_indentationSubDlg._tipAutoIndentBasic, NppDarkMode::ToolTipsType::tooltip); NppDarkMode::setDarkTooltips(_indentationSubDlg._tipAutoIndentBasic, NppDarkMode::ToolTipsType::tooltip);
@ -6858,7 +6860,13 @@ intptr_t CALLBACK SearchingSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
::SendDlgItemMessage(_hSelf, IDC_CHECK_FILL_FIND_FIELD_SELECT_CARET, BM_SETCHECK, nppGUI._fillFindFieldSelectCaret, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_FILL_FIND_FIELD_SELECT_CARET, BM_SETCHECK, nppGUI._fillFindFieldSelectCaret, 0);
::SendDlgItemMessage(_hSelf, IDC_CHECK_MONOSPACEDFONT_FINDDLG, BM_SETCHECK, nppGUI._monospacedFontFindDlg, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_MONOSPACEDFONT_FINDDLG, BM_SETCHECK, nppGUI._monospacedFontFindDlg, 0);
::SendDlgItemMessage(_hSelf, IDC_CHECK_FINDDLG_ALWAYS_VISIBLE, BM_SETCHECK, nppGUI._findDlgAlwaysVisible, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_FINDDLG_ALWAYS_VISIBLE, BM_SETCHECK, nppGUI._findDlgAlwaysVisible, 0);
::SetDlgItemInt(_hSelf, IDC_FILLFINDWHAT_THRESHOLD_EDIT, nppGUI._fillFindWhatThreshold, 0);
::EnableWindow(::GetDlgItem(_hSelf, IDC_FILLFINDWHAT_THRESH_QUESTION_BUTTON), nppGUI._fillFindFieldWithSelected ? TRUE : FALSE);
::EnableWindow(::GetDlgItem(_hSelf, IDC_FILLFINDWHAT_THRESHOLD_EDIT), nppGUI._fillFindFieldWithSelected ? TRUE : FALSE);
::EnableWindow(::GetDlgItem(_hSelf, IDC_FILLFINDWHAT_THRESHOLD_STATIC), nppGUI._fillFindFieldWithSelected ? TRUE : FALSE);
::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_FILL_FIND_FIELD_SELECT_CARET), nppGUI._fillFindFieldWithSelected ? TRUE : FALSE); ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_FILL_FIND_FIELD_SELECT_CARET), nppGUI._fillFindFieldWithSelected ? TRUE : FALSE);
::SendDlgItemMessage(_hSelf, IDC_CHECK_CONFIRMREPLOPENDOCS, BM_SETCHECK, nppGUI._confirmReplaceInAllOpenDocs, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_CONFIRMREPLOPENDOCS, BM_SETCHECK, nppGUI._confirmReplaceInAllOpenDocs, 0);
::SendDlgItemMessage(_hSelf, IDC_CHECK_REPLACEANDSTOP, BM_SETCHECK, nppGUI._replaceStopsWithoutFindingNext, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_REPLACEANDSTOP, BM_SETCHECK, nppGUI._replaceStopsWithoutFindingNext, 0);
::SendDlgItemMessage(_hSelf, IDC_CHECK_SHOWONCEPERFOUNDLINE, BM_SETCHECK, nppGUI._finderShowOnlyOneEntryPerFoundLine, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_SHOWONCEPERFOUNDLINE, BM_SETCHECK, nppGUI._finderShowOnlyOneEntryPerFoundLine, 0);
@ -6866,10 +6874,11 @@ intptr_t CALLBACK SearchingSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
::SendDlgItemMessage(_hSelf, IDC_CHECK_FILL_DIR_FIELD_FROM_ACTIVE_DOC, BM_SETCHECK, nppGUI._fillDirFieldFromActiveDoc, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_FILL_DIR_FIELD_FROM_ACTIVE_DOC, BM_SETCHECK, nppGUI._fillDirFieldFromActiveDoc, 0);
NativeLangSpeaker* pNativeSpeaker = (NppParameters::getInstance()).getNativeLangSpeaker(); NativeLangSpeaker* pNativeSpeaker = (NppParameters::getInstance()).getNativeLangSpeaker();
wstring tipText = pNativeSpeaker->getLocalizedStrFromID("searchingInSelThresh-tip", L"Number of selected characters in edit zone to automatically check the \"In selection\" checkbox when the Find dialog is activated. The maximum value is 1024. Set the value to 0 to disable auto-checking."); wstring tipInSelectionText = pNativeSpeaker->getLocalizedStrFromID("searchingInSelThresh-tip", L"Minimum number of selected characters in edit zone to automatically check the \"In selection\" checkbox when the Find dialog is activated. The maximum value is $INT_REPLACE$. Set the value to 0 to disable auto-checking.");
_tipInSelThresh = CreateToolTip(IDC_INSELECTION_THRESH_QUESTION_BUTTON, _hSelf, _hInst, const_cast<PTSTR>(tipText.c_str()), pNativeSpeaker->isRTL()); tipInSelectionText = stringReplace(tipInSelectionText, L"$INT_REPLACE$", std::to_wstring(FINDREPLACE_INSELECTION_THRESHOLD_DEFAULT));
_tipInSelThresh = CreateToolTip(IDC_INSELECTION_THRESH_QUESTION_BUTTON, _hSelf, _hInst, const_cast<PTSTR>(tipInSelectionText.c_str()), pNativeSpeaker->isRTL());
if (_tipInSelThresh != nullptr) if (_tipInSelThresh != nullptr)
{ {
::SendMessage(_tipInSelThresh, TTM_SETMAXTIPWIDTH, 0, 260); ::SendMessage(_tipInSelThresh, TTM_SETMAXTIPWIDTH, 0, 260);
@ -6878,6 +6887,18 @@ intptr_t CALLBACK SearchingSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
::SendMessage(_tipInSelThresh, TTM_SETDELAYTIME, TTDT_AUTOPOP, MAKELPARAM((30000), (0))); ::SendMessage(_tipInSelThresh, TTM_SETDELAYTIME, TTDT_AUTOPOP, MAKELPARAM((30000), (0)));
} }
wstring tipFillFindWhatText = pNativeSpeaker->getLocalizedStrFromID("searchingFillFindWhat-tip", L"Maximum number of selected characters in edit zone to fill automatically the \"Find what\" field when the Ctrl-F is triggered. The maximum value is $INT_REPLACE$, which is the maximum size of \"Find what\" field, limited by the system.");
tipFillFindWhatText = stringReplace(tipFillFindWhatText, L"$INT_REPLACE$", std::to_wstring(FINDREPLACE_MAXLENGTH - 1));
_tipFillFindWhatThresh = CreateToolTip(IDC_FILLFINDWHAT_THRESH_QUESTION_BUTTON, _hSelf, _hInst, const_cast<PTSTR>(tipFillFindWhatText.c_str()), pNativeSpeaker->isRTL());
if (_tipFillFindWhatThresh != nullptr)
{
::SendMessage(_tipFillFindWhatThresh, TTM_SETMAXTIPWIDTH, 0, 260);
// Make tip stay 30 seconds
::SendMessage(_tipFillFindWhatThresh, TTM_SETDELAYTIME, TTDT_AUTOPOP, MAKELPARAM((30000), (0)));
}
return TRUE; return TRUE;
} }
@ -6895,7 +6916,7 @@ intptr_t CALLBACK SearchingSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
{ {
auto hdc = reinterpret_cast<HDC>(wParam); auto hdc = reinterpret_cast<HDC>(wParam);
const int dlgCtrlID = ::GetDlgCtrlID(reinterpret_cast<HWND>(lParam)); const int dlgCtrlID = ::GetDlgCtrlID(reinterpret_cast<HWND>(lParam));
if (dlgCtrlID == IDC_INSELECTION_THRESH_QUESTION_BUTTON) if (dlgCtrlID == IDC_INSELECTION_THRESH_QUESTION_BUTTON || dlgCtrlID == IDC_FILLFINDWHAT_THRESH_QUESTION_BUTTON)
{ {
return NppDarkMode::onCtlColorDlgLinkText(hdc, true); return NppDarkMode::onCtlColorDlgLinkText(hdc, true);
} }
@ -6914,8 +6935,9 @@ intptr_t CALLBACK SearchingSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
case WM_COMMAND: case WM_COMMAND:
{ {
if ((LOWORD(wParam) == IDC_INSELECTION_THRESHOLD_EDIT) && if (HIWORD(wParam) == EN_CHANGE)
(HIWORD(wParam) == EN_CHANGE)) {
if (LOWORD(wParam) == IDC_INSELECTION_THRESHOLD_EDIT)
{ {
constexpr int stringSize = 5; constexpr int stringSize = 5;
wchar_t str[stringSize]{}; wchar_t str[stringSize]{};
@ -6923,15 +6945,15 @@ intptr_t CALLBACK SearchingSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
if (lstrcmp(str, L"") == 0) if (lstrcmp(str, L"") == 0)
{ {
::SetDlgItemInt(_hSelf, IDC_INSELECTION_THRESHOLD_EDIT, nppGUI._inSelectionAutocheckThreshold, FALSE); ::SetDlgItemInt(_hSelf, IDC_INSELECTION_THRESHOLD_EDIT, FINDREPLACE_INSELECTION_THRESHOLD_DEFAULT, FALSE);
return FALSE; return TRUE;
} }
UINT newValue = ::GetDlgItemInt(_hSelf, IDC_INSELECTION_THRESHOLD_EDIT, nullptr, FALSE); UINT newValue = ::GetDlgItemInt(_hSelf, IDC_INSELECTION_THRESHOLD_EDIT, nullptr, FALSE);
if (static_cast<int>(newValue) == nppGUI._inSelectionAutocheckThreshold) if (static_cast<int>(newValue) == nppGUI._inSelectionAutocheckThreshold)
{ {
return FALSE; return TRUE;
} }
if (newValue > FINDREPLACE_INSELECTION_THRESHOLD_DEFAULT) if (newValue > FINDREPLACE_INSELECTION_THRESHOLD_DEFAULT)
@ -6944,6 +6966,42 @@ intptr_t CALLBACK SearchingSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
return TRUE; return TRUE;
} }
else if (LOWORD(wParam) == IDC_FILLFINDWHAT_THRESHOLD_EDIT)
{
constexpr int stringSize = 6;
wchar_t str[stringSize]{};
::GetDlgItemText(_hSelf, IDC_FILLFINDWHAT_THRESHOLD_EDIT, str, stringSize);
if (lstrcmp(str, L"") == 0)
{
::SetDlgItemInt(_hSelf, IDC_FILLFINDWHAT_THRESHOLD_EDIT, FILL_FINDWHAT_THRESHOLD_DEFAULT, FALSE);
return TRUE;
}
UINT newValue = ::GetDlgItemInt(_hSelf, IDC_FILLFINDWHAT_THRESHOLD_EDIT, nullptr, FALSE);
if (static_cast<int>(newValue) == nppGUI._fillFindWhatThreshold)
{
return TRUE;
}
if (newValue >= FINDREPLACE_MAXLENGTH)
{
newValue = FINDREPLACE_MAXLENGTH - 1;
::SetDlgItemInt(_hSelf, IDC_FILLFINDWHAT_THRESHOLD_EDIT, newValue, FALSE);
}
if (newValue == 0)
{
newValue = 1;
::SetDlgItemInt(_hSelf, IDC_FILLFINDWHAT_THRESHOLD_EDIT, newValue, FALSE);
}
nppGUI._fillFindWhatThreshold = newValue;
return TRUE;
}
}
switch (wParam) switch (wParam)
{ {
@ -6951,6 +7009,10 @@ intptr_t CALLBACK SearchingSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR
{ {
nppGUI._fillFindFieldWithSelected = isCheckedOrNot(IDC_CHECK_FILL_FIND_FIELD_WITH_SELECTED); nppGUI._fillFindFieldWithSelected = isCheckedOrNot(IDC_CHECK_FILL_FIND_FIELD_WITH_SELECTED);
::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_FILL_FIND_FIELD_SELECT_CARET), nppGUI._fillFindFieldWithSelected ? TRUE : FALSE); ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_FILL_FIND_FIELD_SELECT_CARET), nppGUI._fillFindFieldWithSelected ? TRUE : FALSE);
::EnableWindow(::GetDlgItem(_hSelf, IDC_FILLFINDWHAT_THRESH_QUESTION_BUTTON), nppGUI._fillFindFieldWithSelected ? TRUE : FALSE);
::EnableWindow(::GetDlgItem(_hSelf, IDC_FILLFINDWHAT_THRESHOLD_EDIT), nppGUI._fillFindFieldWithSelected ? TRUE : FALSE);
::EnableWindow(::GetDlgItem(_hSelf, IDC_FILLFINDWHAT_THRESHOLD_STATIC), nppGUI._fillFindFieldWithSelected ? TRUE : FALSE);
if (!nppGUI._fillFindFieldWithSelected) if (!nppGUI._fillFindFieldWithSelected)
{ {
::SendDlgItemMessage(_hSelf, IDC_CHECK_FILL_FIND_FIELD_SELECT_CARET, BM_SETCHECK, BST_UNCHECKED, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_FILL_FIND_FIELD_SELECT_CARET, BM_SETCHECK, BST_UNCHECKED, 0);

View File

@ -273,6 +273,7 @@ public:
private: private:
HWND _tipInSelThresh = nullptr; HWND _tipInSelThresh = nullptr;
HWND _tipFillFindWhatThresh = nullptr;
intptr_t CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) override; intptr_t CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) override;
}; };

View File

@ -474,6 +474,9 @@
#define IDC_INSELECTION_THRESHOLD_EDIT 6911 #define IDC_INSELECTION_THRESHOLD_EDIT 6911
#define IDC_INSELECTION_THRESH_QUESTION_BUTTON 6912 #define IDC_INSELECTION_THRESH_QUESTION_BUTTON 6912
#define IDC_CHECK_FILL_DIR_FIELD_FROM_ACTIVE_DOC 6913 #define IDC_CHECK_FILL_DIR_FIELD_FROM_ACTIVE_DOC 6913
#define IDC_FILLFINDWHAT_THRESH_QUESTION_BUTTON 6914
#define IDC_FILLFINDWHAT_THRESHOLD_EDIT 6915
#define IDC_FILLFINDWHAT_THRESHOLD_STATIC 6916
#define IDD_PREFERENCE_SUB_DARKMODE 7100 #define IDD_PREFERENCE_SUB_DARKMODE 7100

View File

@ -1774,7 +1774,7 @@
<!-- Attention : Don't modify the name of styleID="0" --> <!-- Attention : Don't modify the name of styleID="0" -->
<WidgetStyle name="Default Style" styleID="32" fgColor="000000" bgColor="FFFFFF" fontName="Courier New" fontStyle="0" fontSize="10" /> <WidgetStyle name="Default Style" styleID="32" fgColor="000000" bgColor="FFFFFF" fontName="Courier New" fontStyle="0" fontSize="10" />
<WidgetStyle name="Indent guideline style" styleID="37" fgColor="C0C0C0" bgColor="FFFFFF" fontName="" fontStyle="0" fontSize="" /> <WidgetStyle name="Indent guideline style" styleID="37" fgColor="C0C0C0" bgColor="FFFFFF" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Brace highlight style" styleID="34" fgColor="FF0000" bgColor="FFFFFF" fontName="" fontStyle="1" fontSize="10" /> <WidgetStyle name="Brace highlight style" styleID="34" fgColor="FF0000" bgColor="FFFFFF" fontName="" fontStyle="1" fontSize="" />
<WidgetStyle name="Bad brace colour" styleID="35" fgColor="800000" bgColor="FFFFFF" fontName="" fontStyle="0" fontSize="" /> <WidgetStyle name="Bad brace colour" styleID="35" fgColor="800000" bgColor="FFFFFF" fontName="" fontStyle="0" fontSize="" />
<WidgetStyle name="Current line background colour" styleID="0" bgColor="E8E8FF" /> <WidgetStyle name="Current line background colour" styleID="0" bgColor="E8E8FF" />
<!-- In below rule 'fgColor' attribute for 'Selected text colour' can be unlocked with a enableSelectFgColor.xml file --> <!-- In below rule 'fgColor' attribute for 'Selected text colour' can be unlocked with a enableSelectFgColor.xml file -->
@ -1825,6 +1825,6 @@
<WidgetStyle name="Document map" styleID="0" fgColor="FF8000" bgColor="FFFFFF" /> <WidgetStyle name="Document map" styleID="0" fgColor="FF8000" bgColor="FFFFFF" />
<WidgetStyle name="EOL custom color" styleID="0" fgColor="DADADA" /> <WidgetStyle name="EOL custom color" styleID="0" fgColor="DADADA" />
<WidgetStyle name="Non-printing characters custom color" styleID="0" fgColor="FFB56A" /> <WidgetStyle name="Non-printing characters custom color" styleID="0" fgColor="FFB56A" />
<WidgetStyle name="Global override" styleID="0" fgColor="FFFF80" bgColor="FF8000" fontName="Courier New" fontStyle="0" fontSize="10" /> <WidgetStyle name="Global override" styleID="0" fgColor="FFFF80" bgColor="FF8000" fontName="Courier New" fontStyle="0" fontSize="" />
</GlobalStyles> </GlobalStyles>
</NotepadPlus> </NotepadPlus>

View File

@ -408,6 +408,101 @@ bool launchUpdater(const std::wstring& updaterFullPath, const std::wstring& upda
return true; return true;
} }
DWORD nppUacSave(const wchar_t* wszTempFilePath, const wchar_t* wszProtectedFilePath2Save)
{
if ((lstrlenW(wszTempFilePath) == 0) || (lstrlenW(wszProtectedFilePath2Save) == 0)) // safe check (lstrlen returns 0 for possible nullptr)
return ERROR_INVALID_PARAMETER;
if (!doesFileExist(wszTempFilePath))
return ERROR_FILE_NOT_FOUND;
DWORD dwRetCode = ERROR_SUCCESS;
bool isOutputReadOnly = false;
bool isOutputHidden = false;
bool isOutputSystem = false;
WIN32_FILE_ATTRIBUTE_DATA attributes{};
attributes.dwFileAttributes = INVALID_FILE_ATTRIBUTES;
if (getFileAttributesExWithTimeout(wszProtectedFilePath2Save, &attributes))
{
if (attributes.dwFileAttributes != INVALID_FILE_ATTRIBUTES && !(attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
isOutputReadOnly = (attributes.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0;
isOutputHidden = (attributes.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0;
isOutputSystem = (attributes.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) != 0;
if (isOutputReadOnly) attributes.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
if (isOutputHidden) attributes.dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN;
if (isOutputSystem) attributes.dwFileAttributes &= ~FILE_ATTRIBUTE_SYSTEM;
if (isOutputReadOnly || isOutputHidden || isOutputSystem)
::SetFileAttributes(wszProtectedFilePath2Save, attributes.dwFileAttributes); // temporarily remove the problematic ones
}
}
// cannot use simple MoveFile here as it retains the tempfile permissions when on the same volume...
if (!::CopyFileW(wszTempFilePath, wszProtectedFilePath2Save, FALSE))
{
// fails if the destination file exists and has the R/O and/or Hidden attribute set
dwRetCode = ::GetLastError();
}
else
{
// ok, now dispose of the tempfile used
::DeleteFileW(wszTempFilePath);
}
// set back the possible original file attributes
if (isOutputReadOnly || isOutputHidden || isOutputSystem)
{
if (isOutputReadOnly) attributes.dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
if (isOutputHidden) attributes.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
if (isOutputSystem) attributes.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM;
::SetFileAttributes(wszProtectedFilePath2Save, attributes.dwFileAttributes);
}
return dwRetCode;
}
DWORD nppUacSetFileAttributes(const DWORD dwFileAttribs, const wchar_t* wszFilePath)
{
if (lstrlenW(wszFilePath) == 0) // safe check (lstrlen returns 0 for possible nullptr)
return ERROR_INVALID_PARAMETER;
if (!doesFileExist(wszFilePath))
return ERROR_FILE_NOT_FOUND;
if (dwFileAttribs == INVALID_FILE_ATTRIBUTES || (dwFileAttribs & FILE_ATTRIBUTE_DIRECTORY))
return ERROR_INVALID_PARAMETER;
if (!::SetFileAttributes(wszFilePath, dwFileAttribs))
return ::GetLastError();
return ERROR_SUCCESS;
}
DWORD nppUacMoveFile(const wchar_t* wszOriginalFilePath, const wchar_t* wszNewFilePath)
{
if ((lstrlenW(wszOriginalFilePath) == 0) || (lstrlenW(wszNewFilePath) == 0)) // safe check (lstrlen returns 0 for possible nullptr)
return ERROR_INVALID_PARAMETER;
if (!doesFileExist(wszOriginalFilePath))
return ERROR_FILE_NOT_FOUND;
if (!::MoveFileEx(wszOriginalFilePath, wszNewFilePath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH))
return ::GetLastError();
else
return ERROR_SUCCESS;
}
DWORD nppUacCreateEmptyFile(const wchar_t* wszNewEmptyFilePath)
{
if (lstrlenW(wszNewEmptyFilePath) == 0) // safe check (lstrlen returns 0 for possible nullptr)
return ERROR_INVALID_PARAMETER;
if (doesFileExist(wszNewEmptyFilePath))
return ERROR_FILE_EXISTS;
Win32_IO_File file(wszNewEmptyFilePath);
if (!file.isOpened())
return file.getLastErrorCode();
return ERROR_SUCCESS;
}
} // namespace } // namespace
@ -418,6 +513,45 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE /*hPrevInstance
{ {
g_nppStartTimePoint = std::chrono::steady_clock::now(); g_nppStartTimePoint = std::chrono::steady_clock::now();
// Notepad++ UAC OPS /////////////////////////////////////////////////////////////////////////////////////////////
if ((lstrlenW(pCmdLine) > 0) && (__argc >= 2)) // safe (if pCmdLine is NULL, lstrlen returns 0)
{
const wchar_t* wszNppUacOpSign = __wargv[1];
if (lstrlenW(wszNppUacOpSign) > lstrlenW(L"#UAC-#"))
{
if ((__argc == 4) && (wcscmp(wszNppUacOpSign, NPP_UAC_SAVE_SIGN) == 0))
{
// __wargv[x]: 2 ... tempFilePath, 3 ... protectedFilePath2Save
return static_cast<int>(nppUacSave(__wargv[2], __wargv[3]));
}
if ((__argc == 4) && (wcscmp(wszNppUacOpSign, NPP_UAC_SETFILEATTRIBUTES_SIGN) == 0))
{
// __wargv[x]: 2 ... dwFileAttributes (string), 3 ... filePath
try
{
return static_cast<int>(nppUacSetFileAttributes(static_cast<DWORD>(std::stoul(std::wstring(__wargv[2]))), __wargv[3]));
}
catch ([[maybe_unused]] const std::exception& e)
{
return static_cast<int>(ERROR_INVALID_PARAMETER); // conversion error (check e.what() for details)
}
}
if ((__argc == 4) && (wcscmp(wszNppUacOpSign, NPP_UAC_MOVEFILE_SIGN) == 0))
{
// __wargv[x]: 2 ... originalFilePath, 3 ... newFilePath
return static_cast<int>(nppUacMoveFile(__wargv[2], __wargv[3]));
}
if ((__argc == 3) && (wcscmp(wszNppUacOpSign, NPP_UAC_CREATEEMPTYFILE_SIGN) == 0))
{
// __wargv[x]: 2 ... newEmptyFilePath
return static_cast<int>(nppUacCreateEmptyFile(__wargv[2]));
}
}
} // Notepad++ UAC OPS////////////////////////////////////////////////////////////////////////////////////////////
bool TheFirstOne = true; bool TheFirstOne = true;
::SetLastError(NO_ERROR); ::SetLastError(NO_ERROR);
::CreateMutex(NULL, false, L"nppInstance"); ::CreateMutex(NULL, false, L"nppInstance");