Generated reference › API — ICoreEssentials/UI/Backends/WinUI/Text
kind: generated#api#icoreessentials-ui-backends-winui-text

API — ICoreEssentials/UI/Backends/WinUI/Text

The public contract of 3 header(s) under ICoreEssentials/UI/Backends/WinUI/Text — 3 class/struct definition(s), 21 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.

ICoreWinUISyntaxHighlighter.h#

ICoreEssentials/UI/Backends/WinUI/Text/ICoreWinUISyntaxHighlighter.h

The WinUI text tier's syntax-highlighting engine (the planning row is named in the .cpp, not here): the per-paragraph callback, the block-state machine that lets a construct span paragraphs, and the run formatting a highlighter paints with. The peer of Backends/AppKit/Text/ICoreAppKitSyntaxHighlighter.h, and deliberately the same surface -- the seam one layer up is identical on the two backends, so the halves it joins should be too.

⚠ IT SPEAKS PLAIN NUMBERS AND std::wstring, NOT THE ICore VALUE CLASSES, for the reason the AppKit engine states: ICoreTextCharFormat and ICoreString reach a toolkit in their headers today (W9.1), so an engine written against them could not be compiled -- let alone tested -- without the very thing this backend exists to replace. The translation happens ONE LAYER UP, in ICoreSyntaxHighlighter.cpp, where those types are already unwrapped.

ICoreWinUITextRunFormat#

ICoreWinUISyntaxHighlighter.h:39 · struct · 1 declaration(s)

One run's worth of formatting, in the four properties TOM can carry plus the one it cannot (see below).

struct ICoreWinUITextRunFormat {
public:
    bool hasForeground = false;
    int foregroundRed = 0;
    int foregroundGreen = 0;
    int foregroundBlue = 0;
    int foregroundAlpha = 255;

    bool bold = false;
    bool italic = false;

    bool underline = false;

    // ⚠ A SEPARATE FLAG FOR THE UNDERLINE COLOUR, WHICH THE APPKIT RECORD DOES
    // NOT HAVE, AND THE DIFFERENCE IS DELIBERATE. `setUnderlineStyle(Wave)`
    // without `setUnderlineColor(...)` is a legal thing for a highlighter to
    // ask for, and a record that could not say so would have to invent a colour
    // -- which would then come back out of formatAt() and make a format the
    // caller never wrote compare unequal to the one it did.
    bool hasUnderlineColor = false;
    int underlineRed = 0;
    int underlineGreen = 0;
    int underlineBlue = 0;
    int underlineAlpha = 255;

    // A format that asks for nothing: no colour, no weight, no slant, no
    // squiggle. Painting one is not an error -- it resets the run.
    [[nodiscard]] bool isEmpty() const;
};
};

ICoreWinUISyntaxHighlighter#

ICoreWinUISyntaxHighlighter.h:68 · class · pImpl · 16 declaration(s)

class ICoreWinUISyntaxHighlighter {
public:
    ICoreWinUISyntaxHighlighter();
    virtual ~ICoreWinUISyntaxHighlighter();

    ICoreWinUISyntaxHighlighter(const ICoreWinUISyntaxHighlighter&) = delete;
    ICoreWinUISyntaxHighlighter& operator=(const ICoreWinUISyntaxHighlighter&) = delete;

    // `textDocument` is an ITextDocument* -- the document model a WinUI 3
    // RichEditBox sits on and the one a Win32 RICHEDIT50W hands out of
    // EM_GETOLEINTERFACE. Attaching AddRef's it; passing nullptr, or destroying
    // the highlighter, releases it.
    //
    // ⚠ THE ENGINE IS DRIVEN, NOT SUBSCRIBED. Qt's seat is called by the
    // toolkit whenever the document changes; TOM has no such callback, so a
    // pass happens when rehighlight() or rehighlightBlock() is called and at no
    // other time. The editor (W5.3) is what will call them on an edit.
    void setDocument(void* textDocument);
    [[nodiscard]] void* document() const;

    // Reapply the highlighting to every paragraph.
    void rehighlight();

    // Reapply it to one paragraph, and to as many after it as the block state
    // requires -- a paragraph whose end state changes forces the next one to be
    // re-read, which is what lets a comment opened on one line reach the lines
    // below it.
    void rehighlightBlock(int blockNumber);

    // Paragraphs in the attached document. An empty document still has one:
    // a TOM story is never shorter than its final paragraph mark.
    [[nodiscard]] int blockCount() const;

    // =========================
    // THE RUN SURFACE
    // =========================
    //
    // ⚠ PUBLIC, NOT PROTECTED, AND THAT IS DELIBERATE -- the same sentence the
    // AppKit engine and the component above both carry. These are what a
    // highlighter CALLS while it works, not what it overrides, and the header
    // surface rule bans protected non-virtual helpers precisely because a thing
    // called from a subclass is public API written down as an inheritance
    // detail.

    // Paint a run of the paragraph being highlighted. `start` is relative to
    // that paragraph, not to the document; a run reaching past the paragraph's
    // last visible character is clipped to it, and the paragraph mark is never
    // painted.
    //
    // ⚠ A LATER CALL REPLACES AN EARLIER ONE over the same characters. TOM's
    // own writes MERGE -- setting italic on a run leaves its colour alone, which
    // the W5.1 spike measured -- so this seat writes every modelled property on
    // every call rather than only the ones that were set. Replace is what the
    // Qt seat was measured to do and what the conformance suite pins; a merging
    // setFormat would leave the previous pass's colour under a comment.
    void setFormat(int start, int count, const ICoreWinUITextRunFormat& format);

    // What the run at `position` -- again relative to the current paragraph --
    // is painted with, including whatever this pass has already applied.
    //
    // ⚠ PASS-SCOPED, AND THAT IS A CONTRACT RATHER THAN A LIMITATION.
    // Outside a highlight pass this answers an empty format, because
    // the Qt seat does: QSyntaxHighlighter::format() reads the block being
    // highlighted right now and there is no such block once rehighlight() has
    // returned. TOM would happily answer at any time -- an ITextRange does not
    // care whether a pass is running -- and answering would let a caller write
    // code that works here and silently returns defaults on Qt.
    [[nodiscard]] ICoreWinUITextRunFormat formatAt(int position) const;

    // The end state of the paragraph before this one, or -1 for the first
    // paragraph and for one whose predecessor never set a state.
    [[nodiscard]] int previousBlockState() const;

    // The state of the paragraph being highlighted. -1 until something sets it;
    // a state set in a previous pass survives into this one.
    [[nodiscard]] int currentBlockState() const;
    void setCurrentBlockState(int state);

    // Which paragraph is being highlighted, counting from zero. -1 outside a
    // pass.
    [[nodiscard]] int currentBlockNumber() const;

protected:
    // Implemented by the highlighter. `text` is one paragraph WITHOUT the
    // paragraph mark that ends it -- every TOM paragraph carries one, the last
    // one included (measured by the W5.1 spike), so this strips a fixed trailing character
    // rather than special-casing the final block.
    virtual void highlightBlock(const std::wstring& text) = 0;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreWinUITextDocument.h#

ICoreEssentials/UI/Backends/WinUI/Text/ICoreWinUITextDocument.h

The WinUI text tier's shared vocabulary and its in-zone seam. The peer of Backends/AppKit/Text/ICoreAppKitTextDocument.h. (The planning row is named in the .cpp, not here.)

NO tom.h AND NO windows.h IN THIS HEADER -- the document is passed as an opaque void* that the .cpp casts to ITextDocument*, so a verify suite can include this without the Text Object Model. Same rule as the event map, the paint state and this zone's other seams.

⚠ THE DOCUMENT IS AN ITextDocument, WHICH IS THE MODEL AND NOT A VIEW -- and on Windows that sentence needs one qualification the AppKit peer does not. An NSTextStorage can be built out of nothing; a TOM document cannot, because the implementation of TOM lives inside a RichEdit control. So the factory below creates an off-screen RICHEDIT50W and hands back its document. Nothing

Declares no class of its own — see the file.

ICoreWinUITom.h#

ICoreEssentials/UI/Backends/WinUI/Text/ICoreWinUITom.h

The Text Object Model plumbing this zone's text seat is built from, in one place because two .cpp files need it. (The planning row is named in the .cpp files, not here: gen_api.py lifts HEADER comments onto a public API page, where a board filename trips the docs guard's D15 audience-leak row -- the Qt char-format seat carries the same note for the same reason.)

⚠⚠ THE TOM INTERFACE IDs ARE HAND-DEFINED, AND THAT IS A FINDING RATHER THAN BOILERPLATE (W5.1 §13.6 item 5). MinGW's tom.h DECLARES them -- EXTERN_C const IID IID_ITextDocument -- and libuuid.a defines NONE of them, so a file that names one compiles cleanly and fails at LINK time with an undefined reference. MSVC's uuid.lib does define them, so the gap is MinGW-only; defining our own constants costs nothing on either toolchain and is why this seat builds with both.

Ptr#

ICoreWinUITom.h:41 · class · 4 declaration(s)

class Ptr {
public:
    Ptr() = default;
    Ptr(const Ptr&) = delete;
    Ptr& operator=(const Ptr&) = delete;
    ~Ptr() { reset(); }

    T** put() { reset(); return &m_p; }
    T* get() const { return m_p; }
    T* operator->() const { return m_p; }
    explicit operator bool() const { return m_p != nullptr; }

    void reset(T* p = nullptr) {
        if (m_p) m_p->Release();
        m_p = p;
    }

};