* Layout: a picture lowered past its height lowers its line as far, as in Word
A picture lowered further than its own height had its lowering cut at that
height. Word keeps its top on the baseline but lowers the line as far as the
position says: a 6 pt picture lowered 30 pt makes a 30 pt line. Exact spacing
keeps the line's baseline. Closes the gap noted with #3984: all 156 measured
lines now match Word.
* Lowered pictures: an exact-spacing test; gaps and progress log
An exact-spacing line keeps its baseline when a picture is lowered past its
height (the test fails without the cap). Gap 4 and the progress log note the
change.
---------
Co-authored-by: Daniele Mori <Dinasty@hotmail.it>
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
* M14: keep native CLI input names after options
* docs(M14): clarify native CLI path option exceptions
Qualify the roadmap summary and history: text option values need Unicode, while run --file and run --script retain native paths. Addresses review4485129728. Documentation only; no CLI behavior changes.
* docs(M14): qualify Unicode values in format parity notes
Exclude the existing run --file and run --script native path operands from the text option Unicode requirement. Addresses review4485129728; documentation only.
* docs(M14): qualify Unicode values in CLI gap notes
Document the existing native path exceptions for run --file and run --script. Completes the three-file wording correction requested in review4485129728, without changing readiness estimates or CLI behavior.
---------
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
* RTF: honor the declared Unicode fallback count
* RTF: record declared Unicode fallback counts
* M12: count unknown RTF symbols in Unicode fallback
Address the unrecognized-control-symbol review finding in parse.rs. Each symbol consumes one Unicode fallback unit; outside fallback it remains ignored. Four additional actual-import cases cover uc0, uc1, uc2 and uc18. The uc2 regression fails before the fix (≤ rest versus ≤b rest). All 664 formats tests, scoped rustfmt and strict all-target formats Clippy pass in the exact-source isolated closure. Binary fallback remains separate in #4806.
* M12: count structural RTF words in Unicode fallback
Treat par, pard, cell and row like other control words while consuming declared Unicode fallback. Add actual import cases for those fallback units and a uc0 paragraph control. Scoped rustfmt passes; full validation is pending hosted CI.
* M12: describe RTF fallback units precisely
Address the review wording finding: the Unicode fallback count measures units, including control words and escaped symbols, rather than fixed-length bytes. Preserve every roadmap history and progress record.
* M12: count all RTF fallback control symbols
Consume non-hex control symbols before dispatch while Unicode fallback remains, covering escaped LF/CR and star without applying their side effects. Keep valid hex escapes on their four-byte path, and include revision-author text in the existing control-word guard. Add six actual body-import cases and two actual revision-author cases, including uc0 controls. Both regressions fail before the patch in the exact current closure; all 665 formats tests, scoped rustfmt and strict all-target formats Clippy pass afterward. Binary and invalid-hex handling remain separate. Full hosted gate will be checked on the draft PR.
* M12: preserve the roadmap final newline
Restore the trailing LF omitted by copying the Raw view. The roadmap now differs only by the requested fallback-unit wording; production code and tests are unchanged.
* M12: skip RTF info effects during Unicode fallback
Move the existing info_depth assignment after the existing fallback-control-word guard. A skipped info word inside a Unicode title fallback must not overwrite metadata depth and drop the following author. Preserve the binary and escaped-hex paths, other destination handling and uc0 effects. The supplied metadata import regresses before the move; all 667 formats tests, scoped rustfmt and strict all-target formats Clippy pass afterward. Regression coverage follows in this draft PR.
* M12: cover RTF fallback metadata depth
Add four actual RTF import cases asserting title, creator and body text: skipped info controls at uc9 and uc1 retain the following author; uc0 title and a real info group after body Unicode still work. The supplied uc9 case fails before the parser reorder with an empty creator instead of Alice. All 667 formats tests, scoped rustfmt and strict all-target formats Clippy pass in the exact c153 source closure plus this two-file follow-up. Full hosted CI will be checked on the draft PR.
---------
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
* fix(fields): quoted-argument backslash escapes and body PAGE in a cardinal-text section
A backslash inside a quoted field argument makes the next character literal, so TITLE "x \* Upper" shows x * Upper as Word does. A body PAGE field now uses the section's page number format (cardinal text shows words), as headers and footers already did.
* Fields: PAGE in a body table follows the section number format; parity docs
* fmt
* docs: clarify quoted field escape rule
* Fix page fields in fitted text boxes
* Move fitted cache test after layout helpers
---------
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
* M14: keep Page Setup margin and grid editors within their width (#5650)
Use the pinned egui DragValue clipping option for four margins and both grid counts. Canonical actual WordApp regression and 12 Page Setup controls pass; strict all-target UI Clippy and scoped rustfmt pass.
* M14: keep Page Setup paper-size editors within their width (#5650)
Apply the same bounded text editing to paper width and height while preserving their existing limits, units and speed. Actual Page Setup regression and existing controls pass.
* M14: regress Page Setup paste, blur and reopen widths (#5650)
Exercise all eight numeric fields through the actual WordApp harness. Baseline Bottom paste reproduced width growth from 354 to 2973 pt; the fixed canonical 12-test Page Setup suite passes. Private rendering hooks are excluded.
* M14: record bounded Page Setup number editors (#5650)
Add the focused UI fix to the progress and revision logs and status line. Readiness estimates remain unchanged.
* M14: note the focused Page Setup paste fix in gaps (#5650)
Record bounded numeric editing in the gap note, status and revision history; no ranked gap or readiness estimate changes.
* M14: document bounded Page Setup numeric input (#5650)
Update the UI parity note, status and revision history for long input scrolling inside the existing fields. Readiness estimates remain unchanged.
* M14: bound unfocused Page Setup margin values (#5650)
Keep the unfocused DragValue inside an allocated, clipped field without changing numeric parsing, units, speed or accepted values. Regress a finite long paste followed by Tab in all four margins. The actual baseline grew from 354 to 458.53125 pt after Tab; the canonical 13 Page Setup tests and scoped formatting checks pass, and the inspected fixed renders stay 354 pt. Hosted validation remains pending in draft PR #5696.
* M14: record unfocused Page Setup bounds (#5650)
Update the gap and UI parity notes for the accepted-value paste followed by Tab regression. Retain the existing progress history, value ranges and readiness estimates.
* M14: log the Page Setup blur regression (#5650)
Record the bounded unfocused margin display and accepted-value regression. Preserve every upstream progress entry and the previous validation history.
* M14: regress RTL margin re-entry (#5650)
Cover re-editing the visible portion of a wide blurred margin in the real Page Setup dialog under an asserted RTL fixture. Raw pointer events restore editing and accept a normal value; the existing thirteen tests remain unchanged. Fourteen Page Setup tests, package formatting, strict all-target UI Clippy and source-integrity checks passed. No production or dependency changes.
* ODT gap 19: a watermark change to a file is saved
A file's own page definitions were written back whatever happened to its
watermark, so one added, changed or removed in WordCraft was gone from the
saved file. The watermark now counts as part of the page setup, so a change
writes the page definitions from the model. A watermark with no text isn't
written, so it isn't a change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ODT gap 19: Different Odd & Even Pages changed in a file is saved
A file's own page definitions were written back whatever happened to this
setting, so the left pages' header stayed after it was turned off, and turning
it on did nothing. The setting now counts as part of the page setup, as the
watermark does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ODT tests: say what the watermark and odd/even tests check (gap 19)
Doc comments for CodeRabbit's docstring coverage check on this PR.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
* ODT gap 19: a table row that doesn't break across pages stays so
fo:keep-together on a table row wasn't read, so rows kept whole came back from
a save free to break across pages in LibreOffice. Read and write it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ODT: a row follows the default style's keep-together (gap 19)
A row whose style doesn't say took "free to break" instead of the default style's
setting. Found by CodeRabbit on this PR.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ODT: a row free to break stays so over a default that keeps rows together (gap 19)
Nothing was written for it, and the file's default row style stays, so a save took
that away.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
* ODT gap 19: a heading's text of another size keeps it
Every run in a heading, title or code paragraph lost its size to the style, so
a smaller word in a heading came back at the heading's size in LibreOffice
after a save. Only text at the style's size goes with the style.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ODT: a heading's text is sized against the heading (gap 19)
The comparison used the size outside the paragraph, so text stating the heading's
own size kept it through a style change. A size in percent was of 12 pt, not the
heading's. Found by CodeRabbit on this PR.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ODT: text in a heading style stating no size keeps its own (gap 19)
The run's size was compared with Standard's, so with Standard at 14 pt a 14 pt run lost its size and took WordCraft's Heading 1 size of 20 pt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ODT: a span stating no size has none in a heading stating none (gap 19)
The size used to work out a percent stayed on a span saying nothing of size, so a bold word in such a heading took Standard's size. It came in with the last commit here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ODT: a percent in a parentless heading is of the default size (gap 19)
It was of Standard's, which a style with no parent isn't based on: 50% over a 10 pt default and a 14 pt Standard came out 7 pt, not 5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ODT: a style's percent size is of what is under it (gap 19)
It was of 12 pt, whatever the parent or default: 50% over a 10 pt default made a 6 pt style, and a 5 pt span in it lost its size and showed at 6.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* ODT gap 19: a frame offering several picture formats shows one it can read
LibreOffice writes its own .svm metafile before a PNG of the same picture.
WordCraft took the first whatever it was, so the picture was missing, and gone
from the file once the paragraph was written from the model. Take the first
it can read, as the frame's order of preference means.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ODT: a replacement picture before its object is kept (gap 19)
A frame's picture WordCraft can't show was dropped before the object came, so a
save from the model lost the object's replacement. Found by CodeRabbit on this PR.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ODT: a readable picture after an unreadable replacement is shown and kept (gap 19)
With an unreadable replacement first, the readable picture after it was skipped: WordCraft drew a placeholder and a save from the model lost the picture. It is now shown and written after the replacement. A placeholder is still not written.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* #5710: the Print panel lists printers without asking their drivers
On Windows the printer list waited until every printer's driver said
whether it prints on both sides. A networked printer in power save can
hold that query for a long time, so the list stayed empty and Refresh
stayed unavailable. WordCraft never used the answer.
Discovery now uses craft-print's printer_queues, which lists the same
queues and default without asking any driver (storytold/craft-libs#618).
Printing still checks the job's options with the driver. Only the
craft-print pin moves; craft-ui doesn't depend on it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* #5710: the docs say what is proven, not that the sleeping printer is fixed
Review: the progress log and gap rows stated the reported outcome as
certain, but the sleeping network printer hasn't been retested. They now
say the driver query is removed and the reported printer awaits retest.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* #5710: craft-print pin moves to the merge of storytold/craft-libs#618
e653048 is craft-libs main's merge of #618; crates/print is identical
to the reviewed and tested head 81c2488.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* #5710: a print job waiting on its driver can be cancelled, and quitting doesn't wait for it
On Windows a print job asks the printer's driver for its capabilities
before it is sent, and a networked printer in power save can hold that
query for a long time. The Print page stayed locked until the driver
answered, and quitting waited for the job before saving preferences
(CodeRabbit on #5732).
Each job now carries a craft-print Cancel token. Cancel printing
(ui.printCancel) stops a job that hasn't started reaching the spooler,
so it is never sent, and frees the Print page with the settings kept;
a job already being sent completes, and the page says to cancel it
from the system's queue. Quitting cancels jobs still waiting and waits
only for jobs already being sent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* #5710: quitting cancels every waiting print job before it waits; Cancel asks the active job
Review: quitting cancelled and waited for jobs one by one, so a job left
waiting while an earlier one was being sent could start sending
meanwhile. Every job is now cancelled first, then only those already
being sent are waited for. Cancel printing asked every unfinished job,
so a job that had just been sent could be reported as cancelled and its
receipt lost; it now asks the job being submitted, which answers that it
was already sent.
The tests cover both orders, junk parameters for ui.printCancel, and the
kept printer list and status message.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* #5710: craft-print pin moves to storytold/craft-libs#622 for submit_cancellable
85c8ca1 is #622's head (craft-libs main e653048 plus the Cancel token);
it moves to #622's merge on craft-libs main before this merges.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* #5710: craft-print pin follows storytold/craft-libs#622 (230d522)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* #5710: pin craft-print to merged cancellation fix
* #5710: allow print cancellation after closing the document
* #5710: correct print-cancellation status date
* #5710: clarify when a print job cannot yet be cancelled in the queue
* #5710: isolate Windows print submissions in cancellable helper processes
* #5710: strengthen helper retry and crash-cleanup regressions
* #5710: erase helper inputs before driver work
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* WC6-06: preserve adjustRightInd in DOCX
* WC6-06: honor grid indent defaults and XML order
* Update lockfile for DOCX test dependency
* Format DOCX ordering assertion
* Keep main lockfile for paragraph property PR
* PR 5384: tighten grid indent docs and regression
* PR 5384: match paragraph check formatting
* M6: preserve numbered REF results during field updates
Adapt and validate the patch published in WordCraft #4533, retaining main's bounded numbering renderer and adding relative-context/cache guards.
Co-authored-by: Alyosha-dot-shop <218732667+Alyosha-dot-shop@users.noreply.github.com>
* M6: reuse bookmark lookup for numbered REF updates
* REF: use explicit imports for the workspace clippy gate
* #4609: adapt synthetic fixtures to shared document data
* #4609: checkpoint review fixes and isolated validation notes
* #4609: retain rendered REF labels and isolate relative context by list
---------
Co-authored-by: Alyosha-dot-shop <218732667+Alyosha-dot-shop@users.noreply.github.com>
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
* #3614: reuse paragraph-prefix lookups during ink discovery
* Update ink lookup status date (#3614)
---------
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>