Commit Graph
202 Commits
Author SHA1 Message Date
Jayesh Prajapati 4e692b4123 #3637: A table cell span from a .json file no longer overflows (#3927)
Insert Column, Merge Cells and Delete Column did arithmetic on the raw
CellProps::span, which a .json document can set to any u32, so a span
near u32::MAX overflowed (a panic in debug, a wrapped span in release).
They now work from the clamped span() and cap the result at MAX_COLS.
2026-10-23 11:20:58 -04:00
NetterSilverandClaude Haiku 5.5 32f8e2c2ad Fix spurious 零 after a group's trailing zeros in Chinese numerals (#3745)
Found while testing crates/doc/src/cjk_numbers.rs:47-55 (Counting::format)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-23 10:31:48 -04:00
NetterSilverandClaude Opus 5.5 66ff2afc4d Return None from parse_number when the value overflows f64 (#3577)
Found while testing crates/doc/src/locale_number.rs:104

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 10:31:39 -04:00
aiongg 5dc68481ed Integration: track t09
crates/ui-egui/src/backstage.rs: t03's bidi_display on the Recent names over t09's borrowed name/path. people.toml: union. Tests: both tracks' tests kept whole. Docs: status lines combined, rows unioned or word-merged.
2026-10-22 01:48:25 +00:00
aiongg 3581f80251 Integration: track t07
# Conflicts:
#	ROADMAP.md
#	docs/file-format-parity.md
#	docs/gaps.md
#	docs/layout-parity.md
2026-10-22 01:47:46 +00:00
aiongg 04b3881e3e Integration: track t06
docs/gaps.md row 4: one row (t06 had kept a second, older copy of it); t05's #1840 and t06's #2964 clauses both in, main's #2963 clause kept. docs/recovery.md: t06's retry sentence with t01's base64 size text. Test files: both tracks' tests kept whole.
2026-10-22 01:47:34 +00:00
aiongg 16d1c8a933 Integration: track t05
crates/pdf/src/lib.rs: t01's vector_text kept before t05's watermark (box area signature). Test files and canvas.rs tests: both tracks' tests kept whole. Docs: status lines combined, rows unioned or word-merged.
2026-10-22 01:46:47 +00:00
aiongg 0d3b8eb0cb Integration: track t04
crates/formats/src/odt.rs: t01's Body::new/take_blocks kept; take_blocks finishes tables with t04's TableB::finish (column widths). Test files: both tracks' tests kept whole. Docs: status lines combined, rows unioned or word-merged.
2026-10-22 01:46:17 +00:00
aiongg 245b5bd8d0 Integration: track t02
Docs: status lines combined (t02's entries first); log rows unioned; file-format-parity .rtf row from t02 (#1653, duplicate .rtf row dropped as t02 did), .odt row word-merged.
2026-10-22 01:44:01 +00:00
aiongg 406694ea58 Integration: #3429 the based-on-chain test's doc comment back above its test 2026-10-22 01:25:08 +00:00
aiongg ef00b55870 Merge PR #3429: #3415: banded rows shade the same rows in the reference app and WordCraft (table style band sizes)
crates/docx/tests/fixtures.rs: union, keeps main's shape-gradient test and the PR's band-size tests.
ROADMAP.md, docs/file-format-parity.md: main's status lines with this change added to the newest; log rows from both sides in date order.
2026-10-22 01:25:02 +00:00
aiongg 61570835bc Merge PR #3156: Watermark: the text fills its shape's box, as the reference app's textpath does
crates/docx/src/read/story.rs: main's vml_opacity with the PR's box size.
crates/pdf/src/tests.rs: both sides' tests kept; the glyph_frames helper both #3155 and #3156 add stays once.
2026-10-22 01:24:10 +00:00
aiongg d985d0ecce Merge PR #3289: M15: fix Russian ё ordering and decomposed Cyrillic keys
ROADMAP.md: status line and revision history carry both sides.
docs/gaps.md, docs/localization-parity.md: status lines carry both sides.
2026-10-22 01:23:41 +00:00
aiongg 9cd24539bd Merge PR #2549: #1653: RTF import decodes the East Asian multibyte code pages (932/936/949/950)
docs/file-format-parity.md: main's status line with this change added.
2026-10-22 01:23:23 +00:00
aiongg 264bfdaed3 Merge PR #3333: M15: correct Cuban and Peruvian Spanish decimal separators
ROADMAP.md, docs/gaps.md, docs/localization-parity.md: main's status lines kept; the PR's log rows and gaps note added.
2026-10-22 01:23:06 +00:00
aiongg 1c757ece6b Merge PR #3199: Signature lines stay signable after saving a .docx
ROADMAP.md: status line once (this change first, then main's); progress-log rows union in date order
docs/file-format-parity.md: status line once; VML row merged word by word (main's #1500 fill text plus the PR's signature-line text)
2026-10-22 01:22:51 +00:00
aiongg b0fb2b9386 Merge PR #2101: File: recovery copies and .json files store pictures as base64 (#586 follow-up)
ROADMAP.md: status line, progress log and revision history carry both sides.
docs/file-format-parity.md: status line and change log carry both sides.
2026-10-22 01:22:47 +00:00
aiongg 558f6c85af Merge PR #2343: Fix numbered list levels that start at 0 or are overridden to 1
crates/doc/src/numbering.rs: kept #3417's per-(num, level) seen map and its single-level override; the override now sets that level's LevelFlags { started: false, first: Some(start) } from #2343 instead of start - 1 (the reviewed integration fix for #2343).
2026-10-22 01:21:21 +00:00
aiongg eedcd7e98c Merge PR #2244: fix(docx, doc): support VML wrap side and case-insensitive float anchors
crates/docx/tests/fixtures.rs: both sides' appended tests kept.
2026-10-22 01:21:19 +00:00
aiongg 9eb0dba8d0 Merge PR #3417: doc: a start override restarts only its own level 2026-10-22 01:20:54 +00:00
aiongg 5a8cb21978 Merge PR #3315: Reject signs and repeated '#' in Rgb::parse 2026-10-22 01:20:53 +00:00
aiongg 53418631eb Merge PR #1739: Tables nest 24 deep at most, so pasting a table into its own cell can't build a document that crashes (#1596)
ROADMAP.md: main's status line kept; both progress-log lines added.
docs/target-app-parity.md: main's status line and Tables row kept, #1596 sentence added to the row; log row added.
2026-10-22 01:20:47 +00:00
aiongg 8077310218 Merge PR #3463: fix(docx): preserve East Asian language w:eastAsia on w:lang 2026-10-22 01:20:11 +00:00
aiongg 11f265b807 Merge PR #3304: Map Windows-1255 byte 0xCA to U+05BA 2026-10-22 01:20:11 +00:00
aiongg cbc3246c2c Merge PR #2298: Comments: comments in headers, footers, notes and text boxes are listed, get balloons and are reached by Next/Previous (#2289) 2026-10-22 01:20:00 +00:00
aiongg abd1c7fb36 Merge PR #1760: Tables: rows with gridBefore/gridAfter keep their grid columns 2026-10-22 01:19:46 +00:00
aiongg 50ef30939f Merge PR #2034: Floating objects are drawn in their stacking order (relativeHeight) 2026-10-22 01:19:45 +00:00
6b01aa967f Shape fills: gradients and transparency (#1500) (#1605)
* #1500: shape fills keep gradients and transparency (model, DOCX read/write)

A shape's, text box's and canvas's fill is now a `Fill` (solid with
transparency, or a gradient kept as the file states it) instead of one
opaque colour, so gradients and transparency survive opening and saving.

- doc: `fill::Fill`/`Gradient` with sanitizing for hostile input; `.json`
  keeps writing opaque solid fills as `[r,g,b]` and reads both forms;
  `ShapeExtra::outline_fill` keeps an outline gradient.
- docx read: `a:solidFill` with `a:alpha`, `a:gradFill` (stops, `a:lin`,
  `a:path`/`fillToRect`, `tileRect`, `rotWithShape`, `flip`), theme fill
  styles through `a:fillRef` 1-999/1001+ with `phClr`, `a:grpFill`,
  `satMod`, outline gradients, VML `v:fill` gradients and opacity, canvas
  backgrounds.
- docx write: `a:solidFill` + `a:alpha`, `a:gradFill` as read.
- engine/docbin/layout: call sites; drawing still uses the main colour
  (next commit draws gradients).

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

* #1500: draw shape gradients and transparency (layout, render, PDF)

- layout: WordArt's paint becomes a shared `display::Paint` (solid,
  linear, radial); `paint_for` lays a fill over the shape's frame
  (linear at its angle, `scaled` honoured; path gradients circular from
  their focus to the farthest corner). Shapes, freeforms and canvas
  backgrounds use it.
- render: one `set_paint` for shapes, paths and WordArt; radial
  gradients; soft edges fade the real fill.
- pdf: axial and radial shadings with per-stop opacity.
- Review fixes: nested groups without a fill pass theirs on to
  `a:grpFill`, text-box contents don't take a group's fill, `phClr`
  transparency only on `phClr` colours, VML focus ends consistent and
  opacity clamped, `rotWithShape`/`scaled` written only when set,
  Shape Outline clears an outline gradient, shared stop sanitizing.
- docs: file-format, layout parity, gaps #1, roadmap progress log.

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

* #1500: shape.fill sets transparency and gradients on every selected shape

- shape.fill (now cmd/shape_fill.rs) takes {"color", "transparency"?} or {"gradient": {stops,
  type, angle, focus, rotateWithShape}}; a colour alone keeps the transparency; values are
  sanitized; applies to every selected shape, text box and canvas as one undo step.
- Formatting (shape.fill, shape.effects) keeps a Shift+click multi-selection, as in Word.
- view.formatShapePane toggles the Format Shape pane.
- Session::undo_mark/merge_undo_since: a pane drag that applies as it goes undoes in one step.
- Helpers for the pane: params(fill), stop add/remove/move, directions, variations and
  presets (variation and preset colours provisional until compared with Word).
- Catalog: Shape Fill Gradient, Format Shape Pane.

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

* #1500: Shape Fill › Gradient and the Format Shape pane

- Shape Fill › Gradient: No Gradient, Light and Dark Variations of the shape's colour, More
  Gradients… (opens the pane).
- Format Shape pane (right): No fill / Solid fill (colour, transparency) / Gradient fill
  (presets, type, direction, angle, stops bar with add/remove/drag and arrow keys, per-stop
  colour, position, transparency, rotate with shape). Drags preview live, one undo step.
- Right-click › Format Shape… on shapes, text boxes and canvases.
- Gradient swatches have accessible names; new labels translated (own wording, clean room).

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

* #1500: preset gradients are our own design (clean room)

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

* #1500: Gradient variations, starting gradient and directions as Word 365 does them

Observed in Word 365 (behaviour and values only):
- Shape Fill › Gradient: a No Gradient swatch, then 13 Light and 13 Dark Variations in a
  grid five wide, in Word's order; light stops tinted 66/44.5/23.5% with saturation ×1.6,
  dark shaded 30/67.5/100% with ×1.15; linear ones scaled; corners with their tile rectangle.
- Format Shape › Gradient fill starts from the theme's first accent (four stops, 0/74/83/100%).
- Corner directions in the pane get the same tile rectangle; Add/Remove sit by the stops bar.
- shape.fill carries "scaled" and "tile"; docx exports color_modified (lumMod, lumOff, tint,
  shade, satMod) so variations use the reader's own colour maths.

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

* #1500: review fixes for the shape fill ribbon controls

- Gradient variations are built from the colour the shown variation came from, so picking
  variations in turn, or No Gradient, doesn't drift the colour.
- A drag's undo mark is forgotten while the Format Shape pane is closed (a stale mark could
  merge later undo steps).
- Dragging on the stops bar away from a handle no longer moves the selected stop; the arrow
  keys are taken by the bar (no focus moves or shape nudges).
- Direction and Type changes keep a linear gradient's "scaled" and an imported tile
  rectangle; only a corner direction sets its tile.
- Colour modifiers (lumMod, lumOff, tint, shade, satMod) live on Rgb in the doc crate, shared
  by the DOCX reader and the gradient builders.
- Previews build their stop list once per swatch, not per vertex.
- Translations for the pane's hint, direction and preset names.

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

* #1500: adapt to main: caret contrast samples gradient fills; upstream tests use Fill/Paint

- Paint::at gives a paint's colour and opacity at a point; the caret's background sampling
  (#299) uses it for shape fills, now gradients or transparent, and the Format Shape
  previews use it too.
- Upstream tests (#886 shapes survive saving, render) build fills as Fill/Paint.

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

* #1500: adapt to main after the rebase: VML presets, rounded corners, new catalogs

- vml_fill takes the shape's shapetype: a VML preset shape (#1377) takes its fill, opacity and
  gradient from its shapetype when it states none of its own, as it already took its colour.
- Rounded-rectangle corners (#1476) and the gradient paints meet in render, PDF and the caret's
  background sampling; ShapeExtra keeps both `corner` and `outline_fill`.
- Tests that landed on main since build fills as Fill/Paint (VML presets, cover pages, VML
  freeforms, path arrowheads, PDF and render shapes).
- The 40 Shape Fill / Format Shape strings in the hr, ko, sv and vi catalogs, which main
  gained since.

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

* #1500: docs: shape gradients and transparency, Shape Fill › Gradient and the Format Shape pane

Re-applied on main's docs after the rebase: progress log, file-format, layout and UI parity
rows, gaps #1, status lines and revision history; parity checklist regenerated.

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

* #1500: a theme picture fill falls back on the reference colour; VML freeform opacity note

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

* #1500: adapt to main after the second rebase: VML shapetype tests compare Fill; parity checklist regenerated

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

* #1500: one VML fraction parser; a preset takes its gradient from its shapetype

Review notes: story.rs's watermark/freeform opacity reuses shape_style's vml_fraction (clamped at the callers) instead of a second copy; a test pins a VML preset whose v:fill gradient comes from its v:shapetype, and the 65536ths form of a fraction.

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

* #1500: adapt to main after the third rebase: the shape duplicate preview test fills with Fill

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

* #1500: review — harness test: right-click a shape, Format Shape… opens the pane and keeps the shape selected

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

* #1500: review — theme keeps every fill style a fillRef can reach (999 per list), still bounded

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

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: aiongg <aiongtaigi@gmail.com>
2026-10-21 19:12:26 -04:00
Divyanshu Gupta a8ba49e68b fix(docx): preserve East Asian language w:eastAsia on w:lang
Preserve w:lang/@w:eastAsia when reading and writing DOCX documents.
Previously, only w:val and w:bidi were handled, causing w:eastAsia to be
dropped on save.

Fixes #3457
2026-10-21 20:13:15 +05:30
Nghiathan13andClaude Opus 5.5 67d21b0a68 #3415: banded rows shade the same rows in Word and WordCraft
Word reads a table style without w:tblStyleRowBandSize / w:tblStyleColBandSize
as bands of zero and leaves its banded rows and columns unshaded (MS-OE376
§2.7.5.7, MS-OI29500 §17.7.6.5); ECMA-376 says one, which is what we did. Our
writer only wrote a size a style set, and our built-in styles set none, so a
table in Grid Table 4 saved by WordCraft had shaded rows here and none in Word.

- An unset or zero band size now means no bands, as in Word. PartSet::of_cell
  takes row and column band sizes; column bands get a size of their own
  (col_band_size).
- Our banded built-in styles and new table styles set both sizes to one, and
  the writer writes them (and zero), so Word bands them too.
- The reader reads both sizes, zero included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 18:21:49 +07:00
Francesco Urbani afbfa43351 doc: a start override restarts only its own level (ECMA-376 17.9.27)
A num's startOverride for a level applies when that level of that num is first used, and only
there: applying all of them on the num's first use reset the shared counters' other levels and
renumbered every following chapter.
2026-10-20 22:56:04 +02:00
Mex e717ae4dc5 fix(doc): use decimal points for Cuban and Peruvian Spanish
Add the two missing regional exceptions and regression coverage for parsing, grouped numbers, formatting, and Spain controls.
2026-10-20 21:44:52 +02:00
NetterSilverandClaude Haiku 5.5 dfb9e1a851 Reject signs and repeated '#' in Rgb::parse
Found while testing crates/doc/src/props.rs:49-56 (Rgb::parse)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 17:37:31 +00:00
NetterSilverandClaude Haiku 5.5 a31743eb6d Map Windows-1255 byte 0xCA to U+05BA
Found while testing crates/doc/src/encoding.rs:82 (CP1255 table, entry for byte 0xCA)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 18:06:51 +02:00
LQRD 3d03c7cc7a M15: fix Russian ё ordering and decomposed Cyrillic collation 2026-10-20 19:07:31 +05:00
luisvacaandClaude Opus 5.5 fffd48c885 #2289: the first-page header comes before the default header in comment order
With Different First Page on, a section's default header was listed and reached by Next
before its first-page header, so Next went to page 2 before page 1. A section's header and
footer versions now go in the order of the first page each one shows on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 03:33:15 -06:00
luisvacaandClaude Opus 5.5 260014167d #2289: skip comments in header versions not in use and in linked text boxes' own text
A first-page or even-page header or footer is shown only while Different First Page or
Different Odd & Even is on, and a text box linked from another shows the first box's text
instead of its own. Comments in those stories were still listed and reached by Next and
Previous, and typing then went into text nobody sees. shown_stories now picks each
section's versions the way layout does and leaves out linked boxes' own text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:31:20 -06: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
Joey 156817d6ba Word signature lines stay signable after saving a .docx 2026-10-20 01:10:22 +02:00
Frédéric WeilandClaude Opus 5.5 912b98c833 Watermark: the text fills its shape's box, as Word's textpath does
Word's text watermark is a VML WordArt shape (`PowerPlusWaterMarkObject`)
whose `v:textpath fitshape` stretches the text over the shape's box (its
`style` width and height), centred on the margins and, when diagonal,
turned by `rotation:315`. WordCraft ignored the box: it drew the text
70 % of the page diagonal wide (half of it on screen), centred on the
page and along the page diagonal (55° on A4, not 45°). A "BROUILLON"
watermark in a 515 x 104 pt box came out about 1.4 times as large as in
Word.

- doc: `Watermark::size`, the shape's box (`None`: Word's default, half
  the page diagonal across, as high as the text's length makes it);
  `Watermark::frame` gives the box for a page, shared by the writer and
  the renderers.
- docx: the box is read from the shape's style and written back; a box
  equal to the default for the document's page reads as `None`, so a
  watermark made by Design > Watermark keeps following the page.
- pdf, render: the text's advance spans the box's width, its em the
  box's height, the em's foot (the font's win descent below the
  baseline) on the box's bottom; the box centred on the margins,
  turned 45° counterclockwise when diagonal.

Checked against Word for Microsoft 365 (ink bounds, pt, left top right
bottom; fonts here: Liberation Sans for Arial and Calibri, Liberation
Serif for Times New Roman):

  BROUILLON, Calibri, 515.4 x 104.1, 315°:
    Word 93.6 222.7 489.1 619.2; before 60.5 110.4 535.7 732.5;
    after 90.7 214.1 495.8 618.7
  SPECIMEN, Arial, 400 x 100, 315°:
    Word 136.3 261.6 455.0 580.3; before 66.7 108.5 539.0 727.7;
    after 137.8 255.4 454.6 573.1
  HXH, Arial, 300 x 100, flat: Word 158.9 378.2 436.3 449.8;
    before 105.1 353.8 490.1 489.6; after 158.9 380.2 435.8 449.3
  HXH, Times New Roman, 300 x 100, flat: Word 149.8 383.0 445.0 449.3;
    after 151.2 383.5 443.5 449.3
  COPIE, Calibri, 300 x 80, flat: Word 153.1 387.8 441.1 440.2;
    before 96.0 373.9 500.2 469.0; after 152.2 387.4 443.5 444.5

Tests: a watermark with a box of its own is written and read back with
it, Word's default box reads back as none; in the PDF, the text of a
300 x 80 pt watermark is 80 pt high, stretched across, starting at the
box's left edge on the margins' centre line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:31:10 +02: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
2304bf6ac6 Fix Paragraph::sentence_at at the first character of a sentence (#3105)
* Fix Paragraph::sentence_at at the first character of a sentence

Found while testing crates/doc/src/para.rs:1397-1427

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

* sentence_at: a terminator followed directly by text doesn't end the sentence at the caret

"Hello.World" at offset 6 gave an empty (6,6) range; only treat the caret as just past a
sentence end when the character at the caret is a space.

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

---------

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-19 12:45:25 -04:00
NetterSilverandClaude Haiku 5.5 517ba09250 Write large whole numbers without decimals in format_number (#3107)
Found while testing crates/doc/src/locale_number.rs:114

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-19 12:32:21 -04:00
Daniele MoriandClaude Opus 5.5 53296879db Floating objects are drawn in their stacking order (relativeHeight)
Word stacks floating objects by wp:anchor/@relativeHeight, not by the
order of their anchors in the paragraph. The reader ignored the
attribute, so a panel anchored after the text boxes it frames, but
lower in the stack, was drawn over them and hid their text.

- wordcraft-doc: Float gets a `z` (0 = none, drawn in document order).
- wordcraft-docx: it is read from relativeHeight and written back as
  read; an object without one gets the next order above, as before.
- wordcraft-layout: place_objects collects each object's items with
  its order and emits them lowest first (stable, so objects without an
  order keep the paragraph's).

Four round-trip tests compare whole floats after a save; saving now
gives objects without an order one, so those tests compare without it
(`unstacked`). The order itself is covered by its own round-trip test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 15:44:38 +02:00
dfgodvananddfgodvan 4b18b307be Selection rectangles walk only the paragraphs the range reaches (#2967)
Document::paths_between listed every paragraph of the story (every cell
paragraph of every table) and then kept those between the two paths, so each
selection_rects call cost the whole document. The canvas calls it every frame
for each Find reading highlight (up to 5,000), each content control frame,
Read Aloud and the hyperlink under the pointer. It now walks only the
blocks, rows and cells between the two paths: for a one-paragraph range in a
document of 26,000 paragraphs (four 1,500-row tables), 1.0 ms -> 2.6 us.

Co-authored-by: dfgodvan <180286157+dfgodvan@users.noreply.github.com>
2026-10-18 16:53:39 -04:00
luisvacaandClaude Opus 5.5 80f6ba6a25 #2289: comment navigation follows the stories a reader sees, in reading order
Review of the first commit found, and ui_shot runs confirmed, three bugs in it:
- Next Comment moved the caret into a removed header or a deleted
  footnote's text: a story nothing shows, so typing went nowhere visible.
- Next visited headers and footers by part id (creation order), so a
  footer made first came before the header.
- Comments in footnotes were claimed but untested.

Document::shown_stories lists the stories a reader sees, in reading order:
the body with the notes and text boxes it shows, then the headers and
footers the sections use with theirs. It reuses the reachable walk that
counted_stories uses. comment_list scans those stories (and returns at
once when the document has no comments: the balloons ask every frame), and
nav_comment orders by a story's place in that list instead of by Pos.
tools::all_stories is private again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:50:15 -06: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
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
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
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