* #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>
* Table formulas: read the Panamanian balboa B/. in numbers
Word's table formula and sort number reader ignores a currency sign or short currency word around a number; the balboa's B/. was not in the list. Add it as a whitespace-delimited sign, as Word reads it: B/. 1,250.50 and 1,250.50 B/. are numbers, while B/.1,250.50 and B/ 1,250.50 are not. Tested in the locale reader and through =SUM(ABOVE); the localization parity doc records the behaviour.
* Table formulas: read the balboa cell in the document's language
The formula test summed a B/. cell through ev, which supplies no document
or language, so a regression in locale selection could pass. Evaluate
=SUM(ABOVE) with a document whose default text is es-PA and a pl-PL
editing language: 1,250.50 is a number under es-PA and not under pl-PL,
so the assertion fails if the formula stops consulting the cell's
language. The converse case reads B/. 1 250,50 from a pl-PL document with
an en-US fallback, which English alone cannot parse.
* docs: close the parenthesis in the localization-parity change note (#3546)
---------
Co-authored-by: Francisco Herrera <14956584+alosslessdev@users.noreply.github.com>
Co-authored-by: FredApps <FredApps@users.noreply.github.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
The transports, the message types and the origin checks come from the shared crate (storytold/craft-libs#420); WordCraft keeps the host save and dirty hooks, the saveAs rule, the open size limit and the author.
data-host="page" on the canvas opts a page that loads the module into its own document into the host bridge. The ?host=parent messages travel as non-bubbling CustomEvents on the canvas; the bridge holds a Transport (Parent or Page) with one send, and the open, save, dirty, ready and failure handling is shared. ?host=parent is checked first and unchanged, including no bridge for an unframed page. The hosting guide documents both modes.
* docbin: a field's cached result keeps its formatting per run, not per character (#5477)
The result was a Vec<(char, CharProps)>: 365 bytes per character, 1.44 GB
at peak for a 4 MB file with one field. It is now a String plus a run
list that gains an entry only when the formatting changes (25 MB peak
for the same file). Output is unchanged.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* docbin: show the objects when the field-result test fails
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
`comment_export_discovery_scales_with_unrelated_markers` timed `notes` on 2,000 and 16,000
markers through /proc/thread-self/schedstat. That count moves only at a scheduler tick or switch,
so a 17 µs baseline read as nothing or a whole tick, and gate failed on linear code (58.68x on
PR #3228's run 41932894607). As #5608 did for the balloon anchors, the test now counts the
characters the walk visits (`wordcraft_doc::work`): 4,010 -> 32,010 steps, 8.0x, every run. A
prefix scan per marker injected into `notes` counts 63.9x and fails it.
`work::steps` becomes public so a crate that walks a paragraph's text itself can count it; outside
tests it is still nothing.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Alt codes type their character in Find and other text boxes (#4403)
Alt+numpad codes worked only on the page. In a text box (Find what,
Replace with, a dialog's field) the digits were typed instead on Linux,
which sends their text with Alt held; on Windows the box got only what
the system composes, a byte for a code above 255.
A pass before the frame is drawn now gives the focused text box the
same codes as the page: the digits' text is dropped, letting go of Alt
types the character the code names in the same code pages, and a
platform's own composed character is not typed twice (up to 255 the
system's replaces ours, as on the page).
* Alt codes in text boxes: letting go of Alt ends the digits' text
The flag that drops a digit's own text stayed set when no text came
for the last digit, so the first text after the release was lost: on
Windows the system's composed character for a code we name no
character for (CodeRabbit), and on Linux whatever followed a frame
whose digits sent no text (CI). A digit's text comes with its key,
before Alt is let go, so the release now clears the flag everywhere.
* docbin: cap paragraph and cell marks, keep the table context only for table marks (#5476)
The walk budget counts characters, not paragraphs, so a file made of
paragraph marks grew memory about 2,000 times faster than its size
(4 MB of marks: 9.4 s, 8.4 GB peak). Marks now draw on one document-wide
cap (2,000,000, all stories together); past it the read returns
DocbinError::Limit. A ParaOut no longer embeds the 296-byte RowInfo of a
table mark: it is an optional box, present only for table marks.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* docbin: say what the paragraph cap bounds; name the budget test for what it checks
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* docbin: refuse an exhausted paragraph budget before assembling a story (review point)
CodeRabbit pointed out that the header, footnote, endnote and text box walks
assembled their partial paragraph lists before the budget check, a transient
memory peak. They now share story_blocks, which checks first.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* docbin: test that the paragraph cap is shared by the body and a footnote (review nitpick)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* docbin test: review fixes (assert empty pairs, comment wording)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* Content controls: a press on the drop-down list button no longer moves the caret (#5389)
The list button hangs over whatever follows the control. The canvas put the
caret under the pointer first, which left the control, and the list closed in
the frame it opened. A press on the button now skips the caret move.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Content controls: only a press that began on the list button skips the caret move (#5389)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Content controls: a press and release in one frame, and a table tool, no longer hit the button guard (review points)
CodeRabbit pointed out that egui clears press_origin when a press and its
release arrive in the same frame, so the caret still moved off the control and
closed the list; the press is now also read from the frame's events. It also
pointed out that the guard ran before the table pen, so a stroke could not
start over the button; the guard is skipped while a table tool is on.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Content controls: feed the same-frame press and release as one frame in the test
Harness::event runs one frame per event, so the earlier version of the test did
not exercise the single-frame case.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* 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>
* Mini toolbar: hovering a formatting button previews it on the selection (#4664)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Keep mini toolbar stable during alignment preview
* Track live mini toolbar anchor during preview
* Mini toolbar: hovering a font, size, highlight or font colour previews it (#4664)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Mini toolbar preview: the page holds its scroll position (#4664)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Mini toolbar: hovering the highlight and font colour buttons previews their colour (#4664)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Mini toolbar: the font list and colour menus mark the choice in effect (#4664)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Skip hover previews in context toolbar
* Pass preview mode in toolbar test
* Font list: a picked family keeps its place until the list next opens (#4664)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Font and size lists close when an entry is picked (#4664)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Mini toolbar: a clicked button holds its preview until the pointer leaves (#4664)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Mini toolbar: a button already on does not preview (#4664)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Alignment buttons follow the paragraph a selection covers; a toggle previews its undo on return (#4664)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Font list: a recent family is marked as chosen in Recently Used Fonts only (#4664)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Fluorine <joseph.anglada92@gmail.com>
* #3614: reuse paragraph-prefix lookups during ink discovery
* Update ink lookup status date (#3614)
---------
Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
* Let every credits column be dragged, and refit changed tables
The last column was egui's remainder column, which has no drag handle, so
it could only be resized from the edge before it. It is now an ordinary
column with its own handle.
A table keeps its column widths, so switching to a longer name left the
Name column at its old width and clipped the text. The table now goes
back to the opening fit whenever that fit changes: a longer widest cell
or a resized window. Dragged widths are dropped at that point.
fit_widths could overflow the room when one column hit the minimum,
because the other columns did not take up its share. Columns now give
way in proportion to their width above the minimum.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Refit credits tables on what they measure, not the fitted widths
Comparing the fitted widths missed the case it was meant for. Name is the
only growing column, so a longer name takes its extra width from the
spare room and the fit comes out the same: a dragged Name width stayed,
clipping the longer name.
It could also drop dragged widths by accident. The fit comes from the
available width inside the scroll area, which scrolling can nudge, so
scrolling a widened table could reset it.
The table now compares the natural widths and the clip rect's width,
which scrolling does not move.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The page the section before ends on is finished with its own margins and
footnote separators before the starting section's replace them, so the
footnotes pending on it are placed where the page they sit on says.
Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com>
* docx: keep a paragraph's text alignment
w:textAlignment (ECMA-376 17.3.1.39) was not read, so a save dropped it. Word sizes a line by it when a
list's bullet is larger than the text: without it, those lines grow and every page after them moves.
ParaProps gains text_alignment, read and carried through styles, and written back after w:jc. Kept for
the file only; the layout does not use it yet.
* contributors: add entropybeater
---------
Co-authored-by: Brian <255903314+entropybeater@users.noreply.github.com>
Spelling as you type now notes that a web or e-mail address after a
no-break, narrow no-break (U+202F), figure (U+2007) or ideographic space
is not marked while Ignore web and file addresses is on, as
address_after_a_wide_space_is_an_internet_token in craft-proof checks.
* doc, docx: keep the compound border lines
The nine thin and thick compound lines (thinThickSmallGap to thinThickThinLargeGap, ECMA-376 17.18.2)
were read as a single line and written back as one, on paragraphs, tables, cells and pages. BorderStyle
gains them; they are written back by name and drawn as a single line of the border's width, as before.
RTF export and import carry them too (the importer read four of them as double).
* contributors: add entropybeater
---------
Co-authored-by: Brian <255903314+entropybeater@users.noreply.github.com>
metafile_size() parsed the whole metafile, decoding every bitmap and building every path, to
read two numbers at picture insert and replace. A new wordcraft_metafile::size reads the frame
from the EMF header or the placeable WMF header, and falls back to the full parse for every
other file (plain WMF, an EMF without a usable frame, a file with no records), so it returns
what parse would. For an EMF with one 8000x5000 1 bpp bitmap the size now costs well under a
microsecond instead of about 280 ms.
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>