Skip to content

Fmx support#289

Draft
jareddavison wants to merge 112 commits intoTurboPack:masterfrom
jareddavison:fmx-support
Draft

Fmx support#289
jareddavison wants to merge 112 commits intoTurboPack:masterfrom
jareddavison:fmx-support

Conversation

@jareddavison
Copy link
Copy Markdown

@jareddavison jareddavison commented Feb 25, 2026

What's New in SynEdit


FMX Cross-Platform Editor

SynEdit now supports FireMonkey (FMX) alongside VCL through a three-layer architecture that shares highlighters and core logic between both frameworks.

Three-Layer Architecture

The codebase has been restructured into three layers:

  • Shared (Source/) — Platform-independent units: 66 highlighters, text buffer, types, key commands, spell-check infrastructure (Hunspell and Windows providers). These are consumed by both VCL and FMX.
  • VCL (Source/VCL/, Vcl.* prefix) — Windows-specific: DirectWrite rendering, OLE drag-drop, printing, accessibility.
  • FMX (Source/FMX/, FMX.* prefix) — Cross-platform: FMX Canvas rendering, FMX scrollbars, FMX clipboard, drag-drop.

See Architecture.md for the full technical reference.

FMX Editor (TCustomFMXSynEdit)

Unit: Source\FMX\FMX.SynEdit.pas

Inheritance: TControl

A cross-platform syntax-highlighting editor built on FireMonkey. Supports:

  • Syntax highlighting — All 66 shared highlighters work out of the box.
  • Keyboard input — Full text editing with insert/overwrite modes.
  • Selection — Mouse and keyboard selection with correct split-token rendering at selection boundaries.
  • Multi-caret editing — Multiple carets (Alt+Click), column selection (Alt+Shift+Arrows/Drag), select all matching text (Ctrl+Shift+W), carets at line ends (Alt+End). Shared TSynSelectionsBase architecture between VCL and FMX.
  • Clipboard — Cut, Copy, Paste via IFMXClipboardService.
  • Undo/Redo — Full undo/redo stack.
  • File I/OLoadFromFile, SaveToFile, LoadFromStream, SaveToStream.
  • Code folding — Collapse and expand foldable regions.
  • Search/ReplaceSearchReplace method with options for case, whole word, regex, selection-only, and replace all.
  • Completion proposalsTFMXSynCompletionProposal popup with keyboard navigation, filtering, and customizable display.
  • Plugin supportTSynFMXEditPlugin base class for extending the editor via OnCommand hooks.
  • PrintingTFMXSynEditPrint with abstract provider interface for platform-specific rendering.
  • Spell checkTFMXSynSpellCheck with shared provider infrastructure (ISynSpellCheckProvider). Includes Hunspell and Windows spell-check providers usable by both VCL and FMX.
  • Range scanning — Incremental re-scanning for multi-line highlighters (XML, HTML, Delphi, etc.).
  • Drag-and-drop (Windows) — Internal move/copy and external drop via ISynDragDropPlatform abstraction. Windows OLE implementation with CF_UNICODETEXT and CF_HTML formats. Fixes FMX framework bug where TWinDropTarget.Drop fails to report dwEffect. Auto-scroll near edges, visual caret feedback during drag, and full undo support. macOS/Linux not yet implemented — CreateSynDragDropPlatform returns nil on non-Windows platforms.
  • Scrolling — FMX TScrollBar-based scrolling with mouse wheel support.
  • Gutter — Line numbers with configurable width.
  • Right edge — Configurable right margin indicator.
  • Active line highlighting — Configurable active line background color.
  • Macro recordingTFMXSynMacroRecorder component for recording and playing back editor commands. Shared event types via SynMacroRecorderShared.pas.
  • Editor options — Auto indent, smart tabs, tabs-to-spaces, and more via TSynEditorOptions.

What's Missing (compared to VCL)

The FMX editor covers core editing functionality but does not yet have full VCL feature parity. The following VCL capabilities have no FMX equivalent:

Components & Units

VCL Unit Feature
Vcl.SynAccessibility Windows UI Automation / screen reader support
Vcl.SynAutoCorrect Auto-correction engine with customizable rules
Vcl.SynDBEdit Database-aware editor (TDataSet binding)
Vcl.SynURIOpener Hyperlink detection and opening
Vcl.SynEditPythonBehaviour Python-specific auto-indentation
Vcl.SynExportHTML HTML export with CSS styling
Vcl.SynExportRTF Rich Text Format export
Vcl.SynExportTeX LaTeX export
Vcl.SynEditPrintPreview Print preview window
Vcl.SynEditPrintMarginsDialog Print margin configuration dialog
Vcl.SynEditOptionsDialog Editor options configuration dialog
Vcl.SynEditKeyCmdEditor Key command editor dialogs
Vcl.SynDWrite DirectWrite / Direct2D hardware-accelerated rendering

Properties & Features

Feature Description
TextHint Placeholder text when editor is empty
InsertCaret / OverwriteCaret Configurable caret styles
VisibleSpecialChars Show spaces, tabs, and EOL markers
MaxUndo Configurable undo history limit
HideSelection Hide selection when editor loses focus
Indicators Line indicators (breakpoints, errors)
BracketsHighlight Bracket pair matching and highlighting
WordAtCursor / WordAtMouse Word-under-cursor/mouse queries
Scrollbar annotations Visual markers in scrollbar track
Indent guides Vertical lines showing indentation structure

Events

Event Description
OnGutterClick Click handler for gutter area (bookmarks, folding)
OnGutterGetText Custom gutter line text
OnPaint / OnPaintTransient Custom painting hooks
OnDropFiles File drag-drop from Explorer
OnScroll Scroll position change notification
OnZoom Font size zoom (Ctrl+Scroll)
OnMouseCursor Custom cursor per buffer position
OnContextHelp Context-sensitive help lookup

Rendering

The VCL editor uses DirectWrite / Direct2D for hardware-accelerated text rendering with ClearType, ligatures, and advanced typography. The FMX editor uses FMX Canvas rendering, which is adequate for most use cases but does not match DirectWrite quality or performance on Windows.

Drag-and-Drop Platform Support

FMX drag-and-drop is currently Windows-only (OLE-based via ISynDragDropPlatform). macOS and Linux are not yet implemented — CreateSynDragDropPlatform returns nil on non-Windows platforms.

New Packages

Five new packages support the three-layer architecture:

Package Description
SynEditSharedDR / SynEditSharedCR Shared runtime — types, text buffer, 66 highlighters
SynEditFMXDR / SynEditFMXCR FMX runtime — FMX editor and supporting units
SynEditFMXDD / SynEditFMXCD FMX designtime — component registration

Build order: Shared → VCL/FMX Runtime → VCL/FMX Designtime.

FMX Demos

Three FMX demos are included in Demos/FMX/:

  • HighlighterDemo — Browse 13 language highlighters (Delphi, C++, Java, Python, JavaScript, HTML, XML, CSS, SQL, JSON, C#, INI, Batch) with a consistent color scheme.
  • EditApp — Single-document editor with menus (File/Edit), status bar, file I/O, clipboard, undo/redo, and automatic highlighter detection from file extension.
  • FeaturesDemo — Comprehensive feature showcase with a controls panel, editor options toggles, search/replace dialogs, completion proposals, code folding, clipboard buttons, active line color picker, and a timestamped event log.

Test Suites

Two DUnitX test suites run headless with FailsOnNoAsserts enabled and exact-value assertions throughout.

FMX tests (Tests/FMX/FMXSynEditTests.dproj) — 428 tests, 34 fixtures:

Fixture Tests Coverage area
Buffer 10 Line add/delete/insert, text property
Caret 10 Positioning, SelectAll, GetTextRange
CodeFolding 6 Fold detection, collapse/uncollapse, levels
Commands 14 Char insert/delete, line break, tab, navigation
Content 8 Text get/set, multi-line, stream round-trip
Highlighter 5 Assignment, free notification, switching
Options 10 Default options, read-only, tab width, right edge
Search 9 Case, whole-word, regex, replace, replace-all
UndoRedo 9 Availability, restore, multiple undo/redo, redo caret
SpellCheck 20 Hunspell provider, suffix/prefix rules, suggest
WindowsSpellCheck 11 Windows spell-check COM provider
SpellCheckComponent 17 TSynSpellCheck component integration, selection dedup
BugFixes 23 Plugin dispatch, Modified, nil width, tabs, keyboard chain
CrossPlatformFixes 9 Selection colors, BlockBegin/BlockEnd setters, coordinate clamping
WordWrap 20 Enable/disable, row mapping, coordinate conversion, caret navigation, gutter
AutoIndentTabs 4 Tab preservation, mixed whitespace, disable option
PixelToBufferCoord 4 Click mapping at/near char boundaries, gutter clamp
ScrollBarSizing 3 LinesInWindow/CharsInWindow delta, scrollbar hidden
Selection 18 ecSel* commands, accumulation, collapse, replace, line-boundary
Clipboard 10 Copy/cut/paste, read-only guards, undo support
Editing 12 Line joining, overwrite mode, OnChange, BeginUpdate
Renderer 11 TColorToAlphaColor byte-swap, SysNone, metrics
CompletionProposal 12 AddItem/ClearList, filtering, position, MoveLine
DelphiFolding 26 Procedure/class/record/interface folding, class var exclusion
HTMLFolding 11 Tag pairs, void elements, comments, multi-line tags
XMLFolding 14 Elements, namespaces, PI/CDATA/DOCTYPE, multi-line tags
CSSFolding 13 Brace folding, nested @media, comments, strings
Bookmarks 15 Set/clear/goto, toggle, mark list, line clamp
Gutter 15 Band order/visibility, auto-width, BandAtX, fold sync
MultiCaret 17 Add/toggle carets, column selection, multi-caret edit/delete/backspace, merge, undo/redo
DragDropHelper 10 ComputeDropInfo, AdjustDropPos, IsDropCopy
DragDropIntegration 17 External/internal drop, move/copy, past EOL, multi-line, undo
SharedMacroEvents 14 Factory, stream round-trips, AsString, PlaybackTo callback
FMXHookedCommandHandlers 5 Register/call/suppress/unregister/multiple handlers
FMXMacroRecorder 16 State, record/playback typing/navigation, undo, serialization

VCL tests (Tests/VCL/VCLSynEditTests.dproj) — 95 tests, 5 fixtures:

Fixture Tests Coverage area
SynSpellCheck 20 Hunspell provider, suffix/prefix rules, suggest
WindowsSpellCheck 11 Windows spell-check COM provider
SpellCheckComponent 16 TSynSpellCheck component integration
DragDropIntegration 17 External/internal drop, move/copy, past EOL, multi-line, undo
MacroRecorder 30 State machine, recording, playback, events, serialization, properties

jareddavison and others added 30 commits February 25, 2026 16:20
Separate SynEdit into Shared/VCL/FMX layers to enable cross-platform
FMX support while maintaining full VCL backward compatibility via
Delphi unit scope resolution.

Structure:
- Source/ — shared platform-independent units (no prefix)
- Source/VCL/ — VCL-specific units (Vcl.* prefix)
- Source/FMX/ — FMX stub units (FMX.* prefix)
- Demos/VCL/ — existing demos moved here
- Demos/FMX/ — placeholder for FMX demos

Key changes:
- 66 highlighters: Graphics→System.UITypes, {$IFDEF MSWINDOWS} for
  Windows/Registry, removed Vcl.Controls dependencies
- Shared units made portable: SynEditTypes, SynEditHighlighter,
  SynEditTextBuffer, SynEditCodeFolding, SynUnicode, SynEditKeyCmds,
  SynEditMiscProcs with SYN_SHARED conditional for VCL exclusion
- VCL units renamed with Vcl.* prefix (36 files)
- FMX stub units created (11 files) for Phase 2 implementation
- New SynEditSharedDR package (shared runtime, requires rtl only)
- SynEditDR updated to require SynEditSharedDR
- New SynEditFMXDR/DD packages for FMX runtime/designtime
- New C++ Builder package stubs (SynEditSharedCR, FMX CR/CD)

All 5 Delphi packages compile: SynEditSharedDR → SynEditDR →
SynEditDD → SynEditFMXDR → SynEditFMXDD

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add DCC_UsePackage with Delphi DCP names (SynEditSharedDR, SynEditDR,
  SynEditFMXDR) so C++ Builder packages use pre-compiled Delphi packages
  instead of recompiling shared units from source
- Add Winapi/System.Win namespaces to Base DCC_Namespace for all packages
- Add Win64x platform configuration to SynEditCR and downstream packages
- Fix SynEditFMXCD: add vcl.bpi, fmx.bpi, SynEditSharedCR.bpi imports
  (designide is VCL-based, needs VCL import libraries)
- Add *.o to .gitignore for C++ object files

All 10 packages (5 Delphi + 5 C++ Builder) compile for Win32.
All 5 Delphi packages also compile for Win64 and Win64x.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Documents the shared/VCL/FMX architecture, unit scope resolution,
directory structure, package dependencies, build order, and
contributor guidelines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The class declaration had a TextWidthFunc parameter but the
implementation was parameterless. Align implementation with
declaration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
FMX.SynEditRenderer.pas: Canvas-based rendering with TTextLayout
  font metrics, token painting, line numbers, and TColor-to-
  TAlphaColor conversion.

FMX.SynEditScrollBars.pas: FMX TScrollBar integration replacing
  native Windows scrollbars.

FMX.SynEditUndo.pas: Full undo/redo system ported from VCL, hooks
  TSynEditStringList events directly instead of TSynEditPlugin.

FMX.SynEdit.pas: TCustomFMXSynEdit with syntax highlighting, keyboard
  input, selection, scrolling, clipboard, undo/redo, caret blinking,
  mouse handling, and file I/O.

FMX.SynEditTypes.pas: Added GUID to ISynEditScrollBars interface.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
First FMX demo application. Creates TFMXSynEdit programmatically
with a ComboBox to switch between Delphi, C++, Java, Python,
JavaScript, HTML, XML, CSS, SQL, JSON, C#, INI, and Batch
highlighters showing their sample source.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve Windows system colors (clHighlight, clHighlightText) via
GetSysColor API instead of returning TAlphaColors.Null. Suppress
token background when painting selected text so the selection
highlight shows through.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The FMX editor never populated the Ranges[] array in TSynEditStringList,
causing highlighters that track state across lines (XML, HTML, Delphi,
CSS, SQL, etc.) to receive garbage fRange values and recurse infinitely.

Add ScanRanges (full scan) and ScanFrom (incremental scan) methods ported
from the VCL editor, called on highlighter assignment, text loading, and
after each text-mutating command in ExecuteCommand.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a token partially overlapped the selection, the entire token was
painted with the selection foreground color (white), making the
non-selected portion invisible against the light background.

Split token rendering at selection boundaries so each part (before,
within, after selection) is painted with its correct colors. Applied
to both the highlighted and plain-text painting paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In Delphi, `and` binds tighter than `xor`, so the expression
`A xor B and C` was parsed as `A xor (B and C)` instead of the
intended `(A xor B) and C`. This caused a nil event handler to be
called when FOnModifiedChanged was unassigned, crashing at address 0.

Fixed in both FMX and VCL undo units by adding parentheses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Vcl.Graphics to SynEditHighlighter.pas conditional uses clause
  (provides StringToColor needed by VCL-only registry code)
- Fix EditApp demo relative paths for uHighlighterProcs.pas to account
  for demos being moved from Demos/ to Demos/VCL/
- Add build_vcl_demos.bat script that passes corrected search paths
  (Source, Source/VCL, Source/Highlighters) to all 12 VCL demos

All 12 VCL demos now compile successfully.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Configure colors for Delphi, C++, Java, Python, JavaScript, HTML, XML,
CSS, SQL, JSON, C#, INI, and Batch highlighters. Uses a consistent
palette: navy bold keywords, green italic comments, blue strings/numbers,
teal directives, maroon tags/keys where appropriate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tate

README: Replace outdated two-package description with current three-layer
architecture overview, all 10 packages, updated installation instructions,
demo listings, and build-from-source section. Add links to ARCHITECTURE.md
and What's new.md.

What's new: Add FMX Cross-Platform Editor section covering the three-layer
architecture, TCustomFMXSynEdit features, new packages, and FMX demo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add two new FMX demos: EditApp (single-document editor with menus, file
I/O, clipboard, undo/redo, auto highlighter detection) and FeaturesDemo
(feature showcase with options toggles, clipboard buttons, appearance
controls, and event log). Fix Tab/Shift+Tab in FMX SynEdit by overriding
DialogKey to intercept Tab before FMX uses it for focus navigation, and
add ecShiftTab handler for line unindent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the 47-line stub with a complete code completion component
featuring a TPopup-based dropdown with custom-painted item list,
keyboard navigation (Up/Down/Enter/Escape), type-ahead filtering,
configurable shortcut (default Ctrl+Space), and timer-based activation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New base class TSynFMXEditPlugin with virtual hooks for AfterPaint,
LinesInserted, LinesDeleted, and LinePut. Provides extensibility for
spell check, code analysis, and other editor add-ons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cross-platform design with ISynSpellCheckProvider interface and two
implementations: TSynWindowsSpellProvider (Windows COM ISpellChecker)
and TSynHunspellProvider (Hunspell .dic/.aff dictionaries). Includes
wavy underline rendering via plugin AfterPaint hook.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Five new units implementing syntax-highlighted printing:
- FMX.SynEditPrintTypes: shared types, enums, event definitions
- FMX.SynEditPrinterInfo: ISynPrinterInfo + FMX.Printer implementation
- FMX.SynEditPrintMargins: margin calculations (mm/inch/pixel)
- FMX.SynEditPrintHeaderFooter: header/footer with macro substitution
- FMX.SynEditPrint: ISynPrintProvider + TSynFMXEditPrint component

Uses abstract ISynPrintProvider interface for extensibility beyond
the default FMX.Printer-based implementation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Search dialog with match case, whole word, regex options and
direction selection. Replace dialog extends with replace text
field and Replace/Replace All buttons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Core editor integration for Phase 3 features:
- Code folding: row/line mapping, fold gutter painting with +/- icons,
  gutter click to toggle, fold commands (ecFoldAll, ecUnfoldAll, etc.),
  CollapseAll/UncollapseAll/CollapseNearest public methods
- Search/replace: SearchReplace method ported from VCL with configurable
  search engine (TSynEditSearchCustom), replace text events
- Plugin infrastructure: RegisterPlugin/UnregisterPlugin, AfterPaint hook
- Remove duplicate TSynEditSearchCustom from FMX.SynEditMiscClasses
  (now uses shared version from SynEditTypes.pas)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 7 new units to SynEditFMXDR package: FMX.SynEditPlugins,
FMX.SynSpellCheck, FMX.SynEditPrintTypes, FMX.SynEditPrinterInfo,
FMX.SynEditPrintMargins, FMX.SynEditPrintHeaderFooter, FMX.SynEditPrint.

Register TSynFMXSpellCheck and TSynFMXEditPrint components in the
SynEdit FMX component palette.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Exposes the regex checkbox state so callers can swap between
TSynEditSearch and TSynEditRegexSearch engines accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Five new scrollbox sections: Code Folding (checkbox, fold/unfold
buttons), Search/Replace (find/replace buttons), Completion (activate
button), Spell Check (checkbox, check file button, status label),
and Printing (print button).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Initialize search engines, completion proposal with Delphi keywords,
spell check with Windows provider, and print component in FormCreate.
Add event handlers for code folding toggle/collapse/expand, search and
replace with regex engine swapping, completion activation, spell check
with status reporting, and printing.  Register dialog units in the
project file.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The forward declaration was never resolved in the same type section,
causing E2086. Move the full class definition and implementation into
FMX.SynEdit.pas, reduce FMX.SynEditPlugins to a re-export alias,
and remove the unused nEOLCount variable from SearchReplace.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve unresolved TCustomFMXSynEdit forward declaration by moving
FMX.SynEdit to the interface uses clause. Replace VCL-only ShortCut
and ShortCutToKey functions with direct bitmask operations. Wire
EditorKeyDown handler to the editor OnKeyDown event and remove unused
GetCurrentString wrapper.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace nonexistent TPrinterService with FMX.Printer functions, use
WinAPI CreateDC for printer device caps instead of FMX Canvas.Handle,
fix read-only ActivePrinter.Title assignment, add missing System.Types
and Winapi.Windows imports to margins unit, add System.Math.Vectors
for TMatrix, implement SetSynEdit to extract editor properties, and
remove unused AlphaToken variable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Convert editor-local coordinates to screen coordinates via
LocalToScreen before setting the popup PlacementRectangle (which
uses TPlacement.Absolute). Expose LineHeight as a public property
on TCustomFMXSynEdit for accurate vertical offset calculation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Options set was missing scoCompleteWithEnter and
scoCompleteWithTab, preventing keyboard-based item selection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Protect against access violations when FForm is freed before its
parent references are cleared.  Use FreeAndNil, check FForm <> nil
before accessing IsOpen/Parent, and handle opRemove for the form
component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
jareddavison and others added 16 commits March 1, 2026 04:59
Implements a complete bookmark system for the FMX editor:
- TSynFMXEditMark/TSynFMXEditMarkList classes in FMX.SynEditMiscClasses
- 10 bookmark slots (0-9) with Set/Clear/Goto/GetBookmark APIs
- Toggle behavior: Ctrl+Shift+N on same line clears, different line moves
- Blue circle indicators with numbers rendered in the gutter
- Ctrl+0-9 and Ctrl+Shift+0-9 key bindings wired in KeyDown
- OnPlaceBookmark/OnClearBookmark events
- ClearAll clears all bookmarks
- 15 new DUnitX tests (334 total, all passing)

Note: Ctrl+Shift+0 may be intercepted by Windows for input language
switching. Bookmarks 1-9 are reliable on all configurations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hardcoded gutter rendering with TSynFMXGutter/TSynFMXGutterBand
classes that support ordered bands (line numbers, marks, fold, margin),
auto-width calculation, paint dispatch, and click handling. Default
layout matches the previous hardcoded visual output. Includes 15 tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Clicking a bookmark indicator in the marks gutter band now clears the
bookmark on that line, in both the FMX and VCL editors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move platform-independent selection logic (TSynSelStorage, TSynSelectionsBase)
into new shared unit SynEditSelections.pas. The abstract base class provides
sorted selection management, column selection, merge, line-change adjustment,
and undo storage — with 10 abstract methods for editor coupling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace ~560 lines of selection logic in Vcl.SynEditMiscClasses.pas with a thin
subclass of TSynSelectionsBase. The 10 override methods delegate to VCL editor
APIs (InvalidateSelection, StateFlags, BufferToDisplayPos, etc.). Public API
contract is preserved — no VCL consumer code changes required.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add TSynFMXSelections subclass in FMX.SynEditMiscClasses.pas
- Replace 5 caret/selection fields with FSelection record + FSelections object
- Add CommandProcessor with multi-caret dispatch via SynCommandsInfo
- Add column selection (Alt+Shift+Arrows), select matching (Ctrl+Shift+W),
  carets at line ends (Alt+End), cancel selections (Escape)
- Add Alt+Click to add/toggle carets, Alt+Shift+Drag for column selection
- Paint multi-caret selection backgrounds via PartSelectionsForRow with
  line-boundary clipping and FillWholeLines support
- Extend undo system to store/restore multi-selection state
- Forward line-change notifications to FSelections for caret adjustment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Test fixture covers: single-caret backward compat, add/toggle carets,
column selection up/down, multi-caret char insert/delete/backspace,
cancel selections, merge overlapping, select all matching text,
carets at line ends, multi-caret undo/redo, and PartSelectionsForRow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add MultiCaret fixture (17 tests) to test tables, update test counts,
add multi-caret editing to FMX feature list, and update Multi-caret.md
to document the shared TSynSelectionsBase architecture.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Eliminates duplicate TSynSelectedColor implementations in VCL and FMX
MiscClasses units. Both now use a type alias to the shared class.
FMX editor sets its platform-specific defaults after construction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extracts duplicated ColumnSelectionStart logic and multi-caret command
iteration into shared methods on TSynSelectionsBase. Both VCL and FMX
editors now delegate to these shared implementations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Creates TSynEditUndoBase with all shared undo/redo logic (undo list,
group undo, change tracking, BeginBlock/EndBlock, BufferSaved). VCL
and FMX undo units now inherit from TSynEditUndoBase, keeping only
platform-specific caret/selection items and event wiring.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update references in README.md and What's new.md to point to the
new location.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Delphi's unit scope resolution gives exact name matches priority over
dotted-prefix matches.  A bare 'SynEditKeyConst' in a uses clause
therefore shadows 'Vcl.SynEditKeyConst' and 'FMX.SynEditKeyConst',
making it impossible for VCL/FMX code to reliably reference its own
platform-specific version of the unit.

Renaming the shared unit to SynEditKeyConstShared eliminates the
ambiguity.  The Vcl/FMX wrappers now re-export from the shared unit
instead of independently declaring the same constants against
Windows VK_* / FMX vk* values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Same Delphi scope-resolution issue as SynEditKeyConst: a bare
'SynUnicode' in a uses clause shadows 'Vcl.SynUnicode' and
'FMX.SynUnicode', preventing VCL/FMX code from reaching its own
clipboard-specific version of the unit.

The shared unit is renamed to SynUnicodeShared.  Vcl.SynUnicode and
FMX.SynUnicode now re-export the shared encoding types, constants,
and helper functions alongside their platform-specific clipboard
routines, so consumer code can use a single import.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The third and final scope-resolution collision: a bare 'SynEditTypes'
in a uses clause matches the shared SynEditTypes.pas (exact match) and
shadows 'Vcl.SynEditTypes' and 'FMX.SynEditTypes'.

Renaming the shared side would require updating 110+ files and
re-aliasing Delphi enum types (which creates incompatible types under
{$SCOPEDENUMS ON}).  The VCL/FMX side is renamed instead — both units
contain only ISynEditScrollBars, so 'ScrollTypes' is a more accurate
name and has zero impact on external consumers who never referenced
these internal interfaces directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jimmckeeth
Copy link
Copy Markdown
Contributor

The Architecture link in the description didn't work, so here is a fixed link for anyone else who wants to see it.

I'm really excited to see this. It is something I've wanted for a while, and a quick glance looks promising, especially the fact you made it compatible with the existing SynEdit so well. I'm going to give this a closer look.

jareddavison and others added 2 commits March 3, 2026 05:31
GitHub is case-sensitive: the file is tracked as "What's New.md"
but the link used lowercase "new", resulting in a 404.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update unit counts: 40 VCL units, 19 FMX units
- Document renamed units: SynUnicodeShared, SynEditKeyConstShared,
  SynEditScrollTypes, SynEditUndoShared
- Add new shared units: SynEditSelections, SynEditUndoShared
- Add missing VCL units to directory listing
- Document shared suffix naming convention
- Add multi-caret editing and word wrap to README feature lists

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jareddavison
Copy link
Copy Markdown
Author

jareddavison commented Mar 2, 2026

Thanks Jim. I've refreshed the copy of What's New at the top of this page. It was stale. I had realised later that there was a doc folder and had moved the new ARCHITECTURE.md there. I think the What's New in the repo might have been updated. I've copied and pasted it to above.

jareddavison and others added 10 commits March 4, 2026 05:54
Extract cross-platform drop logic into SynEditDragDropShared:
- TSynDropAction, TSynDropInfo records
- TSynDragDropHelper with ComputeDropInfo, AdjustDropPos, IsDropCopy

Extract Windows OLE building blocks into SynEditDragDropWin:
- TSynDragSource (IDropSource), TSynEnumFormatEtc (IEnumFORMATETC)
- MakeGlobal, HasFormat, GetInternalClipText helpers
- GenerateHTMLFragment for CF_HTML clipboard format
- SynEditClipboardFormat/HTMLClipboardFormat vars + OLE init

Both units added to SynEditSharedDR package.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Vcl.SynEditDragDrop: Remove TSynDragSource, StandardEffect, drop
effect constants — re-export from SynEditDragDropWin.

Vcl.SynEditDataObject: Remove TSynEnumFormatEtc, MakeGlobal,
HasFormat, GetInternalClipText, clipboard format vars, OLE init —
re-export from SynEditDragDropWin. Keep TSynEditDataObject (VCL-specific).

Vcl.SynEdit.OleDrop: Replace inline position logic with
TSynDragDropHelper.ComputeDropInfo/AdjustDropPos from shared unit.

All re-exports preserve the existing public API contract.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
FMX.SynEditDragDrop (new): Platform abstraction for drag-drop.
- ISynDragDropPlatform interface with Windows OLE implementation
- TSynFMXTextDataObject: CF_UNICODETEXT + CF_HTML via shared helpers
- TSynFixedDropTarget: Fixes FMX TWinDropTarget.Drop bug (missing dwEffect)
- RegisterOleDropTarget/UnregisterOleDropTarget for form-level registration

FMX.SynEdit: Full drag-drop integration.
- MouseDown/MouseMove/MouseUp: Detect drag-ready state, threshold, click-on-selection
- DoDragDropOperation: OLE drag source via platform abstraction
- DragOver: Visual caret feedback, auto-scroll near edges
- DragDrop → DropTextAtPos: Core drop logic (internal move/copy, external drop)
- Internal move detection via FIsDragSource flag (OLE drops lack Data.Source)
- SelectAll/ClearSelection: Fix FSelections sync (Ctrl+A text visibility)
- SetSelectedTextPrimitive: Space padding for drops past end of line
- EnableDragHighlight := False to suppress FMX blue outline

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TSynDragDropHelperTests (10 tests): ComputeDropInfo, AdjustDropPos,
IsDropCopy — validates shared drop position logic.

TTestFMXDragDropIntegration (17 tests): End-to-end editor tests via
protected DropTextAtPos method. Covers external drops (single/multi-line,
past EOL, end of document, read-only, empty), internal moves
(same/different line, multi-line selection, source deletion, rejection
inside selection), internal copies, selection state, and undo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update DCC_UnitSearchPath from ..\..\Source to ..\..\..\Source
across all configurations to match the Demos\VCL\ subdirectory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
README: Add OLE drag-drop to FMX feature list, update test count to 393/31.
What's New: Add drag-drop bullet point, DragDropHelper/Integration fixtures.
Architecture: Add SynEditDragDropShared, SynEditDragDropWin, FMX.SynEditDragDrop
to directory listing; update FMX drag-drop row in comparison table; add
drag-drop shared units to naming convention table; update test count.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract DropTextAtPos as protected function from OleDrop for testability.
Add TTestVCLDragDropIntegration fixture covering external/internal drop,
move/copy, past EOL, multi-line, read-only rejection, undo, and selection
state. Update docs to reflect 64 VCL tests across 4 fixtures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document FMX vs VCL feature gaps: missing components (accessibility,
macro recorder, exporters, auto-correct, DB edit, URI opener, dialogs),
properties (TextHint, caret styles, special chars, indicators, bracket
highlight), events (OnGutterClick, OnPaint, OnDropFiles, OnScroll,
OnZoom), DirectWrite rendering, and drag-drop platform support.
Update VCL test count in README (47 → 64).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
FSelection is a record (value type) used as a working copy of the active
selection. Methods like MoveCaretAndSelection and InsertCharAtCursor update
FSelection but never write it back to FSelections, so PaintCaret and
PartSelectionsForRow read stale data. Sync FSelection back to FSelections
at the top of Paint to ensure correct rendering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract macro event types (TSynBasicEvent, TSynCharEvent, TSynStringEvent,
TSynPositionEvent, TSynDataEvent) into SynMacroRecorderShared.pas with a
new PlaybackTo callback pattern replacing the VCL-specific Playback method.

Refactor Vcl.SynMacroRecorder to delegate to shared types and re-export
them via type aliases, preserving the existing public API.

Create FMX.SynMacroRecorder with TFMXSynMacroRecorder component using
the shared event types. Add hooked command handler support and Data
parameter to FMX CommandProcessor for macro playback integration.

Add macro recording UI to FMX FeaturesDemo and VCL SimpleIDEDemo.

Tests: 30 VCL macro tests, 14 shared event tests, 5 FMX hooked command
handler tests, 16 FMX macro recorder tests (428 FMX + 95 VCL all pass).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants