Commit Graph
940 Commits
Author SHA1 Message Date
MarekSpodBiedryandBrandon Thomas 4495e2be53 Use the Default Paragraph Style font when importing ODT (#2804) (#2823)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:46:32 -04:00
833f5b64d9 Keep explicit text:s spaces at paragraph ends on ODT import (#2641)
Found while testing crates/formats/src/odt.rs:1480 (finish_para calls p.trim()); crates/formats/src/model.rs:188 (Para::trim)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:46:15 -04:00
866b48ac55 Recipient list: find box and merged-only view (#1576) (#2621)
* #1576: Recipient list search and filtered view

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* #1576: drive the recipient grid through egui_kittest

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* #1576: recipient search treats final sigma as sigma

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* #1576: removing a row lets go of the focused cell

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:45:59 -04:00
6e30349bbb #1327: protection checks cover tables, Paste Formatting and recipient refresh (#2618)
* #1327: protection checks cover tables, Paste Formatting, template update and recipient refresh

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* #1327: record any content below the protection walk's depth limit

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* #1327: formatting-only protection also refuses table properties and row height

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:45:40 -04:00
8c812bf1d6 #1230: Insert Caption on pictures and shapes; Different First Page in Page Setup (#2615)
* #1230: Insert Caption on pictures and shapes; Page Setup header and footer options

- Right-clicking a picture, shape, text box or chart offers Insert Caption…, as in Word.
- references.caption with a picture or shape selected puts the caption next to the
  paragraph holding it, in the same cell or text box (it used to go after the whole table).
- The Caption dialog proposes Figure for a picture selected in a table, not Table.
- Page Setup: Headers and footers check boxes (Different Odd & Even Pages, Different First
  Page), applied on OK only if changed, in one undo step; a title page can go unnumbered.
- Tests: engine caption_for_an_object_in_a_cell_stays_in_the_cell; kittest
  right_click_on_a_picture_offers_insert_caption and
  page_setup_different_first_page_leaves_the_title_page_unnumbered.
- Docs: ui-parity, target-app-parity, ROADMAP progress log.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8veLveuUsJJm6UEcQPEuW

* ui-parity: keep Insert Caption on the context-menu row

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:45:24 -04:00
dec24458cf #1273: equations from Word files keep all their content (#2613)
- Math straight in the body or a cell (m:oMathPara/m:oMath without w:p,
  allowed by EG_BlockLevelElts) gets its own paragraph instead of vanishing.
- mc:AlternateContent Requires="m" picks the equation, not its fallback.
- Inside an equation, runs in w:hyperlink, w:fldSimple, w:dir, w:bdo and
  mc:AlternateContent are kept (EG_PContentMath); depth stays bounded.
- w:sym, w:noBreakHyphen and Symbol-font text in math runs become Unicode.
- Layout: n-ary operators, delimiters, accents and group characters the math
  font lacks use a fallback font instead of a missing-glyph box.
- Coverage test reads every ECMA-376 §22.1 element and checks no argument's
  text is dropped; tests for body-level math, Requires="m", symbols, hostile
  nesting and the font fallback. Parity docs and progress log updated.


Claude-Session: https://claude.ai/code/session_01P8veLveuUsJJm6UEcQPEuW

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:45:01 -04:00
Fin WarmanandBrandon Thomas 473df388f3 Keep the line in an empty section starting a page (#2609)
* 371: retain the line in an empty page section

* 371: resolve hidden section marks

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:44:45 -04:00
beedd1b30d Drop Cap Options dialog (#2601) (#2602)
* #2601: Drop Cap Options dialog

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gaps: keep the Drop Cap Options note on the dialog-depth row

* i18n: translate the two Drop Cap disabled reasons in the audited catalogs

---------

Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:44:30 -04:00
87cab84e4a #1086: ribbon tooltips show why a control is disabled (#2623)
Hover hints give the command's own reason, cover split-button arrows, menu buttons and the font/size/outline boxes, and show on keyboard focus.

Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:44:12 -04:00
5fdd0a0e89 Watermarks in header table cells drawn behind the text (#1775) (#2580)
A floating picture or VML shape in a header table cell is placed on the page behind the text.

Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:43:55 -04:00
Fin WarmanandBrandon Thomas a7abd346e7 layout: preserve subpoint table grid widths (#2589)
* 356: preserve subpoint table grid widths

* 356: normalize tiny positive grid totals

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:43:27 -04:00
bdb7672c0f Dragging the scrollbar names the page at the top of the window (#2551) (#2575)
* #2551: dragging the scrollbar names the page at the top of the window

While the canvas's vertical scrollbar is dragged, a tip beside the pointer
says which page is at the top of the window, in the status bar's words
("Page 7 of 10"), so a drag through a long document shows where it will land.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* #2551: the scrollbar tip names the page whose visible band is at the top, also with Hide White Space

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:43:09 -04:00
Fin WarmanandBrandon Thomas b5759bcd99 351: reserve footer flow-table border clearance (#2585)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:42:54 -04:00
Fin WarmanandBrandon Thomas 5b211d6dc5 345: ignore explicit page breaks in table cells (#2574)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:42:39 -04:00
6dd7c3bc3a #1963: wordcraft-cli runs commands from a script file (#2566)
Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:42:13 -04:00
ReesandBrandon Thomas 1005c59bfc fix(ui): keep note editing text readable (#2545) (#2562)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:41:58 -04:00
11f8881cd2 #537: test that System pins the title bar to the desktop's light/dark answer on Linux (#2559)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:41:42 -04:00
Marco ArnulfoandBrandon Thomas 913621c1c4 Font dialog: Kerning for fonts and its Points and above size (#2295)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:41:26 -04:00
divyanshu2074andBrandon Thomas 8c328386fa fix(formats): enforce tag boundary when skipping raw text elements in HTML (#2257)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:41:10 -04:00
63ee34c557 #2105: Highlight No Color sticks to the button (#2208)
No Color removed the highlight from the selection, but the Highlight
split button kept the colour picked before, so the next click on it
highlighted again. As in Word, No Color now becomes the button's choice
and the next click removes highlighting. The ribbon and the mini toolbar
share one highlight menu (the ribbon's copy is gone); No Color is
translated in the mini toolbar and no longer shows Ctrl+Alt+H beside it
in the ribbon.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:40:55 -04:00
divyanshu2074andBrandon Thomas e04dd0e785 fix(formats): support cell and paragraph borders in RTF export (#2207)
* fix(formats): support cell and paragraph borders in RTF export

* rustfmt

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:40:31 -04:00
divyanshu2074andBrandon Thomas 9cd34ebc80 fix(formats): preserve tilde characters in LaTeX URLs and raw arguments (#2202)
* fix(formats): preserve tilde characters in LaTeX URLs and raw arguments

* rustfmt

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:40:15 -04:00
divyanshu2074andBrandon Thomas d9ca2573a6 fix(engine): count multi-column spanning cells once in table formula ranges (#2200)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:40:00 -04:00
divyanshu2074andBrandon Thomas a114a79a69 fix(doc, formats): support OEM character set 255 in charset_code_page (#2195)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:39:37 -04:00
Antoine BoxhoandBrandon Thomas 61a626820e #1552: no spelling squiggle under the word being typed (#2183)
Word draws no red squiggle under the word being typed. It appears when the word ends or the
caret leaves it by a key or a click. The session records the word after a text command that
edits the caret's paragraph, with apostrophes and hyphens counted as the spelling check counts
them, and drops it once the caret is anywhere else. The layout leaves that one range out of the
spelling squiggles, and a caret move without an edit lays out only that paragraph again. F7 and
the Spelling pane still report the word, and grammar marks are unchanged.

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:39:21 -04:00
divyanshu2074andBrandon Thomas 545673d644 fix(formats): resolve sub-location and external URLs in RTF HYPERLINK fields (#2181)
* fix(formats): resolve sub-location and external URLs in RTF HYPERLINK fields

* rustfmt

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:39:05 -04:00
divyanshu2074andBrandon Thomas 973e6e12f5 fix(formats): support quoted and non-latin charset declarations in HTML decode (#2180)
* fix(formats): support quoted and non-latin charset declarations in HTML decode

* html: clippy (question_mark, collapsible_if) after merging main

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:38:50 -04:00
94e3dda6af SmartArt: type into items; open the Text Pane by double-click or frame button (#2170)
* SmartArt: typing with the graphic selected types into an item

Typing with a SmartArt graphic selected replaced the whole graphic with
the typed text. Now the text goes at the end of the current item (the
first before any is picked) and the Text Pane opens, as in Word. The
typing is one undo step.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* SmartArt: double-click or the frame button opens the Text Pane

A double-click on a SmartArt graphic opens its Text Pane. While a
graphic is selected, a Text Pane button sits on the left edge of its
frame, as in Word, and shows or hides the pane.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* SmartArt: the Text Pane closes with the graphic's selection

It opened by itself on the next graphic selected, because the pane flag
outlived the selection. The frame button hides while the pane is open.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:38:34 -04:00
divyanshu2074andBrandon Thomas 3031033790 fix(layout): support quoted bookmark names with spaces in PAGEREF fields (#2169)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:38:19 -04:00
95b5c71f80 Save writes the chosen file when its folder refuses a temporary file (macOS privacy protection) (#2138) (#2167)
* #2138: save writes the chosen file when its folder refuses a temporary file (macOS privacy protection)

On macOS a Save-panel pick inside a protected folder (Desktop, Documents…) grants
access to that file only, so the sibling .wordcraft-save-*.tmp was likely refused
with EPERM. On PermissionDenied creating the temporary file, write the destination
directly; a remaining permission error on macOS says where to allow access.
Untested on a Mac: the fallback path is pinned on Unix with a read-only folder.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* #2138: a failed save in a folder refusing the temporary file keeps the original

Review (FredApps): the in-place fallback truncated the destination before
writing, so a failure partway through lost the previous document.

The fallback now keeps the existing file's bytes in memory (up to 512 MB)
before writing it in place and writes them back if the save fails, or
removes a new file it created. If that write-back fails too, the error
says the file may be incomplete. A file over the limit isn't written in
place; the error suggests Save As.

Tests: the reviewer's partial-write test (read-only folder), a new file
removed on failure, and the size limit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8veLveuUsJJm6UEcQPEuW

* #2138: keep the original untouched when no safe replacement is possible

When the folder refuses the sibling temporary file, an existing destination
is no longer overwritten in place (no in-memory rollback): it stays
byte-identical and the error says to use Save As to another folder or allow
access to the folder (macOS: Privacy & Security > Files and Folders). A
destination that doesn't exist yet is created exclusively and removed again
if the write fails.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8veLveuUsJJm6UEcQPEuW

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:38:04 -04:00
divyanshu2074andBrandon Thomas 6cf7159a71 fix(formats): emit \landscape in RTF export when section is landscape (#2159)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:37:42 -04:00
divyanshu2074andBrandon Thomas 65127c2727 fix(formats): handle negative timezone offsets and flexible day digits in spreadsheet iso_datetime (#2154)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:37:27 -04:00
874e5a76a0 #2052: a second picture style, border or artistic effect replaces the first (#2148)
Picture Styles, Picture Border and Artistic Effects now draw again from the
bitmap under them (kept per drawn picture in Session::picture_looks), so
Thick Frame then Simple Frame is only a simple frame, a border replaces the
border and keeps the style, a style replaces the border, and an effect
replaces the effect ("none" removes it), as in Word. Transparency was already
absolute (#1175); the test pins it.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:37:12 -04:00
divyanshu2074andBrandon Thomas 720f8acd2c fix(layout): support field format switches without whitespace after \* (#2147)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:36:58 -04:00
2054f8fd88 fix(web): fall back after asynchronous save picker rejection (#2145)
Preserve AbortError cancellation and report download fallback failures without marking saves successful.

Fixes #1246

Assisted-by: OpenAI Codex

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:36:42 -04:00
4c8508cd93 Insert › Shapes menu: an icon for each shape and connector (#2142)
Each item shows a small drawn outline of what it inserts (rectangle,
oval, triangle, star, elbow connector...). The icons are drawn in code in
icons.rs as shape.<kind>; widgets::icon_menu_item draws the item.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:36:27 -04:00
divyanshu2074andBrandon Thomas e7babf364e fix(formats): trim whitespace when parsing numeric XML attributes in ODT (#2137)
* fix(formats): trim whitespace when parsing numeric XML attributes in ODT

* rustfmt

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:36:12 -04:00
divyanshu2074andBrandon Thomas c9468a13cb fix(docx): support self-closing w:compat in settings merge (#2131)
* fix(docx): support self-closing w:compat in settings merge

* Drop the duplicate divyanshu2074 entry in people.toml (already on main)

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:35:43 -04:00
divyanshu2074andBrandon Thomas e2d9224996 fix(formats): support relative font size values in HTML font tags (#2130)
* fix(formats): support relative font size values in HTML font tags

* Drop the duplicate divyanshu2074 entry in people.toml (already on main)

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:35:28 -04:00
divyanshu2074andBrandon Thomas eedf9c9740 fix(doc): strip negative sign when formatting numbers rounded to zero (#2122)
* fix(doc): strip negative sign when formatting numbers rounded to zero

* Drop the duplicate divyanshu2074 entry in people.toml (already on main)

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:35:13 -04:00
divyanshu2074andBrandon Thomas 5977112a0d render, pdf: fix vertical double and wave border rendering (#2113)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:34:58 -04:00
872b2bc99d DOCX: ink inside groups and drawing canvases survives saving (gap 2) (#2097)
* gap: nested ink WIP

* gap 2: native ink nested in groups and drawing canvases survives DOCX saves

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* gap 2: review round 1: ungrouping keeps nested ink; no orphan parts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* gap 2: Impact cell matches the restated impact

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gap 2: only Word ink pins a group against Ungroup

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gap 2: alternate ink must hold an a:graphic to be written as standalone

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gap: nested ink WIP

* gap 2: native ink nested in groups and drawing canvases survives DOCX saves

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* gap 2: review round 1: ungrouping keeps nested ink; no orphan parts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* gap 2: Impact cell matches the restated impact

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gap 2: only Word ink pins a group against Ungroup

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gap 2: alternate ink must hold an a:graphic to be written as standalone

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:34:42 -04:00
Antoine BoxhoandBrandon Thomas aed0b71786 #1878: Rulers thin out with the zoom and span the caret's page (#2093)
Ruler numbers now thin out as the page shrinks on screen: a number
every 1, 2, 4, 8... units, whichever keeps them at least 30 px apart,
and the small ticks drop out below 4 px, with the text at its usual
size. A number gives way to an indent, tab or column marker sitting on
it, and the margins get ticks only. Both rulers use the caret page's
rect and scale in every layout, including One Page and Multiple Pages,
and follow the caret to another page. Tests cover the density rule, the
marks, the marker rule for indents, tab stops (set or dragged) and
table columns and rows, and the multi-page geometry.

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:34:26 -04:00
Antoine BoxhoandBrandon Thomas 0f5e945a69 #1945: Hide the Quick Access Toolbar and show it again (#2089)
The Quick Access Toolbar's menu ends with Hide Quick Access Toolbar, as Word's does. Show Quick Access Toolbar brings it back from the ribbon's right-click menu and from a check box on Customize Ribbon's Quick Access Toolbar page. The setting is kept between runs, and keytips skip the toolbar's digit badges while it is hidden. The UI command ui.quickAccessToolbar drives it from scripts and MCP. Regenerates docs/parity-checklist.md, which was behind the catalog. Adds my contributor entry.

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:34:10 -04:00
e50850d4dd RTF: formatting and paragraph-mark revisions are read and written (gap 19) (#2088)
* gap: RTF formatting revisions WIP

* gap 19: RTF formatting and paragraph-mark revisions

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* gap 19: review round 1: list kept on Reject; old formatting normalised; section marks; hostile borders

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* gap 19: review round 2: \oldcprops holds only the changed properties, as Word writes it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* gap 19: old formatting in styled paragraphs uses the style's size and font

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* gap 19: RTF import keeps main's heading and code normalisation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* gap 19: file-format-parity status line keeps main's history

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gap 19: a paragraph that was a list item gets its old list back on Reject

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gap 19: a numbered item made bulleted keeps its numbered list for Reject

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gap 19: format matrix names the tracked section mark

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* rtf test: Writer has the section fields main added; rustfmt

---------

Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:33:46 -04:00
Marco ArnulfoandBrandon Thomas 166b95feba Proofing: a hyphenated word added to the dictionary is no longer flagged (fixes #2082) (#2085)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:33:30 -04:00
072acce71b Legacy form fields are drawn: check boxes, and drop-downs' selected entry (#2076)
* Legacy form fields are drawn: check boxes, and drop-downs' selected entry

Legacy form fields keep their w:ffData since the last round, but were
not drawn: a FORMCHECKBOX has an empty result, so a form of check
boxes came out with none, and a FORMDROPDOWN showed its saved result
rather than its selected entry.

- wordcraft-doc: `legacy_form` reads what layout needs from the kept
  w:ffData (kind, name, check box state and size, drop-down entries and
  selection, text field length); `InlineObject::legacy_form()`.
- wordcraft-layout: a check box takes the text line's height of room
  and is drawn as Word draws it; a drop-down shows its selected entry
  (w:result, else w:default, else the first).

Measured on Word's PDF export with a synthetic document (Calibri):

  text size | Word square | WordCraft
  8 pt      | 7.44        | 7.45
  10 pt     | 9.96        | 9.89
  12 pt     | 12.36       | 12.33
  20 pt     | 22.08       | 22.09
  w:size 15 | 16.08       | 15.99

The square sits 1.16 pt inside the line height on every side (room on
the line within 0.2 pt of Word's), has a 0.72 pt border and, checked,
an X from corner to corner in 0.48 pt lines; w:checked beats
w:default. docs/file-format-parity.md is updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Draw::Shape takes the dash list main added

---------

Co-authored-by: Daniele Mori <Dinasty@hotmail.it>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:33:15 -04:00
70fc00c80f Symbols keep their symbol font when the text font changes (#2036) (#2037)
* Symbols: a w:sym character keeps its symbol font when the text font changes (#2036)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* #2036: review round 3: docx test reads sym_font, paste drops the symbol font, astral symbols stay text

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* #2036: insert.symbol decides symbol or text per character

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 11:33:00 -04:00
20188e4610 A floating object's anchor takes no room on a line (#2033)
A line's first item stays on it even when it is wider than the line;
markers before it don't count. A floating object's anchor (a zero-size
object cluster) did count, so a picture a little wider than the line,
after an anchor, went to a second line and left the anchor an empty
line of its own above it. Word keeps the picture on the first line.
Anchors are now ignored like markers when deciding whether the line
already has content.

Co-authored-by: Daniele Mori <Dinasty@hotmail.it>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:32:22 -04:00
1b45615940 Insert › Shapes keeps the selected shape and text (#2019) (#2030)
Inserting a second shape removed the first: after an insert the new
shape stays selected, and `insert.shape` replaced the selection, so each
shape replaced the one before. Word draws a new shape beside whatever is
selected and never deletes it (checked by hand in Word for Windows: a
second shape is drawn over the first, which stays).

The new shape now goes after the selection, which is left alone, and
becomes the selection. Selected text stays too. A picture still replaces
a selected picture, which is what Word does as well (checked in Word for
Windows), so `insert.picture` is unchanged.

Tests: three shapes inserted in a row are all kept, which fails with the
old code (1 of 3 kept); a shape inserted over selected text keeps the
text and is selected itself; a picture inserted over a selected picture
replaces it.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 11:32:07 -04:00