Commit Graph
871 Commits
Author SHA1 Message Date
Mex bf9571d7e1 Merge branch 'main' into fix/reject-invalid-comment-ids 2026-10-20 22:41:14 +02:00
ratkoandClaude Opus 5.5 15d5617e70 #3331: closing the header or footer returns to the body selection
Close Header and Footer (Esc, the ribbon button, MCP) always put the caret
at the start of the document, so the view jumped to page 1. The session now
remembers the body selection when a command moves the caret into a header
or footer, and closing puts it back, as Word does. A double-click on the
body still puts the caret where clicked.

Fixes #3331.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 22:11:38 +02:00
Mex 1b712863c1 M15: document Cuban and Peruvian decimal separator coverage
Record the regression evidence, preserve broader localization readiness, and update the touched parity document status and history.
2026-10-20 22:02:37 +02:00
Mex 642bf70594 docs: note corrected Cuban and Peruvian table numbers
Record the narrow regional separator correction without changing localization readiness or effort estimates.
2026-10-20 21:49:28 +02:00
LQRD 253fab8a81 #2882: restore the saved proofing default when a command is rejected
Roll back the new preference on final command rejection, including protected-region validation after handler success. Cover prior/default-free preferences, document and undo rollback, serialization and restart. Qualify interface-language fallback documentation and add missing function documentation.
2026-10-20 21:47:13 +05:00
Mat Strangeandopencode 3a15b19e7f Docs: the progress docs' status lines carry today's date
Co-Authored-By: opencode <noreply@opencode.ai>
2026-10-20 17:20:53 +01:00
LQRD ab68111717 M15: persist the default proofing language across restarts (#2882) 2026-10-20 20:07:09 +05:00
LQRD 3d03c7cc7a M15: fix Russian ё ordering and decomposed Cyrillic collation 2026-10-20 19:07:31 +05:00
Jayesh Prajapati fdc325fa89 #3003: Save to a NAS share mounted by GVFS keeps working when it refuses a mode change
A replaced document's temporary file takes the original's Unix mode before
it replaces it. A GVFS SMB mount (smb:// in the Linux file manager) refuses
every mode change with ENOTSUP, so every save of an existing file there
failed and the close prompt's Save never closed. A folder that keeps no
Unix modes has no mode to keep, so the save goes on; any other failure to
set the mode still stops it and keeps the original.
2026-10-20 19:24:45 +05:30
Jayesh Prajapati ee51f59602 #3176 review: recent documents with the same file name are told apart by their path
Two Recent entries ending in the same file name had the same accessible name,
so a screen reader couldn't say which one each button opens. A repeated file
name now adds the path painted under it; unique names are unchanged.
2026-10-20 19:04:11 +05:30
Mat Strangeandopencode 376a517cb0 Docs: the Restrict Editing gaps that are closed
Co-Authored-By: opencode <noreply@opencode.ai>
2026-10-20 14:32:40 +01:00
Mat Strangeandopencode bcd751a588 Restrict Editing: a file command that changes the document is checked too
`always_allowed` waved through every `file.*` id, so on a protected document
the file commands that do change it went unchecked: the privacy options and
the properties wrote document settings, and the inspector's removals deleted
content. The privacy options' own comment already said they were "refused on
a protected document"; that wasn't true.

The allow-list now names the file commands that don't change the open
document, and the ones that do are checked like any other command. Reading
the document stays allowed: the inspector without removals, the privacy
settings, the info, and saving a version snapshot.

Restoring a stored version replaces the whole document, and a snapshot's own
protection is stale — restoring one lifted the protection and dropped its
password. The live document's protection, password and formatting limit now
survive a restore.

Co-Authored-By: opencode <noreply@opencode.ai>
2026-10-20 14:31:41 +01:00
Jayesh Prajapati 950a7adaaa #3176: File › Home and New name each template and recent document for screen readers
Each template tile drew its thumbnail as an unnamed click area with the
caption as a separate label, and each Recent row was an unnamed click area,
so a screen reader found no button and no name to announce. The thumbnail
and caption are now one button named by the caption (painted as before, so
the page looks the same), and each Recent row is a button named by its file
name.
2026-10-20 18:52:52 +05:30
rabisandClaude Opus 5.5 37f28eedd0 #2428: the table handles show while the caret is in the table
As in Word, the caret's table shows its move handle past the top-left
corner and its resize handle past the bottom-right one wherever the
pointer is, not only while the pointer is over the table.
table_mouse::caret_handles gives them per page; the app paints them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 13:00:38 +02:00
rabisandClaude Opus 5.5 8e799be97e #1899: wrap outlines and PDF bitmaps follow the same crop window
contour::picture_outline turned the crop into a pixel window on its own,
so a sliver or overlapping crop gave an empty window and Tight/Through
wrapping fell back to the frame while the renderers draw a 0.5% sliver.
It now uses wordcraft_metafile::crop_window, with the upper pixel edges
rounded up. A PDF test covers the bitmap and metafile paths of the export
(CodeRabbit on #3247).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 11:54:17 +02:00
Mikael Tollefsen 51ef9b9ebc Docs: control protocol's Methods table renders again
The engine.execute row listed the UI commands with unescaped "|" inside
code spans ("system"|"on"|"off", true|false, ...). GitHub-flavoured
Markdown splits table cells on every unescaped pipe, code spans
included, so the row came out as 32 cells in a 3-column table and was
cut off. A second, older engine.execute row duplicated it with a
shorter command list.

The two rows are now one: the current row, with ui.contextMenu (only in
the older row) added. Every "|" inside its code spans is escaped as
"\|", which GitHub shows as "|". Every row of the file's tables now has
its header's number of cells. Nothing else changes.
2026-10-20 11:31:07 +02:00
Магда М.Г. 7f2f45743a Layout: Apple's one-em Symbol takes Windows Symbol's line height, as in Word for Mac
Word for Mac spaces Symbol lines at 1.222 em (measured at 11 and 20 pt)
even with Apple's Symbol installed, whose own line is one em. Symbol's
metrics now apply when the resolved face is one em tall as well as when
the font is substituted (fonts::word::symbol_line).
2026-10-20 12:14:18 +03:00
rabisandClaude Opus 5.5 0cca2f7d21 #1899: a picture cropped to a sliver is drawn at the size the file gives
A crop that kept under 5% of a picture's axis was widened to 5%, so a
header bar cropped to 2.7% of a page-sized WMF came out half as tall and
the text box over it fell below it. The rasteriser, the PDF writer and
the metafile placement now share wordcraft_metafile::crop_window, which
keeps down to 0.1% of an axis and keeps junk crops finite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 10:29:15 +02:00
Diego GueriniandClaude Sonnet 5.5 ff77295db2 Merge upstream/main into altgr-keytips
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 09:54:15 +02:00
Mikael Tollefsen 835f5b5f5f Docs: layout-parity's status date follows its 2026-10-19 revision row 2026-10-20 09:40:49 +02:00
Mikael Tollefsen 8d16b26630 #1549: a Thai run with Latin finds one installed font covering it all
On Linux the run fallback loaded the script's preferred family (Noto Sans
Thai, which has no Latin letters) and stopped: every character had a face,
so an installed font mapping the whole run (IBM Plex Sans Thai) was never
tried, and a Thai + Latin run was split across two faces. Three Thai tests
failed on machines with Noto Sans Thai installed.

When no loaded face covers the run, the search now looks through the
coverage index for the first installed file mapping the whole run. It
loads that file's whole family, since path order can reach the Bold
file before the Regular. It also looks at the loaded faces again even
when it loaded nothing itself: a concurrent search may just have
loaded the font and taken its files off the index, and the miss would
otherwise be cached.

Regression test: a_run_no_preferred_face_covers_whole_loads_an_installed_font_that_does
(synthetic fonts, independent of what is installed).
2026-10-20 09:11:29 +02:00
Dominik StrebelandClaude Opus 5.5 714306fd31 Restrict Editing: forms protection greys out the content-control buttons
With Filling in forms enforced, Word greys out the Developer tab's
content-control buttons and Properties. WordCraft refused them when
clicked (#3112) but drew them live. The ribbon now asks the same check:
Session::why_disabled combines a command's own `enabled` with what
protection refuses outright, and the tooltip says why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:57:11 +02:00
rabisandClaude Opus 5.5 fc36739622 #2038: a click below a floating table goes to the text, not its last row
A table dragged by its move handle floats and the empty paragraph after it
moves up beside it; a click below the table then landed in a cell of its last
row (the nearest line). Pages now list their floating body tables, and
DocLayout::hit leaves out a floating table's cell lines when the point is
outside the area its cells cover, as long as other lines are left. Checked
against Word 2019 for Windows: clicks below the table and Ctrl+End go to the
paragraph beside or after it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:31:15 +02:00
midasdf a7f888055a #1681: HTML export and import keep furigana (ruby)
`InlineObject::Ruby` is written as `<ruby>base<rt>reading</rt></ruby>`, in the
base text's run formatting, and `<ruby>`/`<rb>`/`<rt>` are read back into one
ruby object, so docx/doc → HTML → doc keeps the annotation. `<rp>` fallback
parentheses and the tags are not text; unclosed or half-marked ruby (no `<rt>`,
empty `<rt>`, no base) is tolerated and keeps the text it held, with a block
boundary closing the element as a browser does. HTML states no alignment, size or
raise, so import uses the Phonetic Guide's defaults (centred, half the base size,
raised clear of the base text; the run's size, or 10.5 pt when none is stated).

The flow model gains `Inline::Ruby`; formats without ruby (RTF, ODT, Markdown,
LaTeX) write its base text as before. Tests: `html::tests::ruby_*` and
`tests::html_ruby_round_trip`. Docs: file-format-parity (HTML row) and
localization-parity (Japanese row).
2026-10-20 13:35:52 +09:00
midasdf 2d645dba03 #1653: RTF import decodes the East Asian multibyte code pages
`\ansicpg932`/`936`/`949`/`950`, a font's `\fcharset128`/`129`/`134`/`136`,
`\cpg932` and the OEM charset 255 were read one byte at a time, so Japanese,
Korean and Chinese text came out as mojibake. The reader now holds the 8-bit
text of a multibyte code page and decodes the run with encoding_rs (SHIFT_JIS,
GBK, EUC_KR/UHC, BIG5): a lead byte and its trail byte decode together, escaped
(`\'hh`) or raw. A code page switch (`\f`, `\fcharset`, `\cpg`, `\ansicpg`), a
group end and the end of the document flush what is pending; invalid sequences
read as U+FFFD, as Word writes them, and never lose the rest of the text. The
pending buffer is capped at 4096 bytes.

Single-byte code pages, `\uN?` escapes and their `\ucN` skips, the font table
and every existing test are unchanged. Tests cover Shift-JIS (escaped, raw and
through a `\fcharset128` font), CP949/CP936/CP950, a mixed Japanese/ASCII/
Cyrillic document whose code-page switch must flush, `\uN?` alongside
multibyte text, an invalid sequence and a Windows-1252 regression.
2026-10-20 13:35:52 +09:00
PanSHIgg d4192a0e98 Layout: Format Page Numbers dialog (#1113)
Insert › Header & Footer › Page Number ▸ Format Page Numbers… ran a
plain `layout.pageNumberFormat` call that changed nothing and cleared
the section's Start at. The item now opens Word's dialog: the number
format (1, 2, 3 / I, II, III / i, ii, iii / A, B, C / a, b, c) and
Page numbering — Continue from previous section or Start at: n.

`layout.pageNumberFormat` keeps the section's start when `start` is
left out and numbers on from the section before for `"start": null`;
the dialog reads the section at the caret and writes through the same
command, so scripts and MCP get the same result without it. The
dialog's strings are in every interface catalogue and it joins the
untranslated-text audit. ROADMAP, docs/ui-parity.md and docs/gaps.md
get their rows.

Tests: engine (format and start, keep and continue); ui-egui (the
dialog reads the section, OK sets the format and start, continue
clears it, and a plain command call keeps the start); the i18n audit
draws the dialog's text.
2026-10-20 12:04:42 +08:00
Cursor AgentandCRBBeesy 60e3ff8881 i18n: File › Home greeting in every interface language
`home_page` already passes "Good morning", "Good afternoon" and "Good evening"
through `tl!`, but nine catalogs had no entry, so File › Home opened in English
in German, Estonian, Japanese, Brazilian Portuguese, Serbian (Cyrillic and
Latin), Ukrainian and Chinese (Simplified and Traditional). Adds the three
greetings to each, and a test that every language has them.

Co-authored-by: CRBBeesy <CRBBeesy@users.noreply.github.com>
2026-10-20 03:57:48 +00:00
Sazid Al Bayazid 213045230d Layout: a line can break after a hyphen before a digit, like Word (#2712) 2026-10-20 08:36:18 +06:00
Магда М.Г. e6e007d018 Symbol (PCL6) keeps Symbol's line metrics; restore the STYLEREF row in layout-parity 2026-10-20 05:18:11 +03:00
vangel76 12bb1039d1 Formatting revisions (gap 5, #41): a table, row, cell or section property change made while Track Changes is on now records as a tracked change (w:tblPrChange / w:trPrChange / w:tcPrChange / w:sectPrChange)
Word records formatting changes to table, row, cell and section properties while tracking; the model, the OOXML reading, the writing and Accept/Reject all existed — only the recorder compared characters and paragraphs. `Recorder.blocks` in `crates/engine/src/cmd/fmt_revisions.rs` now compares those properties too (structure stays out: a table's grid, a cell's merge span, a section's headers and footers), so Reject All puts them back and Accept All keeps them.

- regression test `tracked_table_changes_are_kept_as_formatting_changes` (fails without the recorder)
- docs/gaps.md gap 5 narrowed
2026-10-20 01:26:25 +02:00
rabis 9139162e0f #2802: Delete on whole table cells leaves one empty paragraph in each 2026-10-20 01:19:49 +02:00
Dominik Strebel 1fa2533a52 DOCX: majorBidi/minorBidi theme fonts follow the theme font language 2026-10-20 01:19:14 +02:00
Viorel ToaderandClaude Sonnet 5.5 e375004cd6 G14: Romanian parity doc: entry range and citation-style note
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JadgGo4G2GHaAMNb3qyygk
2026-10-20 01:13:28 +02:00
Viorel Toader 2d957c905b G14: Romanian (ro) interface catalog 2026-10-20 01:13:28 +02:00
Dominik Strebel 88d936c3c5 Layout: justified lines shrink their spaces by Word's measured limits 2026-10-20 01:11:36 +02:00
Joey 156817d6ba Word signature lines stay signable after saving a .docx 2026-10-20 01:10:22 +02:00
Matteo Andreuzza 59d9beaeec 3099: Read embedded ODT equations from their MathML object 2026-10-20 00:56:59 +02:00
rabis fb92192fd2 2986: Search and three other boxes stop resetting the input method every frame 2026-10-20 00:51:55 +02:00
ratkoandClaude Opus 5.5 06a120b19f Drop a picture near the bottom of a page where it lands (#3169)
To find the offset from its anchor paragraph, a dropped object was
first laid out at the paragraph's top. Near the bottom of a page that
pushed the paragraph onto the next page, so the object ended up about
a page below the drop point, cut off at the page edge.

Now it is first placed where it was dropped, and the paragraph's
position is read from that layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:28:45 +02:00
dfgodvan e537dce6af Docs: tabs that wrap with their text in the pagination gap (#1840) 2026-10-19 23:08:19 +03:00
dfgodvan 10dff145c5 Docs: the tab-wrapping entries name the cases they cover (#1840) 2026-10-19 23:08:14 +03:00
dfgodvan a216519d44 Docs: tabs that wrap with their text in layout-parity and the progress log (#1840) 2026-10-19 23:07:57 +03:00
Fin Warman b42f1b8061 Refresh main without changing feature history (#2431) 2026-10-19 20:52:37 +01:00
Магда М.Г. af2eb4c6ad Merge remote-tracking branch 'up/main' into up-symbol-font-line-height
# Conflicts:
#	crates/layout/src/tests.rs
#	docs/layout-parity.md
2026-10-19 22:48:35 +03:00
Магда М.Г. bb4c579a4d Merge remote-tracking branch 'up/main' into up-fonts-roman-known-substitutes
# Conflicts:
#	crates/fonts/src/word.rs
#	crates/layout/src/para.rs
#	docs/file-format-parity.md
2026-10-19 22:46:07 +03:00
Tyrel Haveman 452244fd19 Merge remote-tracking branch 'upstream/main' into table-of-figures-label
# Conflicts:
#	ROADMAP.md
2026-10-19 10:40:16 -07:00
justinjohn0306 0a5d0af4f0 Fix #3137: Cannot insert a tab inside table cells (missing Ctrl+Tab shortcut) 2026-10-19 23:02:15 +05:30
e6c5a701dd The caret and clicks land between the letters of a ligature (#1974) (#2006)
* Fix #1974: the caret and clicks land between the letters of a ligature

The glyph's advance is shared evenly among its letters (mirrored in
right-to-left text); ligature letters keep their character spacing.

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

* Fix #1974: a long word never wraps inside a ligature

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

* Fix #1974: a hyphenation point never splits a ligature

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

* #1974: ligature tests use a bundled font that draws fi and ffi as ligatures

They assumed the installed default-font stand-in draws ligatures; Liberation Sans (Linux) draws
none, so they failed there.

Co-Authored-By: Claude Opus 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-19 13:09:22 -04:00
4e2568e2da RTF import: heading and code formatting compared with the file's own stylesheet (gap 19 follow-up) (#2236)
* gap 19: RTF import compares heading and code run formatting with the file's stylesheet

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

* gap 19: review round 1: a style chain with formatting words is complete; unnumbered entries are Normal

Co-Authored-By: Claude Opus 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-19 12:57:16 -04:00
b8debb3050 Content controls: typed text takes the control's formatting, in any language (#3116)
* Content controls: typed text takes the control's formatting, in any language

Text typed in place of a content control's placeholder takes the
control's own run properties (w:sdtPr/w:rPr, ECMA-376 §17.5.2.27), as
in Word: in a protected form filled in Word for Mac, all 17 entered
values carry the style their control's rPr names. WordCraft kept that
rPr only as XML to write back and gave typed text the placeholder's
formatting minus the placeholder style.

It also knew the placeholder style only by its English id,
PlaceholderText. German Word writes Platzhaltertext (the name stays
"Placeholder Text"), so in forms from German Word every entry stayed
grey, on screen and in the saved file, and restoring a placeholder
added a second Placeholder Text style. The style is now found by its
built-in name.

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

* Content controls: typing drops a showing placeholder's own style

A control without run properties that shows its placeholder: text typed
over it drops the placeholder run's character style whatever its id
and name. Word localizes only the placeholder style's id, but another
program may localize its name too, and the name lookup then misses it.
Restoring a placeholder and new controls keep the name lookup.

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-19 12:53:44 -04:00