Merge pull request #5541 from RaiKoHoff/Dev_Master
Some checks failed
Build / ${{ matrix.platform }} ${{ matrix.configuration }} (Release, ARM64) (push) Has been cancelled
Build / ${{ matrix.platform }} ${{ matrix.configuration }} (Release, Win32) (push) Has been cancelled
Build / ${{ matrix.platform }} ${{ matrix.configuration }} (Release, x64) (push) Has been cancelled
Build / ${{ matrix.platform }} ${{ matrix.configuration }} (Release, x64_AVX2) (push) Has been cancelled

fix save file only if "strip trailing blanks" is active and there are trailing blanks
This commit is contained in:
Pairi Daiza 2026-02-20 20:25:13 +01:00 committed by GitHub
commit be7ee0924d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 816 additions and 749 deletions

666
Readme.md
View File

@ -1,613 +1,157 @@
# Notepad3
Notepad3 is free and open source. Your support helps keep development active.
**A fast, lightweight, Scintilla-based text editor for Windows**
[![Sponsor](https://img.shields.io/github/sponsors/rizonesoft?style=flat-square&logo=github)](https://github.com/sponsors/rizonesoft)
[![Donate](https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square&logo=paypal)](https://www.paypal.com/donate/?hosted_button_id=7UGGCSDUZJPFE)
[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg?style=flat-square)](https://opensource.org/licenses/BSD-3-Clause)
### Build Status
Continuous integration ensures code quality across compilers and platforms.
[![AppVeyor](https://img.shields.io/appveyor/ci/rizonesoft/notepad3/master.svg?style=flat-square&label=AppVeyor)](https://ci.appveyor.com/project/rizonesoft/notepad3/branch/master)
[![CI](https://img.shields.io/github/actions/workflow/status/rizonesoft/Notepad3/build.yml?style=flat-square&label=CI)](https://github.com/rizonesoft/Notepad3/actions/workflows/build.yml)
[![Latest Release](https://img.shields.io/github/v/release/rizonesoft/Notepad3?style=flat-square&label=Release&color=0e7490)](https://rizonesoft.com/downloads/notepad3/)
[![AppVeyor](https://img.shields.io/appveyor/ci/rizonesoft/notepad3/master.svg?style=flat-square&label=AppVeyor)](https://ci.appveyor.com/project/rizonesoft/notepad3/branch/master)
[![Release](https://img.shields.io/github/v/release/rizonesoft/Notepad3?style=flat-square&label=Release&color=0e7490)](https://rizonesoft.com/downloads/notepad3/)
[![Nightly](https://img.shields.io/github/v/release/rizonesoft/Notepad3?include_prereleases&style=flat-square&label=Nightly&color=6e40c9)](https://github.com/rizonesoft/Notepad3/releases)
### Tech Stack
Built with modern C++ on the powerful Scintilla editing component.
[Website](https://rizonesoft.com/downloads/notepad3/) · [Downloads](https://github.com/rizonesoft/Notepad3/releases) · [Documentation](https://rizonesoft.com/documents/notepad3/) · [Changelog](https://rizonesoft.com/downloads/notepad3/update) · [Sponsor](https://github.com/sponsors/rizonesoft)
[![Windows](https://img.shields.io/badge/Platform-Windows-0078D6?style=flat-square&logo=windows)](https://rizonesoft.com/downloads/notepad3/)
[![C++](https://img.shields.io/badge/Language-C%2B%2B-00599C?style=flat-square&logo=cplusplus)](https://github.com/rizonesoft/Notepad3)
[![Scintilla](https://img.shields.io/badge/Editor-Scintilla-4B8BBE?style=flat-square)](https://www.scintilla.org/)
[![Architecture](https://img.shields.io/badge/Arch-x86%20%7C%20x64%20%7C%20x64--AVX2%20%7C%20ARM64-informational?style=flat-square)](https://rizonesoft.com/downloads/notepad3/)
---
Notepad3 is a fast and light-weight Scintilla-based text editor with syntax highlighting. It has a small memory footprint, but is powerful enough to handle most programming jobs. [Download Notepad3 here](https://rizonesoft.com/downloads/notepad3).
Notepad3 is a free, open-source text editor with syntax highlighting for Windows. Built on the [Scintilla](https://www.scintilla.org/) editing component and [Lexilla](https://www.scintilla.org/Lexilla.html) lexer library, it has a small memory footprint while being powerful enough for professional programming and everyday text editing.
> *Notepad3 is based on code from Florian Balmer's Notepad2 and XhmikosR's Notepad2-mod. MiniPath is based on code from Florian Balmer's metapath.*
> Notepad3 is based on code from Florian Balmer's [Notepad2](https://www.flos-freeware.ch/notepad2.html) and XhmikosR's [Notepad2-mod](https://xhmikosr.github.io/notepad2-mod/). MiniPath is based on Florian Balmer's metapath.
## Important links!
* Download page - https://rizonesoft.com/downloads/notepad3
* Latest changelog (release notes) - https://rizonesoft.com/downloads/notepad3/update
* Full changelog (all versions/builds) - [Notepad3 - Full Changelog](https://raw.githubusercontent.com/rizonesoft/Notepad3/master/Build/Changes.txt)
* Documentation - https://rizonesoft.com/documents/notepad3
<!-- TODO: Add a screenshot of the Notepad3 main window here.
Save the image as doc/screenshot.png and uncomment the line below:
![Notepad3 Screenshot](doc/screenshot.png)
-->
## Rizonesoft Support
## Features
* **[GET IN TOUCH](https://rizonesoft.com/contact-us)**
* **Premium Support** - On Rizonesoft, support is free and we will assist you the best we can. Please be patient when contacting us; there are mainly volunteers working on Rizonesoft projects, and time is a precious commodity.
### Editing
- **Code folding** with toggle-all support
- **Bookmarks** for quick navigation within files
- **Word auto-completion** with configurable fill-up characters
- **Mark all occurrences** of a selected word with occurrence count display
- **Find and Replace** with [Oniguruma](https://github.com/kkos/oniguruma) regular expression engine
- **Undo/Redo** that preserves selection state
- **Visual Studiostyle** copy/paste of the current line (when nothing is selected)
- **Virtual space** rectangular selection (Alt+Drag)
- **Accelerated word navigation** with configurable delimiters
- **Insert GUIDs** directly into your document
## Changes compared to Flo's official [Notepad2](https://www.flos-freeware.ch/notepad2.html) (made in [Notepad2-mod](https://xhmikosr.github.io/notepad2-mod/)):
### Syntax Highlighting
Over 55 languages supported, including:
* Code folding
* Support for bookmarks
* Option to mark all occurrences of a word
* Updated Scintilla component
* Word auto-completion
* Syntax highlighting support for AutoHotkey (AHK), AutoIt3, AviSynth, Bash, CMake, CoffeeScript,
Inno Setup, LaTeX, Lua, Markdown, NSIS, Ruby, Tcl, YAML and VHDL scripts.
* Improved support for NFO ANSI art
* Other various minor changes and tweaks
> ANSI Art, Apache Config, Assembly, AutoHotkey, AutoIt3, AviSynth, Awk, Batch, C/C++, C#, CMake, CoffeeScript, CSS, CSV, D, Dart, Diff, F77/Fortran, Go, HTML/XML, Java, JavaScript, JSON, Julia, Kotlin, KiXtart, LaTeX, Lua, Makefiles, Markdown, MATLAB, Nim, NSIS, Pascal, Perl, PHP, PowerShell, Python, R/S-Plus, Registry, Resource Script, Ruby, Rust, Shell Script, SQL, SystemVerilog, Tcl, TOML, VBScript, VHDL, Verilog, Visual Basic, YAML, and more.
## Changes compared to the Notepad2-mod fork:
### File Handling
- **AES-256 Rijndael** encryption/decryption (in-app and command-line batch tool)
- **Encoding detection** powered by [uchardet](https://www.freedesktop.org/wiki/Software/uchardet/)
- **File change monitoring** with configurable check intervals
- **Emacs file variables** support (encoding, mode, tab-width, etc.)
- **File history** that preserves caret position and encoding
- **Portable design** — runs from USB drives with relative path storage
* Additional syntax highlighting support for Awk, D, golang, MATLAB
* Regular Expression search engine ([Oniguruma](https://github.com/kkos/oniguruma))
* New toolbar icons based on Yusuke Kamiyaman's Fugue Icons (purchased by [Rizonesoft](https://rizonesoft.com))
* Hyperlink hotspot highlighting (single-click Open in Browser (Ctrl) / Load in Editor (Alt)
* Syntax highlighting support for D Source Script, Go Source Script, JSON, Makefiles, MATLAB, Nim Source Code, Power Shell Script, Resource Script, Shell Script
* New program icon and other small cosmetic changes
* In-App support for AES-256 Rijndael encryption/decryption of files (incl. external command line tool for batch processing)
* Virtual space rectangular selection box (Alt-key down)
* High-DPI awareness, including high definition toolbar icons
* Undo/Redo preserves selection
* File history preserves caret position (optional) and remembers encoding of file
* Accelerated word navigation
* Preserve caret position of items in file history
* Count occurrences of a marked selection or word
* Count and mark occurrences of matching search/find expression
* Visual Studio style copy/paste current line (no selection)
* Insert GUIDs
* Dropped support for Windows XP
* Other various minor changes, tweaks, and bugfixes
### Search
- **grepWinNP3** — integrated search-in-files tool with regex support (**Ctrl+Shift+F**)
- **Hyperlink hotspot highlighting** — Ctrl+Click to open in browser, Alt+Click to load in editor
## Supported Operating Systems:
### User Interface
- **High-DPI aware** with high-definition toolbar icons
- **Dark mode** support with customizable colors
- **Customizable status bar** with 16 configurable fields (line, column, encoding, TinyExpr evaluation, Unicode code point, and more)
- **Customizable toolbar labels** — display function names next to icons
- **Zoom** from 10% to 1000% (Ctrl+Scroll or toolbar buttons)
- **Transparent window mode** with configurable opacity
* Windows 7, 8, 8.1, 10, and 11 (both 32-bit and 64-bit)
### Localization
27 language translations:
<hr/>
> Afrikaans, Belarusian, Chinese (Simplified & Traditional), Dutch, English (US & UK), Finnish, French, German, Greek, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean, Polish, Portuguese (Brazil & Portugal), Russian, Slovak, Spanish (Spain & Latin America), Swedish, Turkish, Vietnamese
# References
### Companion Tools
- **[MiniPath](minipath/)** — fast file browser plugin (Ctrl+M)
- **[grepWinNP3](grepWinNP3/)** — powerful search-and-replace across files
Seen on Nsane Forums: [Notepad3 is an advanced text editor...](https://www.nsaneforums.com/topic/382910-guidereview-notepad3-is-an-advanced-text-editor-that-supports-many-programming-languages/), a review of **Notepad3** posted by the moderator [Karston](https://www.nsaneforums.com/profile/12756-karlston/) at [nsane.forums](https://www.nsaneforums.com/).
## System Requirements
**Notepad3's review**: **[Notepad3 is an advanced text editor that supports many programming languages](https://www.ghacks.net/2020/08/11/notepad3-is-an-advanced-text-editor-that-supports-many-programming-languages/)**.
- **OS:** Windows 8.1, 10, or 11
- **Architectures:** x86 (Win32), x64, x64 with AVX2, ARM64
<hr/>
## Download & Install
# **Notepad3 Settings (Notepad3.ini)**
| Channel | Link |
|---------|------|
| **Stable Release** | [rizonesoft.com/downloads/notepad3](https://rizonesoft.com/downloads/notepad3/) |
| **GitHub Releases** | [github.com/rizonesoft/Notepad3/releases](https://github.com/rizonesoft/Notepad3/releases) |
| **Nightly Builds** | [Pre-releases on GitHub](https://github.com/rizonesoft/Notepad3/releases) |
Notepad3 is fully **portable** — no installation required. Extract the archive and run `Notepad3.exe`. Settings are stored in `Notepad3.ini` alongside the executable. See [Replacing Windows Notepad](https://rizonesoft.com/documents/notepad3/) for system-wide integration.
## **`[Notepad3]`**
## Building from Source
This section can be used to redirect to a settings file which will be used by Notepad3.
If a non-elevated user is not allowed to write to the program directory of Notepad3.exe,
the side-by-side Notepad3.ini can point to a place where the user is allowed to write their settings,
for example:
Notepad3 is built with **Visual Studio 2022** (toolset v143) targeting the Windows SDK.
`Notepad3.ini=%APPDATA%\Rizonesoft\Notepad3\Notepad3.ini`
```powershell
# Restore NuGet packages (required once)
nuget restore Notepad3.sln
or a to have user-specific settings:
# Build a specific platform
Build\Build_x64.cmd Release
`Notepad3.ini=%WINDIR%\Notepad3-%USERNAME%.ini`
# Build all platforms (Win32, x64, x64_AVX2, ARM64)
Build\BuildAll.cmd Release
## **`[Settings]`**
These settings are read and written by Notepad3s user interface.
For example, all Menu ? Settings will go here.
#### `SettingsVersion=5`
#### `Favorites=%APPDATA%\Rizonesoft\Notepad3\Favorites\`
## **`[Settings2]`**
This section offers some advanced Notepad3 program settings, and can only be edited manually.
Press Ctrl+F7 to open the Notepad3 ini-file. Most changes only take effect upon restarting Notepad3.
#### `PreferredLanguageLocaleName=en-US`
The default value for the already supported languages is defined by the: “OS language setting”.
- The fallback is: “en-US”.
##### Available languages:
```
English/United States (en-US) (internal default)
Afrikaans/South Africa (af-ZA)
Belarusian/Belarus (be-BY)
German/Germany (de-DE)
Greek/Greece (el-GR)
English/United Kingdom (en-GB)
Spanish/Spain (es-ES)
French/France (fr-FR)
Hindi/India (hi-IN)
Hungarian/Hungary (hu-HU)
Indonesian/Indonesia (id-ID)
Italian/Italy (it-IT)
Japanese/Japan (ja-JP)
Korean/Korea (ko-KR)
Dutch/Netherlands (nl-NL)
Polish/Poland (pl-PL)
Portuguese/Brazil (pt-BR)
Portuguese/Portugal (pt-PT)
Russian/Russia (ru/RU)
Slovak/Slovakia (sk-SK)
Swedish/Sweden (sv-SE)
Turkish/Turkey (tr-TR)
Vietnamese/Vietnam (vi-VN)
Chinese Simplified/China (zh-CN)
Chinese Traditional/Taiwan (zh-TW)
# Or use MSBuild directly
msbuild Notepad3.sln /m /p:Configuration=Release /p:Platform=x64
```
#### `IMEInteraction=0`
Run `Version.ps1` before building to generate version headers from templates in `Versions\`.
#### `DateTimeFormat=`
## Configuration
- (-> (Locale dependent short format)
Notepad3 uses a portable INI file for all settings. Press **Ctrl+F7** to open it directly in the editor.
#### `DateTimeLongFormat=`
- **UI settings** (`[Settings]`) — managed through Menu → Settings
- **Advanced settings** (`[Settings2]`) — edit manually; most require a restart
- **Status bar** (`[Statusbar Settings]`) — customize field layout, order, and width
- **Toolbar labels** (`[Toolbar Labels]`) — show function names next to icons
- (-> (Locale dependent long format)
📖 **Full configuration reference:** [doc/Configuration.md](doc/Configuration.md)
Specify the short/long date and time formats. This is the format parameter passed to
the `strftime()` function.
Note that the locale will be set to English (because of the English Visual C++ Run-time
Library used by Notepad3).
## Contributing
#### `TimeStampRegEx=`
Contributions are welcome! Here's how to help:
- (-> \$Date:[^\$]+\$) (Find-Pattern to Update Stamps)
1. **Report bugs** — [Open an issue](https://github.com/rizonesoft/Notepad3/issues) with steps to reproduce
2. **Submit pull requests** — Fork the repo, create a feature branch, and submit a PR against `master`
3. **Translate** — Add or improve translations in the `language\` directory
4. **Spread the word** — Star the repo and share with others
#### `TimeStampFormat=`
For support, visit [rizonesoft.com/contact-us](https://rizonesoft.com/contact-us).
- (-> \\$Date:[^\\$]+\\$ | $Date: %Y/%m/%d %H:%M:%S $
- (-> $Date: %s $) (Print format should fit to TimeStampRegEx)
## Credits
This parameter is used as a regex pattern to match time-stamps which will be updated to
current date-time by `Shift+F5`, e.g. `$Date: 2018/04/26 00:52:39 $`
Notepad3 builds upon the work of:
- Default `DateTime` formats are:
1. SHORT: `[Settings2] DateTimeFormat=` (empty) - Notepad3's language locale short '<time> <date>' format is used
2. LONG: `[Settings2] DateTimeLongFormat=` (empty) - Notepad3's language locale long '<time> <date>' format is used
3. TIME_STAMP: `[Settings2] TimeStampFormat=` (empty) - "$Date: %s $" where '%s' is replaced by time/date in
`DateTimeFormat`. E.g. `[Settings2] TimeStampFormat=#TimeStamp=2020-07-21 16:02:23 #`
- All `DateTime` formats accept the [`strftime()`](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strftime-wcsftime-strftime-l-wcsftime-l?view=vs-2019) format string.
Addon: `TimeStampFormat` accepts '%s' (which is no valid `strftime()` formatting code) - a placeholder for a `DateTimeFormat` formatted current date/time string. (mixing of `strftime()` and '%s' is not allowed).
- If you define your own `TimeStampFormat`, you should define the corresponding `TimeStampRegEx` regular expression pattern accordingly (for our example: `[Settings2] TimeStampRegEx="#TimeStamp=[^#]+#"`), so that` Update Timestamps` operation can find and update them correctly.
- Additional Menu Point: Insert Current Timestamp.
| Project | Author | Role |
|---------|--------|------|
| [Notepad2](https://www.flos-freeware.ch/notepad2.html) | Florian Balmer | Original editor |
| [Notepad2-mod](https://xhmikosr.github.io/notepad2-mod/) | XhmikosR | Extended fork |
| [Scintilla](https://www.scintilla.org/) 5.5.8 | Neil Hodgson | Editing component |
| [Lexilla](https://www.scintilla.org/Lexilla.html) 5.4.6 | Neil Hodgson | Syntax highlighting |
| [Oniguruma](https://github.com/kkos/oniguruma) | K. Kosako | Regex engine |
| [uchardet](https://www.freedesktop.org/wiki/Software/uchardet/) | Mozilla / freedesktop | Encoding detection |
| Fugue Icons | Yusuke Kamiyamane | Toolbar icons |
#### `DefaultDirectory=`
## Reviews
Specify the default directory for the open and save dialogs, used if no file is opened.
- Path-names can be relative to the Notepad3 program directory.
- [Notepad3 is an advanced text editor that supports many programming languages](https://www.ghacks.net/2020/08/11/notepad3-is-an-advanced-text-editor-that-supports-many-programming-languages/) — gHacks
- [Notepad3 review on Nsane Forums](https://www.nsaneforums.com/topic/382910-guidereview-notepad3-is-an-advanced-text-editor-that-supports-many-programming-languages/) — Nsane Forums
#### `DefaultExtension=txt`
## License
Specify the default extension for saved files (omit the leading dot, just like txt or html).
Notepad3 is licensed under the [BSD 3-Clause License](License.txt).
#### `DenyVirtualSpaceAccess=0`
Copyright © 20082026 [Rizonesoft](https://rizonesoft.com). All rights reserved.
#### `filebrowser.exe=minipath.exe`
---
Specify the path of an external program that is launched when pressing the Browse toolbar button.
Defaults to `minipath.exe`, which is the file browser plugin.
You can specify additional command line switches, and the file currently opened in Notepad3 will be appended as the last command line parameter.
Note: Due to special treatment of quotes by the Win32 ini-file APIs, pathnames with spaces need to be quadruple-quoted (""path to/file.exe""), but only double-quoted if there's additional command line arguments ("path to/file.exe" /arg).
On the other hand, our preferred file browser is `minipath.exe` (Menu->File->Browse... Ctrl+M) + Toolbar-Button.
If you don't like it, you can configure e.g.
- [Settings2] filebrowser.exe=explorer.exe (system's file explorer), or
- [Settings2] filebrowser.exe=Explorer++.exe (https://explorerplusplus.com/) (side-by-side Notepad3), or
- [Settings2] filebrowser.exe=Q-Dir_x64+.exe (https://www.softwareok.de/?seite=Freeware/Q-Dir/) (side-by-side Notepad3)
#### `grepWin.exe=grepWinNP3.exe`
We have integrated a powerful external tool called **grepWinNP3**.
**grepWinNP3** is a search and replace tool which can use regular expressions to perform its job.
This allows you to perform much more powerful search and replace operations in files.
**grepWinNP3** can be launched:
- from "File --> Launch --> Search in Files"
- or from "Edit --> Search --> Search in Files"
- or simply with "`Ctrl+Shift+F`"
#### `FileCheckInterval=2000`
The interval (in milliseconds) to check for external modification of the currently opened file.
- Defaults is 2000 msec.
- Min: 200[msec] - if equal or less, notify immediately.
#### `FileChangedIndicator=[@]`
#### `FileDeletedIndicator=[X]`
#### `FileDlgFilters=`
Specify filters for the open and save dialogs
- (Example: `Text Files|*.txt;*.wtx;*.log;*.asc;*.doc;*.diz;*.nfo|All Files|*.*`).
#### `FileLoadWarningMB=4`
The size limit, in megabytes, to display a warning message for large files.
- A value of 0 disables the warning.
#### `MultiFileArg=0`
Control if Notepad3 should allow multiple files on the command line (set to 1).
The default behavior is to accept only a single file, without quoted spaces, like Windows Notepad (set to 0).
The command line switches + and - can be used to override this setting on the fly, and the /z command-line switch has the same effect as the - switch.
#### `NoCGIGuess=0`
Set to 1 to disable simple language detection for cgi and fcgi files.
#### `NoCopyLineOnEmptySelection=0`
NoCopyLineOnEmptySelection=1 to avoid the copy line (`Ctrl+C`) on empty selection.
#### `NoCutLineOnEmptySelection=0`
NoCutLineOnEmptySelection=1 to avoid the cut line (`Ctrl+X`) on empty selection.
#### `NoFadeHidden=0`
Set to 1 to disable fading of hidden objects in file lists (such as Favorites, etc.).
#### `NoFileVariables=0`
Set to 1 to disable file variable parsing.
Encoding tag parsing can be disabled in the Menu ? File ? Encoding ? Default dialog box.
Notepad3 can parse a few of the Emacs variables that can be used in source code files.
The first 512 bytes of a file (and, if nothing is found, also the last 512 bytes) are checked for the following constructs (can be manually disabled in the ini-file, or the File, Encoding, Default dialog box, respectively):
```
coding: utf-8;
mode: python;
tab-width: 8;
c-basic-indent: 2;
indent-tabs-mode: nil;
c-tab-always-indent: true;
fill-column: 64;
truncate-lines: false;
enable-local-variables: true;
```
`coding`: Serves as a file encoding tag. Details about using encoding tags are outlined in the
Notepad2 Encoding Tutorial.
`mode`: Indicates the syntax scheme to be used, and is either the name of a scheme, or a
file name extension.
`tab-width`:
`c-basic-indent`: Denote tab and indentation settings.
`indent-tabs-mode`: Determines whether to insert tabs as spaces (nil, false or 0)
or not (true or 1).
`c-tab-always-indent`: Configures whether the tab key re-formats indenting white-space
(true or 1) or not (nil, false or 0).
`fill-column`: Sets the desired limit for long lines (but does not automatically display
the visual marker).
`truncate-lines`: Controls word wrap (enable: nil, false or 0; disable: true or 1).
`enable-local-variables`: Disables file variable parsing (nil, false or 0), but keeps
evaluating encoding tags.
To bypass both file variable and encoding tag parsing, reload the file with Alt+F8.
Adapt the settings mentioned above to permanently turn off file variables and encoding tags.
#### `NoHTMLGuess=0`
Set to 1 to disable simple HTML/XML detection for files without extensions.
#### `PortableMyDocs=1`
If set to 1, recent files and other path settings referring to the `My Documents` directory tree are stored relative to `My Documents`.
This enhances USB stick portability between different versions of Windows, which are using different locations for `My Documents`.
This setting has no effect if Notepad3.exe itself is located inside `My Documents` (or a sub-directory thereof).
- The default is 1 (enabled) if `RelativeFileMRU` is enabled, and 0 (disabled) otherwise.
#### `OpacityLevel=75`
Opacity level (in %) of the Notepad3 window in transparent mode.
#### `FindReplaceOpacityLevel=50`
Opacity level (in %) of the Find/Replace window in transparent mode.
#### `RelativeFileMRU=1`
Set to 0 to disable recent files on the same drive or network share as Notepad3.exe being saved with relative path-names.
- The default is 1 (enabled).
#### `ReuseWindow=0`
This items are managed by Notepad3. (`Menu->Settings->Window->Reuse Window Ctrl+Shift+L`)
- If set, another started Notepad3 instance will try to give control to the currently opened Window and quit.
#### `SaveBlankNewFile=true`
New file (not exists on file system ("Untitled")) asking('true')/not asking('false') for file save if document contains any whitespace (blank/space, tab, line-break) character.
#### `SciFontQuality=3`
#### `SimpleIndentGuides=0`
Set to 1 to prevent indentation guides from jumping across empty lines.
#### `SingleFileInstance=1`
This items are managed by Notepad3.
#### `ShellAppUserModelID=Rizonesoft.Notepad3`
#### `ShellUseSystemMRU=1`
Application User Model IDs (AppUserModelIDs) are used extensively by the taskbar in Windows 7 and later systems to associate processes, files, and windows with a particular application.
In some cases, it is sufficient to rely on the internal AppUserModelID assigned to a process by the system.
However, an application that owns multiple processes or an application that is running in a host process might need to explicitly identify itself so that it can group its otherwise disparate windows under a single taskbar button and control the contents of that application's Jump List.
Most recently used (MRU) source lists are resident on the user's computer and contain information about source paths used in previous installations.
This information can be used when prompting the user for a source path.
Control system MRU, task-bar and jump list behavior.
See Replacing Windows Notepad for detailed explanations.
#### `StickyWindowPosition=0`
This items are managed by Notepad3.
- `Menu->View->Position->Sticky Window Position` (Will remember current window position on restart, instead of last closed position (save on exit))
#### `SubWrappedLineSelectOnMarginClick=false`
Set to `true` to revert to old selection behavior:
- 1 click on line-number margin selects the entire corresponding line
- 1 double click on line-number margin selects the entire line with all sub-lines.
#### `LaunchInstanceWndPosOffset=28`
#### `LaunchInstanceFullVisible=true`
#### `UseOldStyleBraceMatching=0`
UseOldStyleBraceMatching=1 to switch back to (not recommended) old style behavior
#### `WebTemplate1=https://google.com/search?q=%s`
#### `WebTmpl1MenuName=Open Web Action 1`
#### `WebTemplate2=https://en.wikipedia.org/w/index.php?search=%s`
#### `WebTmpl2MenuName=Open Web Action 2
#### `ExtendedWhiteSpaceChars=:`
Put in here all ASCII chars which will be word delimiters for "Accelerated Word Navigation".
#### `AutoCompleteWordCharSet=`
Is set automatically for CJK input languages (GetACP()).
If you define your own character-set in AutoCompleteWordCharSet, Auto-Completion word list is limited to words composed of these chars only (case insensitive).)
#### `AutoCompleteFillUpChars=`
New configuration .ini-file: [Settings2] AutoCompleteFillUpChars=
To get the "Enter" completion behavior back, define: [Settings2] AutoCompleteFillUpChars=\r\n
I you like to allow more "fill-up" characters (accept completion item), just add them:
- e.g. [Settings2] AutoCompleteFillUpChars=\r\n[(. (will accept completion item & adds the char).
#### `LineCommentPostfixStrg=`
It will be appended/removed to the comment tag on line comment block toggle.
If the string contains spaces, you have to double-quote it,
- e.g. [Settings2] LineCommentPostfixStrg=" " to add a space after the comment tag (origin and title of this feature request).
#### `UpdateDelayMarkAllOccurrences=50`
#### `CurrentLineHorizontalSlop=40`
#### `CurrentLineVerticalSlop=5`
#### `UndoTransactionTimeout=0`
- in [msec]
UndoTransactionTimeout=1 (will be clamped to 10msec min.) will separate nearly every keystroke as single undo action.
(UndoTransactionTimeout=0 will switch this timer OFF)
#### `AdministrationTool.exe=`
This parameter is not used at the moment.
#### `DevDebugMode=0`
Encoding Detector information in Titlebar. This parameter is used to "debug" UCHARDET.
#### `AnalyzeReliableConfidenceLevel=90`
Confidence/Reliability level for reliability switch in encoding dialog.
#### `LocaleAnsiCodePageAnalysisBonus=33`
Bias/Bonus on top of Confidence/Reliability if current system's ANSI Code-Page is file encoding analysis result.
(This will push detection algorithm to like system's ANSI Code-Page more than other detection result)
#### `LexerSQLNumberSignAsComment=1`
The # (hash) is the start of a line comment in MySQL dialect.
But if this is confusing, it can be switched off by providing an option to Scintilla's SQL-Lexer
(set option: lexer.sql.numbersign.comment to 0 (zero)).
Unfortunately, in Notepad3, this can not be done by configuration, it can only be done hard coded.
- Ed.: The default is "OFF", it is set to "ON" explicitly in Notepad3 (hard coded) to preserve old behavior,
#### `ExitOnESCSkipLevel=2`
The leveling of ESC behavior (msg-boxes -> selection -> exit) leads to following implementation:
New parameter "[Settings2] ExitOnESCSkipLevel = 2"
- Level 2 : ESC cancels every single state separately (the default).
- Level 1 : ESC cancels message-box and ignores Selection.
- Level 0 : ESC cancels all states and proceeds to Exit (if configured).
#### `ZoomTooltipTimeout=3200`
- in [msec]
- A value of zero (0) (or less than 100 msec) will disable the tooltip display.
#### `WrapAroundTooltipTimeout=2000`
- in [msec]
- A value of zero (0) (or less than 100 msec) will disable the tooltip display.
#### `LargeIconScalePrecent=150`
- `Screen/Display Scale Percent` threshold to switch to bigger file types icons (lexer style selections)
#### `DarkModeBkgColor=0x1F1F1F`
#### `DarkModeBtnFaceColor=0x333333`
#### `DarkModeTxtColor=0xEFEFEF`
#### `HyperlinkShellExURLWithApp=""`
- If not defined or empty the default behavior on `Ctrl+Click` URL is performed:
- The URL-String is sent to the OS via ShellExecute(), which will try open the URL using the registered protocol (e.g. http:// or file://) - in most cases the default browser resp. the file, if extension is known.
- If defined, e.g. "`D:\PortableApps\GoogleChromePortable\GoogleChromePortable.exe`", this application will be started on `Ctrl+Click`.
#### `HyperlinkShellExURLCmdLnArgs="${URL}"`
- (use ${URL} as place holder for clicked Hyperlink URL string)
- Defining the argument/parameter string for the above application (only taken into account if `HyperlinkShellExURLWithApp` is defined).
- If not defined, empty or set to "${URL}", the argument for the app will be the URL-String clicked.
You can specify more command line parameter for the app here. The token `${URL}` within the string will be replaced by the URL-String clicked. E.g. `HyperlinkShellExURLCmdLnArgs="--incognito "${URL}""` will start the Chrome-Browser (see `HyperlinkShellExURLWithApp`) in "incognito mode" trying to open the clicked URL.
#### `HyperlinkFileProtocolVerb=""`
- `ShellExecuteEx()::lpVerb (""=default, "edit", "explore", "find", "open", "print", "properties", "runas")`
#### `CodeFontPrefPrioList="Cascadia Code,Cascadia Mono,Cousine,Fira Code,Source Code Pro,Roboto Mono,DejaVu Sans Mono,Inconsolata,Consolas,Lucida Console"`
Configurable Fonts priority list for for "Common Base" Scheme.
#### `TextFontPrefPrioList="Cascadia Mono,Cousine,Roboto Mono,DejaVu Sans Mono,Inconsolata,Consolas,Lucida Console"`
Configurable Fonts priority list for "Text Files" Scheme.
## **`[Statusbar Settings]`**
This section provides the ability to set the number, order and width of columns,
and the prefix text of the status bar fields.
#### `VisibleSections=0 1 15 14 2 4 5 6 7 8 9 10 11` (internal default)
This parameter is used to define, which fields of the Status Bar should be visible.
If used, this setting also defines the field ordering.
- Section 0 = Ln : Line number of Caret position / Number total of lines in the file
- Section 1 = Col : Column number of Caret position / Limit for Long Line settings
- Section 2 = Sel : Number of characters selected
- Section 3 = Sb : Number of bytes (Bytes in [UTF-8]) selected
- Section 4 = SLn : Number of selected lines
- Section 5 = Occ : Number of Marked Occurrences
- Section 6 = Size of file in [UTF-8] Mode
- Section 7 = Encoding Mode (double click to open `Encoding F9` )
- Section 8 = EOL Mode (Toggle CR+LF, LF, CR)
- Section 9 = Toggle INS/OVR Mode
- Section 10 = Toggle STD/2ND Text Mode (Default Text or 2nd Default Text)
- Section 11 = Current Scheme (double click to open `Select Scheme` )
- Section 12 = Character Count (per line from line start)
- Section 13 = Replaced Occurrences
- Section 14 = TinyExpr Evaluation
- Section 15 = Unicode point display (UTF-16 encoding) of current (caret pos) character.
#### `SectionPrefixes=Ln ,Col ,Sel ,Sb ,SLn ,Occ ,,,,,,,Ch ,Repl ,Eval ,U+,` (internal default)
This parameter is used to redefines the displayed Prefixes in the sections of the Status Bar
- A “,” (comma) is used as separator. Spaces are **NOT** ignored.
#### `SectionPostfixes=,,,,,,,,,,,,,,,,` (internal default)
This parameter is used to redefines the displayed Postfixes in the sections of the Status Bar
- A “,” (comma) is used as separator. Spaces are **NOT** ignored.
#### `SectionWidthSpecs=30 20 20 20 20 20 20 0 0 0 0 0 0 0 20 24` (internal default)
This parameter is used to define the relative width of each field of the Status Bar
- 0 = space optimized fit to text (dynamically adapted to width changes)
- -n (neg. val) = fixed width of section [pix] , longer text is truncated
Fine tuning: increase, decrease or modify the value of numbers,
- e.g.: `;;;;;;;;;;;;;;;;; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15`
- `SectionWidthSpecs=50 40 42 40 36 40 0 0 0 0 0 -10 40 40 -40 40`
#### `ZeroBasedColumnIndex=0`
This parameter is used to define start counting of column (`Col`) at 0 or 1.
#### `ZeroBasedCharacterCount=0`
This parameter is used to define start counting of characters (of current line) (`Ch`) at 0 or 1.
## **`[Toolbar Labels]`**
This section offers the possibility to display the name of the function to the right of its corresponding icon.
```
01=New
02=Open
03=Browse
04=Save
05=Undo
06=Redo
07=Cut
08=Copy
09=Paste
10=Find
11=Replace
12=Word Wrap
13=Zoom In
14=Zoom Out
15=Scheme
16=Customize Schemes
17=Exit
18=Save As
19=Save Copy
20=Delete
21=Print
22=Favorites
23=Add to Favorites
24=Toggle Folds
25=Execute Document
26=Focused View
27=Monitoring Log
28=History
29=Always On Top
30=Search in Files
31=Reset Zoom
32=New Empty Window
```
## **`[Window]`**
#### `<ResX>x<ResY> DefaultWindowPosition=`
This items are managed by Notepad3. (`Menu->View->Position->Save as Default Position`)
(Will set current window position as "Default Position" - can be recalled by `Ctrl+Shift+P` Hotkey)
<hr/>
[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-ea4aaa?style=flat-square&logo=github)](https://github.com/sponsors/rizonesoft)
[![Donate](https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square&logo=paypal)](https://www.paypal.com/donate/?hosted_button_id=7UGGCSDUZJPFE)

485
doc/Configuration.md Normal file
View File

@ -0,0 +1,485 @@
# Notepad3 Configuration Reference
Notepad3 stores its settings in a portable INI file (`Notepad3.ini`). Press **Ctrl+F7** to open it directly in the editor. Most `[Settings2]` changes require restarting Notepad3.
---
## `[Notepad3]`
This section can redirect to a different settings file. Useful when a non-elevated user cannot write to the Notepad3 program directory:
```ini
Notepad3.ini=%APPDATA%\Rizonesoft\Notepad3\Notepad3.ini
```
Or for per-user settings:
```ini
Notepad3.ini=%WINDIR%\Notepad3-%USERNAME%.ini
```
---
## `[Settings]`
These settings are managed through Notepad3's user interface (Menu → Settings). For example:
#### `SettingsVersion=5`
#### `Favorites=%APPDATA%\Rizonesoft\Notepad3\Favorites\`
---
## `[Settings2]`
Advanced settings that can only be edited manually. Press **Ctrl+F7** to open the INI file.
### Localization
#### `PreferredLanguageLocaleName=en-US`
The default value is determined by the OS language setting. Fallback: `en-US`.
Available languages:
| Language | Locale Code |
|----------|-------------|
| English/United States | `en-US` (internal default) |
| Afrikaans/South Africa | `af-ZA` |
| Belarusian/Belarus | `be-BY` |
| German/Germany | `de-DE` |
| Greek/Greece | `el-GR` |
| English/United Kingdom | `en-GB` |
| Spanish/Spain | `es-ES` |
| French/France | `fr-FR` |
| Hindi/India | `hi-IN` |
| Hungarian/Hungary | `hu-HU` |
| Indonesian/Indonesia | `id-ID` |
| Italian/Italy | `it-IT` |
| Japanese/Japan | `ja-JP` |
| Korean/Korea | `ko-KR` |
| Dutch/Netherlands | `nl-NL` |
| Polish/Poland | `pl-PL` |
| Portuguese/Brazil | `pt-BR` |
| Portuguese/Portugal | `pt-PT` |
| Russian/Russia | `ru-RU` |
| Slovak/Slovakia | `sk-SK` |
| Swedish/Sweden | `sv-SE` |
| Turkish/Turkey | `tr-TR` |
| Vietnamese/Vietnam | `vi-VN` |
| Chinese Simplified/China | `zh-CN` |
| Chinese Traditional/Taiwan | `zh-TW` |
### IME & Input
#### `IMEInteraction=0`
### Date & Time
#### `DateTimeFormat=`
Locale-dependent short format. Specify the short date/time format using [`strftime()`](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strftime-wcsftime-strftime-l-wcsftime-l?view=vs-2019) syntax.
#### `DateTimeLongFormat=`
Locale-dependent long format.
#### `TimeStampRegEx=`
Default: `\$Date:[^\$]+\$` — Find pattern to match timestamps for update.
#### `TimeStampFormat=`
Default: `$Date: %Y/%m/%d %H:%M:%S $`
This pattern is used by **Shift+F5** to update timestamps, e.g., `$Date: 2018/04/26 00:52:39 $`.
**Notes:**
- All `DateTime` formats accept [`strftime()`](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strftime-wcsftime-strftime-l-wcsftime-l?view=vs-2019) format strings.
- `TimeStampFormat` also accepts `%s` as a placeholder for a `DateTimeFormat`-formatted current date/time string (mixing `strftime()` codes with `%s` is not allowed).
- If you define a custom `TimeStampFormat`, define a matching `TimeStampRegEx` so that "Update Timestamps" can find and replace them correctly.
### Files & Directories
#### `DefaultDirectory=`
Default directory for open/save dialogs when no file is open. Paths can be relative to the Notepad3 program directory.
#### `DefaultExtension=txt`
Default extension for saved files (omit the leading dot).
#### `DenyVirtualSpaceAccess=0`
#### `filebrowser.exe=minipath.exe`
External program launched by the Browse toolbar button. Defaults to MiniPath.
Additional command line switches can be appended. The currently opened file is passed as the last argument.
> **Note:** Pathnames with spaces need quadruple quoting (`""path to/file.exe""`) when no arguments follow, or double quoting (`"path to/file.exe" /arg`) with arguments.
Alternative file browsers:
- `filebrowser.exe=explorer.exe` — Windows Explorer
- `filebrowser.exe=Explorer++.exe` — [Explorer++](https://explorerplusplus.com/)
- `filebrowser.exe=Q-Dir_x64+.exe` — [Q-Dir](https://www.softwareok.de/?seite=Freeware/Q-Dir/)
#### `grepWin.exe=grepWinNP3.exe`
Integrated search-and-replace tool with regex support. Launch via:
- File → Launch → Search in Files
- Edit → Search → Search in Files
- **Ctrl+Shift+F**
#### `FileCheckInterval=2000`
Interval in milliseconds to check for external file modification. Min: 200 ms (notify immediately if ≤ 200).
#### `FileChangedIndicator=[@]`
#### `FileDeletedIndicator=[X]`
#### `FileDlgFilters=`
Custom filters for open/save dialogs. Example:
```
Text Files|*.txt;*.wtx;*.log;*.asc;*.doc;*.diz;*.nfo|All Files|*.*
```
#### `FileLoadWarningMB=4`
Size limit (MB) for large-file warning. Set to `0` to disable.
#### `MultiFileArg=0`
Set to `1` to allow multiple files on the command line. Default (`0`) accepts a single file like Windows Notepad. Use `+` and `-` command-line switches to override; `/z` behaves like `-`.
### Language Detection
#### `NoCGIGuess=0`
Set to `1` to disable language detection for `.cgi` and `.fcgi` files.
#### `NoHTMLGuess=0`
Set to `1` to disable HTML/XML detection for files without extensions.
### Editing Behavior
#### `NoCopyLineOnEmptySelection=0`
Set to `1` to prevent **Ctrl+C** from copying the current line when nothing is selected.
#### `NoCutLineOnEmptySelection=0`
Set to `1` to prevent **Ctrl+X** from cutting the current line when nothing is selected.
#### `NoFadeHidden=0`
Set to `1` to disable fading of hidden objects in file lists (Favorites, etc.).
#### `NoFileVariables=0`
Set to `1` to disable file variable parsing. Encoding tag parsing can be disabled separately in Menu → File → Encoding → Default.
Notepad3 parses Emacs-style variables in the first and last 512 bytes of a file:
| Variable | Effect |
|----------|--------|
| `coding: utf-8;` | File encoding tag |
| `mode: python;` | Syntax scheme (name or extension) |
| `tab-width: 8;` | Tab width |
| `c-basic-indent: 2;` | Indentation size |
| `indent-tabs-mode: nil;` | Insert tabs as spaces (`nil`/`false`/`0`) or not (`true`/`1`) |
| `c-tab-always-indent: true;` | Tab key reformats whitespace (`true`/`1`) or not |
| `fill-column: 64;` | Long-line limit (does not auto-show the visual marker) |
| `truncate-lines: false;` | Word wrap: enable (`nil`/`false`/`0`), disable (`true`/`1`) |
| `enable-local-variables: false;` | Disable variable parsing but keep encoding tags |
To bypass both file variable and encoding tag parsing, reload the file with **Alt+F8**.
### Portability & Window
#### `PortableMyDocs=1`
Store recent file paths relative to `My Documents` for USB portability across Windows versions. Enabled by default when `RelativeFileMRU=1`.
#### `OpacityLevel=75`
Window opacity (%) in transparent mode.
#### `FindReplaceOpacityLevel=50`
Find/Replace dialog opacity (%) in transparent mode.
#### `RelativeFileMRU=1`
Store recent file paths as relative when on the same drive/share as Notepad3.exe.
#### `ReuseWindow=0`
Managed by Notepad3 (Menu → Settings → Window → Reuse Window, **Ctrl+Shift+L**). When enabled, new instances hand off to the existing window.
#### `SaveBlankNewFile=true`
Whether to prompt for save when closing an untitled document that contains only whitespace.
#### `SciFontQuality=3`
#### `SimpleIndentGuides=0`
Set to `1` to prevent indentation guides from jumping across empty lines.
#### `SingleFileInstance=1`
Managed by Notepad3.
#### `ShellAppUserModelID=Rizonesoft.Notepad3`
#### `ShellUseSystemMRU=1`
Controls taskbar grouping, Jump List, and system MRU behavior. See [Replacing Windows Notepad](https://rizonesoft.com/documents/notepad3/) for details.
#### `StickyWindowPosition=0`
Managed by Notepad3 (Menu → View → Position → Sticky Window Position). Remembers current position on restart instead of last-closed position.
#### `SubWrappedLineSelectOnMarginClick=false`
Set to `true` for old selection behavior: single click selects the visible sub-line, double click selects the entire wrapped line.
#### `LaunchInstanceWndPosOffset=28`
#### `LaunchInstanceFullVisible=true`
### Appearance
#### `UseOldStyleBraceMatching=0`
Set to `1` for legacy brace-matching style.
#### `LargeIconScalePrecent=150`
Display scale percent threshold to switch to larger file-type icons.
#### `DarkModeBkgColor=0x1F1F1F`
#### `DarkModeBtnFaceColor=0x333333`
#### `DarkModeTxtColor=0xEFEFEF`
### Web Actions
#### `WebTemplate1=https://google.com/search?q=%s`
#### `WebTmpl1MenuName=Open Web Action 1`
#### `WebTemplate2=https://en.wikipedia.org/w/index.php?search=%s`
#### `WebTmpl2MenuName=Open Web Action 2`
### Auto-Completion & Editing
#### `ExtendedWhiteSpaceChars=:`
Additional ASCII characters treated as word delimiters for Accelerated Word Navigation.
#### `AutoCompleteWordCharSet=`
Set automatically for CJK input languages. Custom character sets limit the auto-completion word list to words composed of these characters only (case-insensitive).
#### `AutoCompleteFillUpChars=`
Characters that accept an auto-completion item. For Enter-to-complete behavior:
```ini
AutoCompleteFillUpChars=\r\n
```
To also accept on `(` or `.`:
```ini
AutoCompleteFillUpChars=\r\n(.
```
#### `LineCommentPostfixStrg=`
String appended/removed after comment tags on line-comment toggle. Double-quote if it contains spaces:
```ini
LineCommentPostfixStrg=" "
```
### Hyperlinks
#### `HyperlinkShellExURLWithApp=""`
External application for **Ctrl+Click** on URLs. If empty, the OS default handler is used.
#### `HyperlinkShellExURLCmdLnArgs="${URL}"`
Command-line arguments for the URL application. Use `${URL}` as placeholder:
```ini
HyperlinkShellExURLCmdLnArgs="--incognito "${URL}""
```
#### `HyperlinkFileProtocolVerb=""`
`ShellExecuteEx` verb: `""` (default), `"edit"`, `"explore"`, `"find"`, `"open"`, `"print"`, `"properties"`, `"runas"`.
### Fonts
#### `CodeFontPrefPrioList="Cascadia Code,Cascadia Mono,Cousine,Fira Code,Source Code Pro,Roboto Mono,DejaVu Sans Mono,Inconsolata,Consolas,Lucida Console"`
Font priority list for the "Common Base" scheme.
#### `TextFontPrefPrioList="Cascadia Mono,Cousine,Roboto Mono,DejaVu Sans Mono,Inconsolata,Consolas,Lucida Console"`
Font priority list for the "Text Files" scheme.
### Miscellaneous
#### `UpdateDelayMarkAllOccurrences=50`
#### `CurrentLineHorizontalSlop=40`
#### `CurrentLineVerticalSlop=5`
#### `UndoTransactionTimeout=0`
Timeout in milliseconds. Set to `1` (clamped to 10 ms minimum) to make nearly every keystroke a separate undo action. `0` disables the timer.
#### `AdministrationTool.exe=`
Reserved for future use.
#### `DevDebugMode=0`
Show encoding detector (UCHARDET) info in the title bar for debugging.
#### `AnalyzeReliableConfidenceLevel=90`
Confidence threshold for the encoding reliability indicator.
#### `LocaleAnsiCodePageAnalysisBonus=33`
Bias added to confidence when the system's ANSI code page matches the detected encoding.
#### `LexerSQLNumberSignAsComment=1`
Enable `#` as a line-comment character in MySQL-dialect SQL. Set to `0` to disable.
#### `ExitOnESCSkipLevel=2`
Controls ESC key behavior:
- **2** (default): Cancel each state separately (message boxes → selection → exit)
- **1**: Cancel message boxes, skip selection state
- **0**: Cancel all states and proceed to exit (if configured)
#### `ZoomTooltipTimeout=3200`
Zoom tooltip display duration in milliseconds. Set to `0` to disable.
#### `WrapAroundTooltipTimeout=2000`
Search wrap-around tooltip duration in milliseconds. Set to `0` to disable.
---
## `[Statusbar Settings]`
Customize the status bar layout: number, order, width, and prefix/postfix text of fields.
#### `VisibleSections=0 1 15 14 2 4 5 6 7 8 9 10 11`
Defines visible fields and their order:
| Section | Content |
|---------|---------|
| 0 | Ln — Line number / Total lines |
| 1 | Col — Column number / Long-line limit |
| 2 | Sel — Selected characters |
| 3 | Sb — Selected bytes (UTF-8) |
| 4 | SLn — Selected lines |
| 5 | Occ — Marked occurrences |
| 6 | File size (UTF-8 mode) |
| 7 | Encoding (double-click to open Encoding dialog) |
| 8 | EOL mode (toggle CR+LF / LF / CR) |
| 9 | INS/OVR mode toggle |
| 10 | STD/2ND text mode toggle |
| 11 | Current scheme (double-click to open scheme selector) |
| 12 | Ch — Character count from line start |
| 13 | Repl — Replaced occurrences |
| 14 | Eval — TinyExpr evaluation |
| 15 | U+ — Unicode code point (UTF-16) at caret |
#### `SectionPrefixes=Ln ,Col ,Sel ,Sb ,SLn ,Occ ,,,,,,,Ch ,Repl ,Eval ,U+,`
Redefine display prefixes. Comma-separated; spaces are significant.
#### `SectionPostfixes=,,,,,,,,,,,,,,,,`
Redefine display postfixes. Comma-separated; spaces are significant.
#### `SectionWidthSpecs=30 20 20 20 20 20 20 0 0 0 0 0 0 0 20 24`
Relative field widths. `0` = auto-fit, negative = fixed pixel width (text truncated).
#### `ZeroBasedColumnIndex=0`
Start column counting at 0 or 1.
#### `ZeroBasedCharacterCount=0`
Start character counting at 0 or 1.
---
## `[Toolbar Labels]`
Display function names next to toolbar icons:
```ini
01=New
02=Open
03=Browse
04=Save
05=Undo
06=Redo
07=Cut
08=Copy
09=Paste
10=Find
11=Replace
12=Word Wrap
13=Zoom In
14=Zoom Out
15=Scheme
16=Customize Schemes
17=Exit
18=Save As
19=Save Copy
20=Delete
21=Print
22=Favorites
23=Add to Favorites
24=Toggle Folds
25=Execute Document
26=Focused View
27=Monitoring Log
28=History
29=Always On Top
30=Search in Files
31=Reset Zoom
32=New Empty Window
```
---
## `[Window]`
#### `<ResX>x<ResY> DefaultWindowPosition=`
Managed by Notepad3 (Menu → View → Position → Save as Default Position). Recall with **Ctrl+Shift+P**.

View File

@ -863,8 +863,6 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SC_POPUP_TEXT 2
#define SCI_USEPOPUP 2371
#define SCI_SELECTIONISRECTANGLE 2372
#define SC_MIN_ZOOM_LEVEL 10
#define SC_MAX_ZOOM_LEVEL 1000
#define SCI_SETZOOM 2373
#define SCI_GETZOOM 2374
#define SC_DOCUMENTOPTION_DEFAULT 0

View File

@ -2265,12 +2265,6 @@ fun void UsePopUp=2371(PopUp popUpMode,)
# Is the selection rectangular? The alternative is the more common stream selection.
get bool SelectionIsRectangle=2372(,)
# >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
# 2018-09-06 change zoom level and print magnification to percent value
val SC_MIN_ZOOM_LEVEL=10
val SC_MAX_ZOOM_LEVEL=1000
# <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
# Set the zoom level. This number of points is added to the size of all fonts.
# It may be positive to magnify or negative to reduce.
set void SetZoom=2373(int zoomInPoints,)

View File

@ -71,9 +71,7 @@ using namespace Scintilla;
using namespace Scintilla::Internal;
PrintParameters::PrintParameters() noexcept {
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
magnification = 100;
// <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
magnification = 0;
colourMode = PrintOption::Normal;
wrapState = Wrap::Word;
}

View File

@ -63,12 +63,8 @@ bool MarginStyle::ShowsFolding() const noexcept {
void FontRealised::Realise(Surface &surface, int zoomLevel, Technology technology, const FontSpecification &fs, const char *localeName) {
PLATFORM_ASSERT(fs.fontName);
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
//~measurements.sizeZoomed = fs.size + zoomLevel * FontSizeMultiplier;
//~if (measurements.sizeZoomed <= FontSizeMultiplier) // May fail if sizeZoomed < 1
//~ measurements.sizeZoomed = FontSizeMultiplier;
measurements.sizeZoomed = GetFontSizeZoomed(fs.size, zoomLevel);
// <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
// If negative zoomLevel, ensure sizeZoomed at least minimum positive size
measurements.sizeZoomed = std::max(fs.size + (zoomLevel * FontSizeMultiplier), FontSizeMultiplier);
const float deviceHeight = static_cast<float>(surface.DeviceHeightFont(measurements.sizeZoomed));
const FontParameters fp(fs.fontName, deviceHeight / FontSizeMultiplier, fs.weight,
@ -234,9 +230,7 @@ ViewStyle::ViewStyle(size_t stylesSize_) :
marginInside = true;
CalculateMarginWidthAndMask();
textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
zoomLevel = 100; /// @ 20018-09-06 Changed to percent
// <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
zoomLevel = 0;
viewWhitespace = WhiteSpace::Invisible;
tabDrawMode = TabDrawMode::LongArrow;
whitespaceSize = 1;
@ -771,44 +765,6 @@ ViewStyle::CaretShape ViewStyle::CaretShapeForMode(bool inOverstrike, bool isMai
return (caretStyle <= CaretStyle::Block) ? static_cast<CaretShape>(caretStyle) : CaretShape::line;
}
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
bool ViewStyle::ZoomIn() noexcept {
if (zoomLevel < SC_MAX_ZOOM_LEVEL) {
int level = zoomLevel;
if (level < 200) {
level += 10;
} else {
level += 25;
}
level = std::min(level, SC_MAX_ZOOM_LEVEL);
if (level != zoomLevel) {
zoomLevel = level;
return true;
}
}
return false;
}
bool ViewStyle::ZoomOut() noexcept {
if (zoomLevel > SC_MIN_ZOOM_LEVEL) {
int level = zoomLevel;
if (level <= 200) {
level -= 10;
} else {
level -= 25;
}
level = std::max(level, SC_MIN_ZOOM_LEVEL);
if (level != zoomLevel) {
zoomLevel = level;
return true;
}
}
return false;
}
// <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
void ViewStyle::AllocStyles(size_t sizeNew) {
size_t i=styles.size();
styles.resize(sizeNew);

View File

@ -71,14 +71,6 @@ struct CaretLineAppearance {
int frame = 0;
};
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
constexpr int GetFontSizeZoomed(int size, int zoomLevel) noexcept {
size = (size * zoomLevel + 50) / 100;
// Hangs if sizeZoomed (in point) <= 1
return std::max(size, 2 * FontSizeMultiplier);
}
// <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
struct CaretAppearance {
// Line, block, over-strike bar ...
Scintilla::CaretStyle style = CaretStyle::Line;
@ -160,9 +152,7 @@ public:
int fixedColumnWidth = 0; ///< Total width of margins
bool marginInside; ///< true: margin included in text view, false: separate views
int textStart; ///< Starting x position of text within the view
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
int zoomLevel; /// @ 2018-09-06 Changed to a percent value
// <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
int zoomLevel;
Scintilla::WhiteSpace viewWhitespace;
Scintilla::TabDrawMode tabDrawMode;
int whitespaceSize;
@ -259,10 +249,6 @@ public:
bool IsCaretVisible(bool isMainSelection) const noexcept;
bool DrawCaretInsideSelection(bool inOverstrike, bool imeCaretBlockOverride) const noexcept;
CaretShape CaretShapeForMode(bool inOverstrike, bool isMainSelection) const noexcept;
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
bool ZoomIn() noexcept;
bool ZoomOut() noexcept;
// <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
private:
void AllocStyles(size_t sizeNew);

View File

@ -333,12 +333,9 @@ public:
void SetCompositionFont(const ViewStyle &vs, int style, UINT dpi) const {
LOGFONTW lf{};
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
//int sizeZoomed = vs.styles[style].size + (vs.zoomLevel * FontSizeMultiplier);
//if (sizeZoomed <= 2 * FontSizeMultiplier) // Hangs if sizeZoomed <= 1
// sizeZoomed = 2 * FontSizeMultiplier;
int const sizeZoomed = GetFontSizeZoomed(vs.styles[style].size, vs.zoomLevel);
// <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
int sizeZoomed = vs.styles[style].size + (vs.zoomLevel * FontSizeMultiplier);
if (sizeZoomed <= 2 * FontSizeMultiplier) // Hangs if sizeZoomed <= 1
sizeZoomed = 2 * FontSizeMultiplier;
// The negative is to allow for leading
lf.lfHeight = -::MulDiv(sizeZoomed, dpi, pointsPerInch * FontSizeMultiplier);
lf.lfWeight = static_cast<LONG>(vs.styles[style].weight);
@ -1959,15 +1956,7 @@ sptr_t ScintillaWin::MouseMessage(unsigned int iMessage, uptr_t wParam, sptr_t l
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
if (wParam & (MK_CONTROL | MK_RBUTTON)) {
if (wParam & (MK_CONTROL)) {
// Zoom! We play with the font sizes in the styles.
// Number of steps/line is ignored, we just care if sizing up or down
if (linesToScroll < 0)
KeyCommand(Message::ZoomIn);
else
KeyCommand(Message::ZoomOut);
}
// send to main window (trigger zoom callTip or undo/redo history) !
// Forward to parent (NP3 handles zoom steps and undo/redo history)
::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
} else {
// Scroll

View File

@ -1713,11 +1713,11 @@ void LoadSettings()
int const prtFontSize = 10;
int const zoomScale = MulDiv(baseZoom, prtFontSize, f2int(GLOBAL_INITIAL_FONTSIZE));
Defaults.PrintZoom = (Globals.iCfgVersionRead < CFG_VER_0001) ? (zoomScale / 10) : zoomScale;
int iPrintZoom = clampi(IniSectionGetInt(IniSecSettings, L"PrintZoom", Defaults.PrintZoom), 0, SC_MAX_ZOOM_LEVEL);
int iPrintZoom = clampi(IniSectionGetInt(IniSecSettings, L"PrintZoom", Defaults.PrintZoom), 0, NP3_MAX_ZOOM_PERCENT);
if (Globals.iCfgVersionRead < CFG_VER_0001) {
iPrintZoom = 100 + (iPrintZoom - 10) * 10;
}
Settings.PrintZoom = clampi(iPrintZoom, SC_MIN_ZOOM_LEVEL, SC_MAX_ZOOM_LEVEL);
Settings.PrintZoom = clampi(iPrintZoom, NP3_MIN_ZOOM_PERCENT, NP3_MAX_ZOOM_PERCENT);
GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_IMEASURE, tchKeyName, COUNTOF(tchKeyName));
LONG const _margin = (tchKeyName[0] == L'0') ? 2000L : 1000L; // Metric system. L'1' is US System
@ -1886,7 +1886,7 @@ void LoadSettings()
if (Globals.iCfgVersionRead < CFG_VER_0001) {
winInfo.zoom = (winInfo.zoom + 10) * 10;
}
winInfo.zoom = clampi(winInfo.zoom, SC_MIN_ZOOM_LEVEL, SC_MAX_ZOOM_LEVEL);
winInfo.zoom = clampi(winInfo.zoom, NP3_MIN_ZOOM_PERCENT, NP3_MAX_ZOOM_PERCENT);
winInfo.dpi = IniSectionGetInt(IniSecWindow, tchDPI, USER_DEFAULT_SCREEN_DPI);
int const offset = Settings2.LaunchInstanceWndPosOffset;

View File

@ -1338,7 +1338,7 @@ CASE_WM_CTLCOLOR_SET:
StringCchPrintf(wchBuf, COUNTOF(wchBuf), L"\n- Rendering-Technology -> '%s'", Settings.RenderingTechnology ? L"DIRECT-WRITE" : L"GDI");
StringCchCat(wchVerInfo, COUNTOF(wchVerInfo), wchBuf);
StringCchPrintf(wchBuf, COUNTOF(wchBuf), L"\n- Zoom -> %i%%.", SciCall_GetZoom());
StringCchPrintf(wchBuf, COUNTOF(wchBuf), L"\n- Zoom -> %i%%.", NP3_GetZoomPercent());
StringCchCat(wchVerInfo, COUNTOF(wchVerInfo), wchBuf);
Style_GetLexerDisplayName(Style_GetCurrentLexerPtr(), wchBuf, COUNTOF(wchBuf));
@ -4698,7 +4698,7 @@ WININFO GetMyWindowPlacement(HWND hwnd, MONITORINFO *hMonitorInfo, const int off
wi.cx = wndpl.rcNormalPosition.right - wndpl.rcNormalPosition.left;
wi.cy = wndpl.rcNormalPosition.bottom - wndpl.rcNormalPosition.top;
wi.max = (hwnd ? IsZoomed(hwnd) : false) || (wndpl.flags & WPF_RESTORETOMAXIMIZED);
wi.zoom = hwnd ? SciCall_GetZoom() : 100;
wi.zoom = hwnd ? NP3_GetZoomPercent() : NP3_DEFAULT_ZOOM;
wi.dpi = Scintilla_GetWindowDPI(hwnd);
if (bFullVisible) {

View File

@ -1552,7 +1552,7 @@ bool EditSaveFile(
}
// strip trailing blanks
if (Settings.FixTrailingBlanks) {
if (Settings.FixTrailingBlanks && EditHasTrailingBlanks()) {
EditStripLastCharacter(hwnd, true, true);
}
}
@ -2694,6 +2694,7 @@ void EditTabsToSpaces(int nTabWidth,bool bOnlyIndentingWS)
if (bModified) {
char * const pszText2 = AllocMem((size_t)cchConvW * 3, HEAP_ZERO_MEMORY);
if (pszText2) {
ptrdiff_t cchConvM = WideCharToMultiByteEx(Encoding_SciCP,0,pszConvW,cchConvW,
pszText2,SizeOfMem(pszText2),NULL,NULL);
@ -2711,6 +2712,8 @@ void EditTabsToSpaces(int nTabWidth,bool bOnlyIndentingWS)
Sci_ReplaceTargetTestChgHist(cchConvM, pszText2);
EditSetSelectionEx(iAnchorPos, iCurPos, -1, -1);
EndUndoTransAction();
} // if pszText2
FreeMem(pszText2);
}
FreeMem(pszConvW);
@ -2806,6 +2809,7 @@ void EditSpacesToTabs(int nTabWidth,bool bOnlyIndentingWS)
if (bModified || cchConvW != cchTextW) {
char *pszText2 = AllocMem((size_t)cchConvW * 3, HEAP_ZERO_MEMORY);
if (pszText2) {
ptrdiff_t cchConvM = WideCharToMultiByteEx(Encoding_SciCP,0,pszConvW,cchConvW,
pszText2,SizeOfMem(pszText2),NULL,NULL);
@ -2823,6 +2827,8 @@ void EditSpacesToTabs(int nTabWidth,bool bOnlyIndentingWS)
Sci_ReplaceTargetTestChgHist(cchConvM, pszText2);
EditSetSelectionEx(iAnchorPos, iCurPos, -1, -1);
EndUndoTransAction();
} // if pszText2
FreeMem(pszText2);
}
@ -3202,7 +3208,7 @@ void EditModifyLines(const PENCLOSESELDATA pEnclData) {
*q = '\0'; // terminate tinyexpr
StringCchCopyA(mszTinyExprPost, COUNTOF(mszTinyExprPost), t);
StringCchCopyA(mszAppend2, COUNTOF(mszAppend2), q + CONSTSTRGLEN(EXPR_END));
*p = '\0'; // mszPrefix1 terminate
*p = '\0'; // mszAppend1 terminate
p = StrStrA(q, EXPR_BEG); // next
}
else {
@ -3230,7 +3236,7 @@ void EditModifyLines(const PENCLOSESELDATA pEnclData) {
N = I + 1.0;
DocLn vmin = d2ln(te_eval(pTinyExprPre));
DocLn vmax = vmin;
for (DocLn ln = iStartLine + 2; ln <= iEndLine; ++ln) {
for (DocLn ln = iStartLine + 2; ln <= iEndLine + 1; ++ln) {
L = (double)ln;
I += 1.0;
N += 1.0;
@ -3271,7 +3277,7 @@ void EditModifyLines(const PENCLOSESELDATA pEnclData) {
N = I + 1.0;
DocLn vmin = d2ln(te_eval(pTinyExprPost));
DocLn vmax = vmin;
for (DocLn ln = iStartLine + 2; ln <= iEndLine; ++ln) {
for (DocLn ln = iStartLine + 2; ln <= iEndLine + 1; ++ln) {
L = (double)ln;
I += 1.0;
N += 1.0;
@ -3379,7 +3385,7 @@ void EditModifyLines(const PENCLOSESELDATA pEnclData) {
DocPos const newPos = SciCall_PositionFromLine(iResetLine) + iResetOffset + prefixInsertLen;
EditSetSelectionEx(newPos, newPos, -1, -1);
}
else if (iSelStart != iSelEnd) {
else {
if (iResetPos < iAnchorPos) {
EditSetSelectionEx(SciCall_PositionFromLine(iEndLine + 1), SciCall_PositionFromLine(iStartLine), -1, -1);
} else {
@ -3482,9 +3488,9 @@ void EditIndentBlock(HWND hwnd, int cmd, bool bFormatIndentation, bool bForceAll
} else { // on multiline indentation, anchor and current positions are moved to line begin resp. end
if (bFixStart) {
if (iCurPos < iAnchorPos) {
iDiffCurrent = SciCall_LineLength(iCurLine) - Sci_GetEOLLen();
iDiffCurrent = SciCall_GetLineEndPosition(iCurLine) - SciCall_PositionFromLine(iCurLine);
} else {
iDiffAnchor = SciCall_LineLength(iAnchorLine) - Sci_GetEOLLen();
iDiffAnchor = SciCall_GetLineEndPosition(iAnchorLine) - SciCall_PositionFromLine(iAnchorLine);
}
}
EditSetSelectionEx(SciCall_GetLineEndPosition(iAnchorLine) - iDiffAnchor, SciCall_GetLineEndPosition(iCurLine) - iDiffCurrent, -1, -1);
@ -3535,9 +3541,10 @@ void EditAlignText(int nMode)
if (iLineIndentPos != iLineEndPos) {
int const iIndentCol = SciCall_GetLineIndentation(iLine);
DocPos const iLineStartPos = SciCall_PositionFromLine(iLine);
DocPos iTail = iLineEndPos - 1;
char ch = SciCall_GetCharAt(iTail);
while (iTail >= iLineStart && (ch == ' ' || ch == '\t')) {
while (iTail >= iLineStartPos && (ch == ' ' || ch == '\t')) {
--iTail;
ch = SciCall_GetCharAt(iTail);
--iLineEndPos;
@ -3557,7 +3564,7 @@ void EditAlignText(int nMode)
UndoTransActionBegin();
if (chNewLineBuf && wchLineBuf && wchNewLineBuf) {
if (chNewLineBuf && wchLineBuf && wchNewLineBuf && pWords) {
for (DocLn iLine = iLineStart; iLine <= iLineEnd; iLine++) {
DocPos const iStartPos = SciCall_PositionFromLine(iLine);
@ -3608,8 +3615,7 @@ void EditAlignText(int nMode)
}
}
if ((nMode == ALIGN_JUSTIFY || nMode == ALIGN_JUSTIFY_EX) &&
iWords > 1 && iWordsLength >= 2 &&
if (iWords > 1 && iWordsLength >= 2 &&
((nMode != ALIGN_JUSTIFY_EX || !bNextLineIsBlank || iLineStart == iLineEnd) ||
(bNextLineIsBlank && iWordsLength > (iMaxLength - iMinIndent) * 0.75))) {
int iGaps = iWords - 1;
@ -3704,15 +3710,15 @@ void EditAlignText(int nMode)
}
}
FreeMem(pWords);
FreeMem(wchNewLineBuf);
FreeMem(wchLineBuf);
FreeMem(chNewLineBuf);
} else {
InfoBoxLng(MB_ICONERROR, NULL, IDS_MUI_BUFFERTOOSMALL);
}
FreeMem(pWords);
FreeMem(wchNewLineBuf);
FreeMem(wchLineBuf);
FreeMem(chNewLineBuf);
if (iAnchorPos > iCurPos) {
iCurPos = SciCall_FindColumn(iLineStart, iCurCol);
iAnchorPos = SciCall_FindColumn(_lnend, iAnchorCol);
@ -3977,6 +3983,7 @@ void EditToggleLineCommentsExtended(LPCWSTR pwszComment, bool bInsertAtStart)
switch (iAction) {
case 0:
iAction = 2;
// fall through
case 2:
SciCall_SetTargetRange(iIndentPos, iSelPos);
Sci_ReplaceTargetTestChgHist(0, "");
@ -3991,6 +3998,7 @@ void EditToggleLineCommentsExtended(LPCWSTR pwszComment, bool bInsertAtStart)
switch (iAction) {
case 0:
iAction = 1;
// fall through
case 1: {
DocPos const iPos = SciCall_FindColumn(iLine, iCommentCol);
SciCall_InsertText(iPos, mszComment);
@ -4026,7 +4034,7 @@ void EditToggleLineCommentsExtended(LPCWSTR pwszComment, bool bInsertAtStart)
//
// _AppendSpaces()
//
static DocPos _AppendSpaces(HWND hwnd, DocLn iLineStart, DocLn iLineEnd, DocPos iMaxColumn, bool bSkipEmpty)
static DocPos _AppendSpaces(HWND hwnd, DocLn iLineStart, DocLn iLineEnd, DocPos iMaxColumn, bool bSkipEmpty)
{
UNREFERENCED_PARAMETER(hwnd);
@ -4080,7 +4088,7 @@ void EditPadWithSpaces(HWND hwnd, bool bSkipEmpty) {
//~UndoTransActionBegin(); // outside defined
if (Sci_IsMultiOrRectangleSelection() && !SciCall_IsSelectionEmpty()) {
if (Sci_IsMultiOrRectangleSelection()) {
DocPos const selAnchorMainPos = SciCall_GetRectangularSelectionAnchor();
DocPos const selCaretMainPos = SciCall_GetRectangularSelectionCaret();
@ -4094,52 +4102,55 @@ void EditPadWithSpaces(HWND hwnd, bool bSkipEmpty) {
DocLn const iLineCount = abs_p(iRcCaretLine - iRcAnchorLine) + 1;
// lots of spaces
DocPos const spBufSize = max_p(iAnchorColumn, selCaretMainPos);
DocPos const spBufSize = max_p(iAnchorColumn, iCaretColumn);
char * const pSpaceBuffer = (char *)AllocMem((spBufSize + 1) * sizeof(char), HEAP_ZERO_MEMORY);
FillMemory(pSpaceBuffer, spBufSize * sizeof(char), ' ');
DocPos * const pVspAVec = (DocPos *)AllocMem(iLineCount * sizeof(DocPos), HEAP_ZERO_MEMORY);
DocPos * const pVspCVec = (DocPos *)AllocMem(iLineCount * sizeof(DocPos), HEAP_ZERO_MEMORY);
for (DocLn i = 0; i < iLineCount; ++i) {
pVspAVec[i] = SciCall_GetSelectionNAnchorVirtualSpace(i);
pVspCVec[i] = SciCall_GetSelectionNCaretVirtualSpace(i);
}
if (pSpaceBuffer && pVspAVec && pVspCVec) {
DocPos i = 0;
DocPos iSpcCount = 0;
DocLn const iLnIncr = (iRcAnchorLine <= iRcCaretLine) ? ((DocLn)+1) : ((DocLn)-1);
DocLn iLine = iRcAnchorLine - iLnIncr;
do {
iLine += iLnIncr;
DocPos const iInsPos = SciCall_GetLineEndPosition(iLine);
DocPos const cntVSp = bSelLeft2Right ? pVspCVec[i++] : pVspAVec[i++];
bool const bSkip = (bSkipEmpty && (iInsPos <= SciCall_PositionFromLine(iLine)));
FillMemory(pSpaceBuffer, spBufSize * sizeof(char), ' ');
if ((cntVSp > 0) && !bSkip) {
pSpaceBuffer[cntVSp] = '\0';
SciCall_InsertText(iInsPos, pSpaceBuffer);
pSpaceBuffer[cntVSp] = ' ';
iSpcCount += cntVSp;
for (DocLn i = 0; i < iLineCount; ++i) {
pVspAVec[i] = SciCall_GetSelectionNAnchorVirtualSpace(i);
pVspCVec[i] = SciCall_GetSelectionNCaretVirtualSpace(i);
}
} while ((iLine != iRcCaretLine) && (i < iLineCount));
DocPos i = 0;
DocPos iSpcCount = 0;
DocLn const iLnIncr = (iRcAnchorLine <= iRcCaretLine) ? ((DocLn)+1) : ((DocLn)-1);
DocLn iLine = iRcAnchorLine - iLnIncr;
do {
iLine += iLnIncr;
DocPos const iInsPos = SciCall_GetLineEndPosition(iLine);
DocPos const cntVSp = bSelLeft2Right ? pVspCVec[i++] : pVspAVec[i++];
bool const bSkip = (bSkipEmpty && (iInsPos <= SciCall_PositionFromLine(iLine)));
if ((cntVSp > 0) && !bSkip) {
pSpaceBuffer[cntVSp] = '\0';
SciCall_InsertText(iInsPos, pSpaceBuffer);
pSpaceBuffer[cntVSp] = ' ';
iSpcCount += cntVSp;
}
} while ((iLine != iRcCaretLine) && (i < iLineCount));
if (iRcAnchorLine <= iRcCaretLine) {
if (bSelLeft2Right) {
EditSetSelectionEx(selAnchorMainPos + pVspAVec[0], selCaretMainPos + iSpcCount, 0, 0);
} else {
EditSetSelectionEx(selAnchorMainPos + pVspAVec[0], selCaretMainPos + pVspCVec[iLineCount - 1] + iSpcCount - pVspAVec[iLineCount - 1], 0, 0);
}
} else {
if (bSelLeft2Right) {
EditSetSelectionEx(selAnchorMainPos + pVspAVec[0] + iSpcCount - pVspCVec[0], selCaretMainPos + pVspCVec[iLineCount - 1], 0, 0);
} else {
EditSetSelectionEx(selAnchorMainPos + iSpcCount, selCaretMainPos + pVspCVec[iLineCount - 1], 0, 0);
}
}
}
FreeMem(pSpaceBuffer);
if (iRcAnchorLine <= iRcCaretLine) {
if (bSelLeft2Right) {
EditSetSelectionEx(selAnchorMainPos + pVspAVec[0], selCaretMainPos + iSpcCount, 0, 0);
} else {
EditSetSelectionEx(selAnchorMainPos + pVspAVec[0], selCaretMainPos + pVspCVec[iLineCount - 1] + iSpcCount - pVspAVec[iLineCount - 1], 0, 0);
}
} else {
if (bSelLeft2Right) {
EditSetSelectionEx(selAnchorMainPos + pVspAVec[0] + iSpcCount - pVspCVec[0], selCaretMainPos + pVspCVec[iLineCount - 1], 0, 0);
} else {
EditSetSelectionEx(selAnchorMainPos + iSpcCount, selCaretMainPos + pVspCVec[iLineCount - 1], 0, 0);
}
}
FreeMem(pVspCVec);
FreeMem(pVspAVec);
@ -4151,15 +4162,10 @@ void EditPadWithSpaces(HWND hwnd, bool bSkipEmpty) {
const DocPos iSelStart = SciCall_GetSelectionStart();
const DocPos iSelEnd = SciCall_GetSelectionEnd();
DocLn iStartLine = 0;
DocLn iEndLine = Sci_GetLastDocLineNumber();
if (iSelStart != iSelEnd) {
iStartLine = SciCall_LineFromPosition(iSelStart);
iEndLine = SciCall_LineFromPosition(iSelEnd);
if (iSelEnd < SciCall_GetLineEndPosition(iEndLine)) {
--iEndLine;
}
DocLn iStartLine = SciCall_LineFromPosition(iSelStart);
DocLn iEndLine = SciCall_LineFromPosition(iSelEnd);
if (iSelEnd < SciCall_GetLineEndPosition(iEndLine)) {
--iEndLine;
}
if (iStartLine < iEndLine) {
DocPos iMaxColumn = 0;
@ -4193,8 +4199,8 @@ void EditStripFirstCharacter(HWND hwnd)
return;
}
DocPos const iSelStart = SciCall_IsSelectionEmpty() ? 0 : SciCall_GetSelectionStart();
DocPos const iSelEnd = SciCall_IsSelectionEmpty() ? Sci_GetDocEndPosition() : SciCall_GetSelectionEnd();
DocPos const iSelStart = SciCall_GetSelectionStart();
DocPos const iSelEnd = SciCall_GetSelectionEnd();
DocLn const iLineStart = SciCall_LineFromPosition(iSelStart);
DocLn const iLineEnd = SciCall_LineFromPosition(iSelEnd);
@ -4220,8 +4226,8 @@ void EditStripFirstCharacter(HWND hwnd)
StringCchCopyNA(lineBuffer, SizeOfMem(lineBuffer), SciCall_GetRangePointer(nextPos, len + 1), len);
SciCall_SetTargetRange(selTargetStart, selTargetEnd);
Sci_ReplaceTargetTestChgHist(len, lineBuffer);
remCount += (nextPos - selTargetStart);
}
remCount += (nextPos - selTargetStart);
} // for()
FreeMem(lineBuffer);
}
@ -4313,8 +4319,10 @@ void EditStripLastCharacter(HWND hwnd, bool bIgnoreSelection, bool bTrailingBlan
lineBuffer[++i] = lineBuffer[end++]; // add "\r\n" if any
}
diff = len - (++i);
SciCall_SetTargetRange(selTargetStart, selTargetEnd);
Sci_ReplaceTargetTestChgHist(-1, lineBuffer);
if (diff > 0) {
SciCall_SetTargetRange(selTargetStart, selTargetEnd);
Sci_ReplaceTargetTestChgHist(-1, lineBuffer);
}
}
} else {
DocPos const prevPos = SciCall_PositionBefore(selTargetEnd);
@ -4347,14 +4355,16 @@ void EditStripLastCharacter(HWND hwnd, bool bIgnoreSelection, bool bTrailingBlan
DocPos const iEndPos = SciCall_GetLineEndPosition(iLine);
if (bTrailingBlanksOnly) {
DocPos i = iEndPos;
char ch = '\0';
do {
ch = SciCall_GetCharAt(--i);
} while ((i >= iStartPos) && IsBlankCharA(ch));
if ((++i) < iEndPos) {
SciCall_SetTargetRange(i, iEndPos);
Sci_ReplaceTargetTestChgHist(0, "");
if (iStartPos < iEndPos) {
DocPos i = iEndPos;
char ch = '\0';
do {
ch = SciCall_GetCharAt(--i);
} while ((i >= iStartPos) && IsBlankCharA(ch));
if ((++i) < iEndPos) {
SciCall_SetTargetRange(i, iEndPos);
Sci_ReplaceTargetTestChgHist(0, "");
}
}
} else { // any char at line end
if (iStartPos < iEndPos) {
@ -4371,6 +4381,27 @@ void EditStripLastCharacter(HWND hwnd, bool bIgnoreSelection, bool bTrailingBlan
}
//=============================================================================
//
// EditHasTrailingBlanks()
//
bool EditHasTrailingBlanks()
{
DocLn const iLineCount = SciCall_GetLineCount();
for (DocLn iLine = 0; iLine < iLineCount; ++iLine) {
DocPos const iStartPos = SciCall_PositionFromLine(iLine);
DocPos const iEndPos = SciCall_GetLineEndPosition(iLine);
if (iEndPos > iStartPos) {
char const ch = SciCall_GetCharAt(iEndPos - 1);
if (IsBlankCharA(ch)) {
return true;
}
}
}
return false;
}
//=============================================================================
//
// EditCompressBlanks()

View File

@ -80,6 +80,7 @@ void EditToggleLineCommentsExtended(LPCWSTR pwszComment, bool bInsertAtStart);
void EditPadWithSpaces(HWND hwnd, bool bSkipEmpty);
void EditStripFirstCharacter(HWND hwnd);
void EditStripLastCharacter(HWND hwnd, bool bIgnoreSelection, bool bTrailingBlanksOnly);
bool EditHasTrailingBlanks();
void EditCompressBlanks();
void EditRemoveBlankLines(HWND hwnd, bool bMerge, bool bRemoveWhiteSpace);
void EditUniteDuplicateLines(HWND hwnd, bool bRemoveEmptyLines, bool bRemoveLastDup);

View File

@ -127,6 +127,9 @@ HPATHL g_tchToolbarBitmapDisabled = NULL;
WCHAR Default_PreferredLanguageLocaleName[LOCALE_NAME_MAX_LENGTH + 1] = { L'\0' };
// zoom conversion helper (forward declaration)
static int ZoomPercentToSciLevel(int percent);
// ------------------------------------
HPATHL s_hpthRelaunchElevatedFile = NULL;
@ -639,6 +642,7 @@ static void _InitGlobals()
Globals.iWhiteSpaceSize = 2;
Globals.iCaretOutLineFrameSize = 0;
Globals.iZoomPercent = NP3_DEFAULT_ZOOM;
Globals.DOSEncoding = CPI_NONE;
Globals.bZeroBasedColumnIndex = false;
@ -2192,6 +2196,11 @@ LRESULT CALLBACK MainWndProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
case WM_MOUSEWHEEL:
if (wParam & MK_CONTROL) {
if (GET_WHEEL_DELTA_WPARAM(wParam) > 0) {
NP3_ZoomIn();
} else if (GET_WHEEL_DELTA_WPARAM(wParam) < 0) {
NP3_ZoomOut();
}
ShowZoomCallTip();
} else if (wParam & MK_RBUTTON) {
// Hold RIGHT MOUSE BUTTON and SCROLL to cycle through UNDO history
@ -2728,7 +2737,7 @@ LRESULT MsgCreate(HWND hwnd, WPARAM wParam,LPARAM lParam)
Encoding_Current(Settings.DefaultEncoding);
SciCall_SetZoom(g_IniWinInfo.zoom ? g_IniWinInfo.zoom : 100);
NP3_ApplyZoom(g_IniWinInfo.zoom ? g_IniWinInfo.zoom : NP3_DEFAULT_ZOOM);
return 0LL;
}
@ -6217,19 +6226,19 @@ LRESULT MsgCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
break;
case IDM_VIEW_ZOOMIN: {
SciCall_ZoomIn();
NP3_ZoomIn();
ShowZoomCallTip();
}
break;
case IDM_VIEW_ZOOMOUT: {
SciCall_ZoomOut();
NP3_ZoomOut();
ShowZoomCallTip();
}
break;
case IDM_VIEW_RESETZOOM: {
SciCall_SetZoom(100);
NP3_ApplyZoom(NP3_DEFAULT_ZOOM);
ShowZoomCallTip();
}
break;
@ -8960,8 +8969,8 @@ static LRESULT _MsgNotifyFromEdit(HWND hwnd, const SCNotification* const scn)
case SCN_ZOOM:
SciCall_SetWhiteSpaceSize(MulDiv(Globals.iWhiteSpaceSize, SciCall_GetZoom(), 100));
SciCall_SetCaretLineFrame(MulDiv(Globals.iCaretOutLineFrameSize, SciCall_GetZoom(), 100));
SciCall_SetWhiteSpaceSize(MulDiv(Globals.iWhiteSpaceSize, Globals.iZoomPercent, 100));
SciCall_SetCaretLineFrame(MulDiv(Globals.iCaretOutLineFrameSize, Globals.iZoomPercent, 100));
UpdateToolbar();
UpdateMargins(true);
break;
@ -9903,10 +9912,10 @@ static void _UpdateToolbarDelayed()
EnableTool(Globals.hwndToolbar, IDT_VIEW_TOGGLE_VIEW, b2 && IsFocusedViewAllowed());
CheckTool(Globals.hwndToolbar, IDT_VIEW_TOGGLE_VIEW, tv);
int const zoom = SciCall_GetZoom();
CheckTool(Globals.hwndToolbar, IDT_VIEW_ZOOMIN, (zoom > 100));
CheckTool(Globals.hwndToolbar, IDT_VIEW_RESETZOOM, (zoom == 100));
CheckTool(Globals.hwndToolbar, IDT_VIEW_ZOOMOUT, (zoom < 100));
int const zoom = NP3_GetZoomPercent();
CheckTool(Globals.hwndToolbar, IDT_VIEW_ZOOMIN, (zoom > NP3_DEFAULT_ZOOM));
CheckTool(Globals.hwndToolbar, IDT_VIEW_RESETZOOM, (zoom == NP3_DEFAULT_ZOOM));
CheckTool(Globals.hwndToolbar, IDT_VIEW_ZOOMOUT, (zoom < NP3_DEFAULT_ZOOM));
}
@ -10906,7 +10915,7 @@ bool FileLoad(const HPATHL hfile_pth, const FileLoadFlags fLoadFlags, const DocP
UpdateToolbar();
UpdateMargins(true);
if (SciCall_GetZoom() != 100) {
if (NP3_GetZoomPercent() != NP3_DEFAULT_ZOOM) {
ShowZoomCallTip();
}
@ -11156,7 +11165,7 @@ bool FileLoad(const HPATHL hfile_pth, const FileLoadFlags fLoadFlags, const DocP
}
UpdateMargins(true);
if (SciCall_GetZoom() != 100) {
if (NP3_GetZoomPercent() != NP3_DEFAULT_ZOOM) {
ShowZoomCallTip();
}
UpdateToolbar_Now(Globals.hwndMain);
@ -11390,7 +11399,7 @@ bool FileSave(FileSaveFlags fSaveFlags)
}
}
bool const bSaveNeeded = (IsSaveNeeded() || IsFileChangedFlagSet() || Settings.FixTrailingBlanks) && !bIsEmptyNewFile;
bool const bSaveNeeded = (IsSaveNeeded() || IsFileChangedFlagSet() || (Settings.FixTrailingBlanks && EditHasTrailingBlanks())) && !bIsEmptyNewFile;
if (!(fSaveFlags & FSF_SaveAs) && !(fSaveFlags & FSF_SaveAlways) && !bSaveNeeded) {
_MRU_UpdateSession();
@ -12041,6 +12050,68 @@ void ResetMouseDWellTime()
SciCall_SetMouseDWellTime(500); // needed for "Mouse cursor vanish handling (hide while typing)"
}
//=============================================================================
//
// NP3 Zoom Helpers — percentage-based zoom with Scintilla's additive zoom API
//
// Scintilla zoom is additive: sizeZoomed = fontSize + zoomLevel * FontSizeMultiplier
// NP3 displays percentage (100% = normal). Conversion uses GLOBAL_INITIAL_FONTSIZE.
//
static int ZoomPercentToSciLevel(int percent)
{
// zoomLevel = baseFontSizeSM * (percent - 100) / 10000
// where baseFontSizeSM = GLOBAL_INITIAL_FONTSIZE * 100 (FontSizeMultiplier units)
__int64 const raw = (__int64)NP3_ZOOM_BASE_FONT_SIZE * (percent - 100);
return (int)((raw >= 0) ? (raw + 5000) / 10000 : (raw - 5000) / 10000);
}
void NP3_ApplyZoom(int percent)
{
percent = clampi(percent, NP3_MIN_ZOOM_PERCENT, NP3_MAX_ZOOM_PERCENT);
Globals.iZoomPercent = percent;
SciCall_SetZoom(ZoomPercentToSciLevel(percent));
}
void NP3_ZoomIn()
{
int const curLevel = SciCall_GetZoom();
int percent = Globals.iZoomPercent;
if (percent < 200) {
percent += 10;
} else if (percent < 500) {
percent += 25;
} else {
percent += 50;
}
percent = min_i(percent, NP3_MAX_ZOOM_PERCENT);
int newLevel = ZoomPercentToSciLevel(percent);
if (newLevel <= curLevel) {
newLevel = curLevel + 1;
}
Globals.iZoomPercent = percent;
SciCall_SetZoom(newLevel);
}
void NP3_ZoomOut()
{
int const curLevel = SciCall_GetZoom();
int percent = Globals.iZoomPercent;
percent -= 10;
percent = max_i(percent, NP3_MIN_ZOOM_PERCENT);
int newLevel = ZoomPercentToSciLevel(percent);
if (newLevel >= curLevel) {
newLevel = curLevel - 1;
}
Globals.iZoomPercent = percent;
SciCall_SetZoom(newLevel);
}
int NP3_GetZoomPercent()
{
return Globals.iZoomPercent;
}
//=============================================================================
//
// ShowZoomCallTip()
@ -12051,7 +12122,7 @@ void ShowZoomCallTip()
int const delayClr = Settings2.ZoomTooltipTimeout;
if (delayClr >= (_MQ_TIMER_CYCLE << 3)) {
StringCchPrintfA(chToolTip, COUNTOF(chToolTip), "Zoom: %i%%", SciCall_GetZoom());
StringCchPrintfA(chToolTip, COUNTOF(chToolTip), "Zoom: %i%%", NP3_GetZoomPercent());
DocPos const iPos = SciCall_PositionFromLine(SciCall_GetFirstVisibleLine());

View File

@ -95,6 +95,11 @@ bool CheckAutoLoadMostRecent();
void ShowZoomCallTip();
void ShowWrapAroundCallTip(bool forwardSearch);
void NP3_ZoomIn();
void NP3_ZoomOut();
void NP3_ApplyZoom(int percent);
int NP3_GetZoomPercent();
void MarkAllOccurrences(const LONG64 delay, const bool bForceClear);
void UpdateToolbar();

View File

@ -358,8 +358,9 @@ extern "C" bool EditPrint(HWND hwnd,LPCWSTR pszDocTitle,LPCWSTR pszPageFormat)
SendMessage(hwnd,SCI_SETPRINTCOLOURMODE,printColorModes[Settings.PrintColorMode],0);
//SendMessage(hwnd, SCI_SETPRINTWRAPMODE, SC_WRAP_WORD, 0); // default: SC_WRAP_WORD
// Set print magnification...
SendMessage(hwnd, SCI_SETPRINTMAGNIFICATION, (WPARAM)Settings.PrintZoom, 0);
// Set print magnification (convert NP3 percent to Scintilla additive points)
int const printZoomLevel = (int)(((__int64)NP3_ZOOM_BASE_FONT_SIZE * (Settings.PrintZoom - 100) + 5000) / 10000);
SendMessage(hwnd, SCI_SETPRINTMAGNIFICATION, (WPARAM)printZoomLevel, 0);
DocPos const lengthDocMax = SciCall_GetTextLength();
DocPos lengthDoc = lengthDocMax;
@ -559,7 +560,7 @@ static UINT_PTR CALLBACK _LPSetupHookProc(HWND hwnd, UINT uiMsg, WPARAM wParam,
UDACCEL const acc[1] = { { 0, 10 } };
SendDlgItemMessage(hwnd, 30, EM_LIMITTEXT, 32, 0);
SendDlgItemMessage(hwnd, 31, UDM_SETACCEL, 1, (WPARAM)acc);
SendDlgItemMessage(hwnd, 31, UDM_SETRANGE32, SC_MIN_ZOOM_LEVEL, SC_MAX_ZOOM_LEVEL);
SendDlgItemMessage(hwnd, 31, UDM_SETRANGE32, NP3_MIN_ZOOM_PERCENT, NP3_MAX_ZOOM_PERCENT);
SendDlgItemMessage(hwnd, 31, UDM_SETPOS32, 0, Settings.PrintZoom);
// Set header options

View File

@ -1570,7 +1570,7 @@ void Style_SetLexer(HWND hwnd, PEDITLEXER pLexNew)
}
Globals.iWhiteSpaceSize = iValue;
//SciCall_SetWhiteSpaceSize(iValue);
SciCall_SetWhiteSpaceSize(MulDiv(Globals.iWhiteSpaceSize, SciCall_GetZoom(), 100)); // needs update on zoom
SciCall_SetWhiteSpaceSize(MulDiv(Globals.iWhiteSpaceSize, NP3_GetZoomPercent(), 100)); // needs update on zoom
// whitespace colors
rgb = RGB(0, 0, 0);
@ -2087,7 +2087,7 @@ void Style_HighlightCurrentLine(HWND hwnd, int iHiLitCurLn)
iFrameSize = max_i(1, ScaleIntToDPI(hwnd, iFrameSize));
Globals.iCaretOutLineFrameSize = iFrameSize;
// SciCall_SetCaretLineFrame(iFrameSize);
SciCall_SetCaretLineFrame(MulDiv(Globals.iCaretOutLineFrameSize, SciCall_GetZoom(), 100)); // needs update on zoom
SciCall_SetCaretLineFrame(MulDiv(Globals.iCaretOutLineFrameSize, NP3_GetZoomPercent(), 100)); // needs update on zoom
}
else {
SciCall_SetCaretLineFrame(0);

View File

@ -249,6 +249,13 @@ typedef enum STATUS_SECTOR_T {
#define GLOBAL_INITIAL_FONTSIZE 11.0f
// NP3 zoom constants (percentage-based, 100 = normal)
#define NP3_MIN_ZOOM_PERCENT 10
#define NP3_MAX_ZOOM_PERCENT 1000
#define NP3_DEFAULT_ZOOM 100
// Base font size in Scintilla FontSizeMultiplier units (points * 100) for zoom conversion
#define NP3_ZOOM_BASE_FONT_SIZE ((int)(GLOBAL_INITIAL_FONTSIZE * 100))
// --------------------------------------------------------------------------
// |- len -|
@ -523,6 +530,7 @@ typedef struct GLOBALS_T {
int iWhiteSpaceSize;
int iCaretOutLineFrameSize;
int iZoomPercent;
bool bMinimizedToTray;
bool bZeroBasedColumnIndex;