Review on #2957, point 1. Both entry points already trim the whole name
before splitting it, and a space beside a period stays in its part,
which matches black-box observation of Acrobat and ISO 32000-2 12.7.4.2
(only a period is barred from a partial name). The test pins that down;
three mutants (no trim in add_field, no trim in set_props, untrimmed
empty-part check) each fail it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main now renames a field in the calculations that read it. After rebasing,
that runs for a dotted name too, which moves the field under new parents: the
sum and the script that read `a` read `Group.a`, and still compute after a
save and reopen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review on #2957: own_inherited wrote what the field inherits onto it before
check_place could refuse the move, so a refused move still changed the field.
What it inherits is now read first, counted as its own by the check, and
written only once the move is allowed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review on #2957: set_props took the field out of the tree before attach
checked the destination, so a refused move (a parent holding /MaxLen, say)
left it out of /Fields for a direct caller of the forms API. The read-only
check is now its own function, run before the field is detached.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review on #2957. The field list holds only terminal fields, so a parent
left empty by a move wasn't seen and a second field of its name could be
made beside it, by adding or by renaming. And a new field joining a parent
that holds /V, /DV or /MaxLen inherited them, with no neutral value of its
own to turn them off: such a parent now takes no field that doesn't hold
its own.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A field's own (partial) name can't contain a period (ISO 32000-2
§12.7.4.2), so Prepare a form refused MASTER.first. Acrobat reads such a
name as a full name: the field `first` under a parent field `MASTER`.
- add_field: a dotted name makes or joins the parent fields it names.
- set_props: a dotted name is the full name and moves the field there,
copying what it inherited onto it first; a plain name still renames
the field within its parent. Either way the new full name may not be
taken by, or hold or sit inside, another field.
- A field joining an existing parent doesn't take its Ff or Q.
- Field Properties and the Prepare a form name tags show the full name
instead of the last part.
- Names are capped at 32 parts; empty parts are refused.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every packaging script runs under bash, so [[ ]] is available. Name the positional
parameters of sha256, render and has, end env.sh's functions with an explicit return
(bare, so the exit status is unchanged), and give the build-label case a default arm.
vendor/ is third-party code kept close to upstream (vendor/README.md), so SonarCloud's
186 findings there are not ours to restyle. MD5 in crates/crypt is what ISO 32000's
standard security handler mandates, and RIPEMD-160 in crates/sign is a digest existing
signatures can name; both S4790 findings are scoped to those two files.
30 x 42 in is `na_wide-format_30x42in` in PWG 5101.1-2023 and the IANA
IPP registry (checked against both). `na_arch-e1_30x42in` was asked for
on the IPP list in 2021 but never registered. CUPS maps the new name to
the PPD's 30 x 42 in size (cupsfilter, synthetic PPD), and the paper
test pins it and fails on the old name.
Doc comments for bad, printers and two paper tests, for the review's
docstring check.
Review: storytold/pdfcraft#4161 (CodeRabbit).
ARCH A-E went out as arch_a_9x12in .. arch_e_36x48in; PWG 5101.1 names
them na_arch-a_9x12in .. na_arch-e_36x48in (ARCH E1's IANA-registered
na_arch-e1_30x42in already had the prefix). CUPS parses either from the
dimensions, which is why the cupsfilter check passed, but a driverless
printer may accept only the names it advertises. Re-checked the corrected
names with cupsfilter against the synthetic PPD.
The paper test now pins every size's exact name, and fails on the old
spelling. Doc comments for doc_print and PrintDraft::job.
Review: storytold/pdfcraft#4161 (CodeRabbit).
A CUPS job that names no paper gets the queue's PPD default (A4 on the
reporter's Xerox queue), whatever the sheets were laid out on. Two gaps
remained after #1583:
- cups_media had no name for 13 of the 21 PAPERS sizes (A6, ARCH A-E1,
ANSI C-E, A0-A2), so the Print dialog sent no media for them. They now
use PWG 5101.1 names (the IANA-registered na_arch-e1_30x42in for ARCH
E1), which carry their dimensions: CUPS feeds the driver's size of those
dimensions whatever the driver calls it, and driverless IPP printers use
them natively. Checked with cupsfilter against a synthetic PPD whose
sizes use vendor keywords (ARCHD, AnsiD, A0...): each name produced its
size's bounding box. The 8 sizes that already worked keep their PPD
keywords.
- doc_print to a printer (CLI run, MCP) sent no paper at all. It now
resolves the paper to its PAPERS index and sends the same media option
as the dialog, after the driver options. The job is built in spool_job
so it can be tested without printing.
print::media_option is the one place both get the option from. Both new
tests were seen failing without the fix. The macOS tray half of #3752
(Auto Select instead of the PPD's default tray) is a craft-print change.
Extraction walked the name tree again with a fresh key budget, so keys
the listing had left out could fill it and a listed embedded file came
back as not found. The lookup compares each key with the one wanted and
keeps none, so it needs no budget; a key object or /Names array that
several places reference is converted once.
A kept web address or attachment text spent only its converted length,
so a long raw value that trimmed short was converted in full for every
entry sharing it. A kept conversion now spends the longer of its raw
and converted lengths.
Review on #4157 (CodeRabbit): the symbolic branch of EmbeddedKind::map_code is taken whenever the
Nonsymbolic flag is not set; it doesn't look at /Encoding.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hayro-interpret's map_code tried a symbolic font's cmap subtables in the order the font lists
them, by platform ID, so Macintosh (1, 0) came before Windows (3, 0). ISO 32000-2 §9.6.5.4
gives (3, 0) first and (1, 0) only otherwise. SAS 9.4 embeds AMT fonts whose (1, 0) table is
wrong, so "8" drew as "p", "+" as "V", and "1" and "%" not at all.
The Windows (3, 0)/(3, 1) records are now tried first; Macintosh and Unicode ones still serve
codes those leave out. The test font is built in memory.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Quitting with several unsaved documents moves from one question to the next
without the prompt closing, so a question that opened in the background after
one the user saw asked for nothing (review feedback on #4155).
close_and_continue now marks the next document's question as new. A request
that still stands carries over to it instead of being sent again.
Quitting from the Dock menu (or logging out, or an agent's ui.quit) while
another app is in front opens "Save changes?" in a window the user can't see,
so it looked as if PdfCraft hadn't quit. The prompt now sends a critical
user-attention request on the frame it opens while the window isn't focused:
the Dock icon bounces until PdfCraft is active, the Windows taskbar button
flashes until the window is in front, and X11 sets the urgency hint. Coming
back, or answering, sends Reset. This is what AppKit does by itself when an
inactive app presents a modal panel; PdfCraft's prompt is drawn by egui, so
AppKit never sees it.
The embedded-files name tree copied every key, and an attachment
without a file name copied its key again as the name, so many entries
sharing one long key string multiplied it. Keys, and a key kept again
as the name, now spend the 16 MiB link and attachment text budget; an
embedded file whose key does not fit is not listed.
An annotation attachment's /Contents was read and charged to the text
budget before the file specification's /UF or /F, which then named the
attachment, so the discarded text could leave a later web address
unlisted. /Contents is now read only when neither name is there.
A web address or attachment text that converted to more than the budget
left spent nothing, so every link or attachment sharing it converted it
again. A conversion that comes out too long now spends the raw length,
and so does attachment text that trims to nothing.
The fixture's image stream held six bytes under /Length 4, and the test
only checked that the picture was missing at a zero budget, which a
picture that could not be prepared also passes. The stream is four
bytes, and the picture is first shown to export at a 1 MiB budget.