Unable to type certain characters on non US keyboards/IME on macOS app using Scintilla
Unable to type certain characters on non US keyboards/IME on macOS app using Scintilla
Committed as [ed808b], [490e80].
Small optimization avoids retrieving font ascent twice.
Feature [feature-requests:#1571]. Improve determination of monospace.
The goal without change how aveCharWidth is measured is change how monospaceASCII is computed. Patch changed monospaceASCII to (maxWidth - minWidth)/minWidth < monospaceWidthEpsilon => (maxWidth - minWidth) < minWidth * monospaceWidthEpsilon, as minWidth is used to render ASCII characters.
This issue is too complex and has become a discussion of associated aspects. The main initial issue is that Unifont contains bad metrics and that is exacerbated by Notepad4 changing Scintilla to use aveCharWidth instead of monospaceCharacterWidth. Changing the behaviour of Scintilla may cause problems in downstream projects so should be limited in scope and specify a clear goal. 'Check monospaced and average character width' is not a clear goal.
Potential narrow fix. There may be related issues not fixed by this patch. diff -r 4b8c335b8c50 src/Document.cxx --- a/src/Document.cxx Thu Dec 18 14:49:28 2025 +1100 +++ b/src/Document.cxx Fri Dec 19 14:16:29 2025 +1100 @@ -1590,7 +1590,10 @@ } cb.PerformUndoStep(); if (action.at != ActionType::container) { - ModifiedAt(action.position); + if ((action.at == ActionType::remove) || (action.position < LengthNoExcept()) || (action.position == 0)) + ModifiedAt(action.position); + else + ModifiedAt(action.position...
SetWindowSubclass seems to be a better approach in more complex situations in applications where there may be multiple features or code sources (like plug-ins and scripting) that need to subclass a window. Applications that use Scintilla will likely be more maintainable if they use SetWindowSubclass since there are often multiple reasons to enhance Scintilla. Once SetWindowSubclass is used for one element, its then more consistent to use it in all cases.
There's a difference between Document::DeleteChars and Document::Undo: // DeleteChars: if ((pos < LengthNoExcept()) || (pos == 0)) ModifiedAt(pos); else ModifiedAt(pos-1); // Undo: ModifiedAt(action.position);
Undo added text at end of document
It seems system (checked wine) also use English letters to measure average width. See GdiGetCharDimensions() at https://gitlab.winehq.org/wine/wine/blob/master/dlls/gdi32/text.c which is used by dialog creation at https://gitlab.winehq.org/wine/wine/blob/master/dlls/user32/dialog.c
OK, just fell code with SetWindowSubclass is clean.
Convert old style cast into more specific C++ cast.
Changed to CALLBACK with [94f6bd] [bbbd84] .
Feature [feature-requests:#1573]. Replace archaic PASCAL with current CALLBACK.
Feature [feature-requests:#1573]. Replace archaic PASCAL with current CALLBACK.
s/PASCAL/CALLBACK/ is fine although not significant.
I'm not seeing a strong benefit here with a simple use of window bytes replaced by a window property. The disadvantages listed above don't seem relevant. Scintilla never removes the subclass and data is stored in the C++ class so is easy to access. Is there some needed function that can be implemented by application code subclassing the listbox instead of the ListBoxX? As explained in the above link, SetWindowSubclass uses a UxSubclassInfo property which will be less efficient. Maybe the cost isn't...
SciTEWin::AboutMessage() (in SciTEWinDlg.cxx) uses GWLP_WNDPROC and GWLP_USERDATA.
I think use GWLP_USERDATA on lb is fine as it's system ListBox control which private to and used by ListBoxX (the wid container). Update win32/makefile.
inefficient (use GetProp() ... That is something I'd be worried about as well. The change also added comctl32.dll dependency Yes, it would need to be in other Win32 build files like win32/makefile/ g++ -shared -static -mwindows -o ../bin/Scintilla.dll -s AutoComplete.o CallTip.o CaseConvert.o CaseFolder.o CellBuffer.o ChangeHistory.o CharacterCategoryMap.o CharacterType.o CharClassify.o ContractionState.o DBCS.o Decoration.o Document.o EditModel.o Editor.o EditView.o Geometry.o Indicator.o KeyMap.o...
Looking source code for SetWindowSubclass() at https://gitlab.winehq.org/wine/wine/blob/master/dlls/comctl32/commctrl.c, it's just wrap for SubclassWindow() and CallWindowProc(), maybe inefficient (use GetProp() to retrieve callback function and data). The change also added comctl32.dll dependency for Scintilla.dll, may not a problem for GUI app/lib. With old approach, ListBoxX::ControlWndProc can still be eliminate (to avoid PointerFromWindow(::GetParent(hWnd))) with something like SetWindowLongPtr(lb,...
Change ListBoxX to using modern control subclassing
Modularising the HTML lexer Will do some experiments later, as I already made a separated PHP lexer (with complete PHP styling, more JavaScript styles, also basic CSS highlighting) at https://github.com/zufuliu/notepad4/blob/main/scintilla/lexers/LexPHP.cxx Rewrite the lexer or new lexers with StyleContext would improve readability and maintainability, but this may slow down loading large program generated HTML/XML file.
Modularising the HTML lexer would be a worthwhile project. It needs a good configurable way of crossing from base to server and return. The state for the base lexer will be separate from the server state and both need to coordinated with attaching to lines and saving for future calls. As well as determining styles, fold level may also be affected by both. It may be better to separate fold determination into a separate pass as is done by most languages. Separating out the processing of client side...
SCE_HB_OPERATOR isn't needed if client-side VBScript is removed. keep sync client/server side VBScript styles just to make the lexer simple. Reclaiming the client-side VBScript and client-side Python style IDs needs a plan and possibly a separate new lexer. for backward compatibility reason, they probably needs to be kept for a while. possibly a separate new lexer. Current HTML lexer can be separated by server side languages or template: 1. A base HTML/XML lexer that contains SGML, tag, JavaScript...
SCE_HB_OPERATOR isn't needed if client-side VBScript is removed. Reclaiming the client-side VBScript and client-side Python style IDs needs a plan and possibly a separate new lexer. There still appears to be some use of server-side VBScript so I don't know if that can be removed.
Maybe this (adding SCE_HB_OPERATOR and SCE_HBA_OPERATOR) can be implemented now as more styles can be used and VBScript is dead, so it's no longer need to reserve styles.
Avoid link errors from using sanitizer.
Change log from Scintilla.
SCI_SETSELECTIONNSTART and END set anchor and caret instead
Committed an implementation as [ac6a2d].
Bug [#2488]. Fix SCI_SETSELECTIONNSTART and SCI_SETSELECTIONNEND.
With the current patch not blocking drags into Scintilla, there is an API policy choice. The API is currently a simple boolean but if drags from and to need to be independently blocked then the API will be more complex, perhaps a bit mask or multiple APIs.
Use symbolic constants and simplify code.
Added escape sequence suport as escseq.
Remove unnecessary code.
Simplify by using starts_with.
Improve type safety and shorten code.
Replace 'magic' literals with named constants.
Yeah, pass function is good. not sure whether it has security or related problem, so it's declared as reference in the patch. using CreateFoldMapFunc = void (&)(int codePage, FoldMap *foldingMap);
Commit [8b3f2c] uses a vector for FoldMaps. Similar to patches above but without passing a function since that's a technique that has made evolution more difficult in the past.
Feature [feature-requests:#1564]. Use vector to store FoldMaps as map is not
Feature [feature-requests:#1564]. Remove DBCSSetFoldMap as never called.
Committed the Fold simplification with [750626].
Feature [feature-requests:#1564]. Simplify Fold.
Use const where reasonable.
Apply rule-of-5 since painter holds a resource.
When I saw 'multicolumn' I thought it was going to be a way to isolate columns in a tabular file like a CSV or database dump then prevent (most) user actions from affecting other columns. To me the concept is quite strange. Maybe it will be of interest to others. Without very strong interest from other users and downstream projects, I don't think the feature is worth the additional code size and complexity.
GTK print
Multicolumn editor
No problem, let's avoid it completely in SciTE, then.
but abandoned due to binary size increment (not figured out why) OK. Tracing some DBCS examples, I haven't seen the current Fold be prominent, so this may not be an area that will repay more effort.
No real use case for this feature has been described so it is hard to understand the scope of control needed. The earlier post talked about Notepad++ and how they present the option is up to them. For SciTE, I'd either avoid it completely or make it a properties file setting instead of adding a menu item.
Its difficult to test interactive feature but the API can be checked to return a reasonable result with the setter changing this result. The testUndoCollection method can be used as an example. The patch blocks dragging from Scintilla but not dropping into Scintilla. It is still possible to drag from another application like Chrome into Scintilla. It would be better, but not essential, to use a selection I beam cursor over the selection when it can not be dragged instead of the arrow.
What would assigning the feature request do? It's not really a concept within this tracker or the project.
@nyamatongwe could you please assign this feature request to me? Thank you.
It may be possible to expose FoldMap to the DBCS branch of Document::FindText in a way that the compiler will be able to inline. I tried following in Notepad4 but abandoned due to binary size increment (not figured out why). 1. move CaseFolderDBCS into CaseFolder.h. 2. cast pcf.get() to CaseFolderDBCS pointer. 3. use following method to replace bytes folding: const char *FoldDualByte(unsigned char lead, unsigned char trail) const noexcept { const uint16_t ind = DBCSIndex(lead, trail); const char...
The condition could be simplified by ensure mixed is NUL-terminated (const char *search parameter) or larger than lenMixed (local const char bytes).
And here is the patch to add the feature to SciTE.
Here is a first version of the patch. Not sure how to write unit tests, your help is very welcome there. Thank you!
If APIs or embedded font metadata are producing bad results then it is hard to fix sensibly. A bug report could be sent to Unifont or a particular version could be recommended if this is present only in some versions. https://savannah.gnu.org/projects/unifont/
Improved behaviour when lead byte followed by non trail byte with [2f4c2f].
Feature [feature-requests:#1564]. Ensure DCBS fold map initialized and folding
not the more complex cases. Some code pages (949, 1361) contains complex cases, e.g. ß to ss, but the output is still same 2-bytes length.
BothFold() and FindText() loops don't check DBCS trail byte (unlike UTF-8), filling foldingMap with any value for invalid bytes should not mater, invalid bytes rarely match. A more correct/robust implement would like UTF-8 CaseConvertString(): Character has no conversion so copy the input to output.
It looks a bug in the Unifont font itself, it's tmAveCharWidth is same as tmMaxCharWidth.
FoldMap only covers cases where folding produces the same length as input. This wasn't certain before FoldMap was implemented but it turned out to be true in all tested successful cases. While the DBCS encodings include Greek letters, there are only the basic letters, not the more complex cases. pcf->Fold() is only used inside Document::FindText(), and is over-allocated, boundary checks inside Fold() can all be omitted. Still want some tests in case it is called in other circumstances. Maybe protect...
Since it is GDI that is providing poor data, a change to just that platform layer will have less potential to cause unexpected results. Perhaps just limit the return of SurfaceGDI::AverageCharWidth to a maximum of tmMaxCharWidth.
will decrease the value and may lead to unexpected changes that are visible to users. Only happens for proportional font, so does SurfaceImpl::AverageCharWidth() in PlatCocoa.mm. That's a little strange. Are you trying to handle bi-width fonts where the Chinese characters should be exactly double the width of Roman characters? Unifont is ASCII monospaced, but GDI SurfaceGDI::AverageCharWidth() value is 2x wider than ASCII letter, use it (instead of monospaceCharacterWidth) inside PositionCache::MeasureWidths()...
Since the loop is 1:1 input:output, and the output is commonly conservatively over-allocated, the bounds checks can probably be moved outside the loop. There's a minor hassle with an odd final lead byte but that could possibly be handled after the loop. pcf->Fold() is only used inside Document::FindText(), and is over-allocated, boundary checks inside Fold() can all be omitted. constexpr size_t maxFoldingExpansion = 4; for DBCS can also be omitted. for UTF-8, maybe it can be reduced, e.g. use maxExpansionCaseConversion...
Including punctuation in the calculation of average character width will decrease the value and may lead to unexpected changes that are visible to users. Any change for Unifont should be narrow to avoid the possibility of regressions. The mentioned bug is because I use aveCharWidth instead of monospaceCharacterWidth That's a little strange. Are you trying to handle bi-width fonts where the Chinese characters should be exactly double the width of Roman characters? Using std::minmax_element would be...
Can't strongly recall the reasoning for the convoluted API but it was likely from wanting a clear way to add thread safety with locks if needed for background searching. Sharing implementation between platforms was also a goal. Adding another test inside CaseFolderDBCS::Fold would likely have worse performance than filling in those entries. Since the loop is 1:1 input:output, and the output is commonly conservatively over-allocated, the bounds checks can probably be moved outside the loop. There's...
both are slow than a plain loop like following: auto it = positions.begin(); XYPOSITION prev = *it; XYPOSITION maxWidth = prev; XYPOSITION minWidth = prev; while (++it != positions.end()) { const XYPOSITION current = *it; const XYPOSITION value = current - prev; prev = current; maxWidth = std::max(maxWidth, value); minWidth = std::min(minWidth, value); }
The UndoCollection property is a similar boolean feature. Search for 'UndoCollection' (case-insensitive) in all Scintilla files to find all the declarations, code, documentation, and tests related to this property.
std::max_element() + std::min_element() can be merged into single std::minmax_element() as we don't care which one is min/max.
Check monospaced and average character width
Thank you @nyamatongwe. Could you please point me towards an example of such a message so I can use that as a reference implementation? Thank you!
This work appears to be at an early stage where it should not be included in Scintilla as yet. If this is to be included in Scintilla it should be modifiable after start. It should add to the normal API as a SCI_ message.
This work appears to be azt an early stage where it should not be included in Scintilla as yet. If this is to be included in Scintilla it should be modifiable after start. It should add to the normal API as a SCI_ message.
Hi all, I intend to implement a V0 of this feature. I built a working proof of concept it by making a change in Notepad++'s Scintilla version. It consists in removing the line of code setting inDragDrop to DragDrop::initial in src/Editor.cxx at line 4927. This flag can be a static flag passed to Scintilla when initializing it, and that flag would be read-only from initialization. This means that, in this V0, it will not be possible to enable or disable drag-and-drop on the fly, and it will require...
Hi all, I intend to implement a V0 of this feature. I built a working proof of concept it by making a change in Notepad++'s Scintilla version. It consists in removing the line of code setting inDragDrop to DragDrop::initialin src/Editor.cxx at line 4927. This flag can be a static flag passed to Scintilla when initializing it, and that flag would be read-only from initialization. This means that, in this V0, it will not be possible to enable or disable drag-and-drop on the fly, and it will require...
Hi all, I intend to implement a V0 this feature. I tried it by making a change in Notepad++'s Scintilla version. It consists in removing the line of code setting inDragDrop to DragDrop::initialin src/Editor.cxx at line 4927. This flag can be a static flag passed to Scintilla when initializing it, and that flag would be read-only from initialization. This means that, in this V0, it will not be possible to enable or disable drag-and-drop on the fly, and it will require restarting the editor. We can...
Option to copy only matching lines to clipboard in filter view
Option to copy only matching lines to clipboard in filter view
Thanks for the pointer. This is my script: function CopySelectedVisibleLines() local startLine = editor:LineFromPosition(editor.SelectionStart) local endLine = editor:LineFromPosition(editor.SelectionEnd) local lineTexts = {} local lineText = "" for line = startLine, endLine do if editor.LineVisible[line] then lineText = editor:GetLine(line) table.insert(lineTexts, lineText) end end editor:CopyText(table.concat(lineTexts)) end Please close the ticket.
Thanks for the pointer. This is my script: function CopySelectedVisibleLines() local startLine = editor:LineFromPosition(editor.SelectionStart) local endLine = editor:LineFromPosition(editor.SelectionEnd) local lineTexts = {} local lineText = "" for line = startLine, endLine do if editor.LineVisible[line] then lineText = editor:GetLine(line) table.insert(lineTexts, lineText) end end editor:CopyText(table.concat(lineTexts)) end
Thanks for the pointer. This is my script: function CopySelectedVisibleLines() local startPos = editor.SelectionStart local endPos = editor.SelectionEnd local startLine = editor:LineFromPosition(startPos) local endLine = editor:LineFromPosition(endPos) local lineTexts = {} for line = startLine, endLine do local visible = editor.LineVisible[line] if visible then local lineText = editor:GetLine(line) table.insert(lineTexts, lineText) end end editor:CopyText(table.concat(lineTexts)) end
Thanks for the pointer. I used the following code: function CopySelectedVisibleLines() local startPos = editor.SelectionStart local endPos = editor.SelectionEnd local startLine = editor:LineFromPosition(startPos) local endLine = editor:LineFromPosition(endPos) local lineTexts = {} for line = startLine, endLine do local visible = editor.LineVisible[line] if visible ~= 0 then local lineText = editor:GetLine(line) table.insert(lineTexts, lineText) end end -- Join and put into clipboard editor:CopyText(table.concat(lineTexts))...
Thanks for the pointer. I tried to use message SCI_GETLINEVISIBLE (see [1]) but got the error Pane function / readable property / indexed writable property name expected with the following code: function CopySelectedVisibleLines() local editor = editor local startPos = editor.SelectionStart local endPos = editor.SelectionEnd local startLine = editor:LineFromPosition(startPos) local endLine = editor:LineFromPosition(endPos) local result = {} for line = startLine, endLine do -- Query Scintilla directly:...
Thanks for the pointer. I tried to use message SCI_GETLINEVISIBLE (see [1]) but got the error Pane function / readable property / indexed writable property name expected with the following code: function CopySelectedVisibleLines() local editor = editor local startPos = editor.SelectionStart local endPos = editor.SelectionEnd local startLine = editor:LineFromPosition(startPos) local endLine = editor:LineFromPosition(endPos) local result = {} for line = startLine, endLine do -- Query Scintilla directly:...
Its likely possible to write a script that does this.
Option to copy only matching lines to clipboard in filter view
Search Results and Double-Click
High DPI Screen Toolbar
Add noexcept to COM methods
Closing since the approach fails with at least one build setup.
It worked with w64devkit 2.4.0 [1], which ships gcc 15.2.0. [1] https://github.com/skeeto/w64devkit
Regexp to simulate DOTALL mode does not work