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

API — ICoreEssentials/UI/Backends/Web/Text

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

ICoreWebSyntaxHighlighter.h#

ICoreEssentials/UI/Backends/Web/Text/ICoreWebSyntaxHighlighter.h

ICoreWebSyntaxHighlighter#

ICoreWebSyntaxHighlighter.h:30 · class · pImpl · 18 declaration(s)

The web text tier's syntax-highlighting engine (web backend, WB5.2): the per-paragraph callback, the block-state machine that lets a construct span paragraphs, and the run formatting a highlighter ...

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

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

    // A document from icoreWebMakeTextDocument(); nullptr detaches, and
    // detaching removes this engine's overlay from the document it leaves.
    void setDocument(void* document);
    [[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 changed forces the next one to be
    // re-read, which is what carries a block comment down the file.
    void rehighlightBlock(int blockNumber);

    // Paragraphs in the attached document; an empty document still has one.
    [[nodiscard]] int blockCount() const;

    // ⚠ SUBSCRIBED, NOT DRIVEN, like the GTK engine and unlike the WinUI one
    // (TOM has no change notification). An edit re-highlights the paragraphs it
    // touched and then cascades while their end states change -- Qt's
    // QSyntaxHighlighter::_q_reformatBlocks shape. Painting writes only the
    // overlay, which emits no change, so a pass cannot re-enter itself.
    //
    // The public seam one layer up publishes rehighlight() and nothing
    // narrower, so without this an editor wanting live highlighting could only
    // re-run the whole file per keystroke. Off for a batch pass or a test.
    void setAutoRehighlight(bool on);
    [[nodiscard]] bool autoRehighlight() const;

    // =========================
    // THE RUN SURFACE -- public, not protected: these are what a highlighter
    // CALLS, and the header surface rule bans protected non-virtual helpers.
    // =========================

    // Paint a run of the paragraph being highlighted; `start` is relative to
    // it. Clipped to the paragraph, never paints the separator, and REPLACES
    // what this engine had there -- it does not merge. Outside a pass, a no-op.
    void setFormat(int start, int count, const ICoreWebTextRunFormat& format);

    // What this engine has painted at `position` of the current paragraph,
    // including this pass's own runs.
    //
    // ⚠ PASS-SCOPED: outside a highlight pass it answers an empty format,
    // because the Qt seat does -- QSyntaxHighlighter::format() reads the block
    // being highlighted and there is none once the pass returns. The overlay
    // could answer at any time; answering would let a caller write code that
    // works here and silently reads defaults elsewhere.
    [[nodiscard]] ICoreWebTextRunFormat formatAt(int position) const;

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

    // The current paragraph's state: -1 until set, and a state set in an
    // earlier pass survives into this one.
    [[nodiscard]] int currentBlockState() const;
    void setCurrentBlockState(int state);

    // The paragraph being highlighted, or -1 outside a pass.
    [[nodiscard]] int currentBlockNumber() const;

protected:
    // One paragraph WITHOUT its separator -- what QTextBlock::text() hands over.
    virtual void highlightBlock(const std::u16string& text) = 0;

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

ICoreWebTextDocument.h#

ICoreEssentials/UI/Backends/Web/Text/ICoreWebTextDocument.h

The web text tier's document model and its in-zone seam (web backend, WB5.1). The peer of ../../Gtk4/Text/ICoreGtk4TextDocument.h, and deliberately the same vocabulary.

⚠⚠ THIS BACKEND HAS NO TOOLKIT BUFFER, SO THE MODEL IS WRITTEN HERE. The three desktop seats each sit on a document their toolkit already owns -- a QTextDocument, an NSTextStorage, a GtkTextBuffer, a TOM document. A browser has none a canvas-painted editor can use: a DOM <textarea> is a VIEW with a string in it, and WB2.3 uses one only as the IME/keyboard seat. So the document is a plain C++ object, owned by whoever made it, and every other file in this directory is a view over it.

⚠ IT NAMES NO BROWSER API AND NEEDS NONE. Nothing in this directory includes <emscripten/...>, so the whole tier compiles and runs on a host compiler as

ICoreWebTextChange#

ICoreWebTextDocument.h:152 · struct · 0 declaration(s)

What one edit did, in BLOCKS.

struct ICoreWebTextChange {
public:
    int position = 0;
    int charsRemoved = 0;
    int charsAdded = 0;
    int firstBlock = 0;
    int oldBlockCount = 1;
    int newBlockCount = 1;
};
};

ICoreWebTextRunFormat#

ICoreWebTextDocument.h:180 · struct · 3 declaration(s)

One run's worth of formatting: the vocabulary ICoreTextCharFormat carries.

struct ICoreWebTextRunFormat {
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;
    bool hasUnderlineColor = false;
    int underlineRed = 0;
    int underlineGreen = 0;
    int underlineBlue = 0;
    int underlineAlpha = 255;

    // Asks for nothing. Painting one CLEARS the run.
    [[nodiscard]] bool isEmpty() const;
    [[nodiscard]] bool operator==(const ICoreWebTextRunFormat& other) const;
    [[nodiscard]] bool operator!=(const ICoreWebTextRunFormat& other) const;
};
};

ICoreWebTextRun#

ICoreWebTextDocument.h:204 · struct · 0 declaration(s)

A painted span of one block: start, start + length), block-relative.

struct ICoreWebTextRun {
public:
    int start = 0;
    int length = 0;
    ICoreWebTextRunFormat format;
};
};

ICoreWebTextView.h#

[ICoreEssentials/UI/Backends/Web/Text/ICoreWebTextView.h

The web backend's text VIEW (WB5.3): what GtkTextView, NSTextView and the WinUI painted engine are to their seats -- layout, wrapping, hit-testing, caret and selection, keyboard editing, undo and scrolling -- over the WB5.1 document model (ICoreWebTextDocument.h).

⚠⚠ WHY IT IS PAINTED AND NOT A <textarea>. The script editor paints syntax runs (the WB5.2 overlay), a gutter, folds, decorations and a completion popup over its text; a <textarea> can show none of that -- one colour, one font, no per-run anything. So the view is painted on the canvas from the model, and a hidden DOM element is only ever the keyboard/IME sink (the CodeMirror 6 / Monaco shape). This class is the painted half; it does not paint either -- the seats walk visibleLines() with the Canvas2D painter.

⚠ IT NAMES NO BROWSER, NO NODE AND NO PAINTER. Text is measured through a

ICoreWebTextLine#

ICoreWebTextView.h:36 · struct · 1 declaration(s)

One visual line: a block's run of text as laid out on one row.

struct ICoreWebTextLine {
public:
    int block = 0;          // document block number
    int start = 0;          // block-relative unit where the line starts
    int length = 0;         // units on this line, without the separator
    double top = 0.0;       // content-space y of the row's top
    double height = 0.0;    // the row's height (line spacing x the block's line height)
    double baseline = 0.0;  // content-space y of the text baseline
    std::vector<double> xs; // x of each unit boundary on the line, size length + 1
};
};

ICoreWebTextKeyOutcome#

ICoreWebTextView.h:48 · struct · 1 declaration(s)

What a key did, for the seat to finish: the clipboard is the seat's, so the engine asks rather than touching it.

struct ICoreWebTextKeyOutcome {
public:
    bool consumed = false;
    bool writeClipboard = false;     // copy/cut: put clipboardText on the clipboard
    bool readClipboard = false;      // paste: the seat calls insertText(clipboard)
    std::u16string clipboardText;
};
};

ICoreWebTextView#

ICoreWebTextView.h:55 · class · pImpl · 50 declaration(s)

class ICoreWebTextView {
public:
    using Measure = std::function<double(const std::u16string& text)>;

    ICoreWebTextView();
    ~ICoreWebTextView();
    ICoreWebTextView(const ICoreWebTextView&) = delete;
    ICoreWebTextView& operator=(const ICoreWebTextView&) = delete;

    // ---- the model -------------------------------------------------------------

    // The view makes and OWNS its document (one reference), as a GtkTextView
    // owns its buffer; documentHandle() hands out borrowed views of it.
    [[nodiscard]] void* document() const;

    void setPlainText(const std::u16string& text);   // resets undo, caret to 0
    [[nodiscard]] std::u16string plainText() const;

    // ---- metrics and geometry ---------------------------------------------------

    // `measure` answers the advance of a run with no tabs in it. `ascent` and
    // `lineSpacing` are the font's. Changing any of them relays out everything.
    void setMetrics(Measure measure, double ascent, double lineSpacing);
    void setTabStopDistance(double pixels);           // 0 = 8 spaces' worth
    void setWrap(bool wrapAtViewportWidth);
    void setDocumentMargin(double margin);             // around the text, all four sides
    void setViewportSize(double width, double height);
    [[nodiscard]] double viewportWidth() const;
    [[nodiscard]] double viewportHeight() const;

    // ⚠ Block visibility (folding) and a block's line height are document
    // properties that change WITHOUT a change notice -- they are not text. The
    // seat that changes one calls this, or the view keeps the old layout.
    void invalidateLayout();

    [[nodiscard]] double contentHeight() const;        // including both margins
    [[nodiscard]] double contentWidth() const;         // the widest line, with margins

    // The caret rectangle at a position (content space): the unit's left edge,
    // one line tall, zero wide. A position at a wrap point belongs to the line
    // it STARTS, as on every desktop toolkit.
    [[nodiscard]] ICoreRect rectForPosition(int position) const;
    // The position nearest a content-space point (above the text is 0, below
    // is the end, past a line's end is the line's end).
    [[nodiscard]] int positionAt(double x, double y) const;
    // A block's rows, content space; empty for a hidden or invalid block.
    [[nodiscard]] ICoreRect blockBounds(int block) const;

    // The visual lines that intersect the viewport, in order -- what a seat
    // paints. Content space: subtract the scroll offsets to paint.
    [[nodiscard]] std::vector<ICoreWebTextLine> visibleLines() const;

    // ---- scrolling --------------------------------------------------------------

    [[nodiscard]] double scrollY() const;
    [[nodiscard]] double scrollX() const;
    void setScrollY(double y);                          // clamped to the content
    void setScrollX(double x);
    enum class ScrollHint { Visible, Top, Center };
    void scrollToBlock(int block, ScrollHint hint);
    void ensureCaretVisible();

    // ---- caret and selection ----------------------------------------------------

    [[nodiscard]] int position() const;
    [[nodiscard]] int anchor() const;
    [[nodiscard]] bool hasSelection() const;
    [[nodiscard]] int selectionStart() const;
    [[nodiscard]] int selectionEnd() const;
    [[nodiscard]] std::u16string selectedText() const;
    // Clamped. `reveal` scrolls the caret into view; the widget seats pass
    // false, because ICoreRichTextEdit::setTextCursor/setSelection do not
    // scroll on GTK4 or AppKit -- ensureCursorVisible() is its own call, and
    // the Script IDE's goToLine() centres a line only if it is off screen
    // AFTER placing the caret (scriptide/go_to_line_centres_a_line_off_screen).
    void setSelection(int anchor, int position, bool reveal = true);
    void setCaret(int position);

    // ---- editing ----------------------------------------------------------------

    void setReadOnly(bool readOnly);
    [[nodiscard]] bool isReadOnly() const;

    // Replace the selection with `text` (typing, paste, IME commit). One undo
    // step, except that consecutive single typed characters with no caret move
    // in between coalesce into one, as every desktop editor does.
    void insertText(const std::u16string& text);

    // An editing/navigation key. `typed` is the character(s) a printable key
    // produced (empty for a non-printing key). Chords are Control on Windows
    // and Linux, Meta (Cmd) on macOS -- both are accepted, as the portable text
    // item core does, because a page cannot trust what platform it is on.
    ICoreWebTextKeyOutcome key(int icoreKey, unsigned int modifiers, const std::u16string& typed);

    void undo();
    void redo();
    [[nodiscard]] bool isUndoAvailable() const;
    [[nodiscard]] bool isRedoAvailable() const;

    // Keep only the last `blocks` blocks (0 = unlimited), trimming from the top
    // after an append -- a console's scrollback.
    void setMaximumBlockCount(int blocks);
    // Append at the end of the document without moving the caret or recording
    // undo (output, not typing); returns the position the text started at.
    int append(const std::u16string& text);

    // ---- pointer -----------------------------------------------------------------

    // Viewport-space coordinates. clickCount 2 selects a word, 3 a block.
    void pointerPressed(double x, double y, int clickCount, bool extend);
    void pointerDragged(double x, double y);
    void pointerReleased();
    // Wheel: pixels to scroll (positive = down/right). Returns whether it moved.
    bool scrolled(double dx, double dy);

    // ---- notifications (all on the main thread, after the state changed) --------

    void setContentsChangedHook(std::function<void()> hook);
    void setBlockCountChangedHook(std::function<void(int)> hook);
    void setCursorChangedHook(std::function<void()> hook);
    void setScrollChangedHook(std::function<void()> hook);
    void setUndoAvailableHook(std::function<void(bool)> hook);
    void setRedoAvailableHook(std::function<void(bool)> hook);
    // Anything the seat must repaint for: text, caret, selection, scroll, layout.
    void setRepaintHook(std::function<void()> hook);

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