- Grey out restricted page context-menu actions (editing, annotation, assembly, printing) on protected PDFs.
- Group installed fonts by family with search, max height, and scroll area in the format panel. Prevent row cutoff in font dropdown.
- Document Unicode character conversion behavior for superscript and subscript in parity notes.
- Revert unintended clipboard-win bump in Cargo.lock back to 5.4.1.
When undoing or redoing an edit (such as Arrange), re-resolve any active image selection to match the same image's XObject, name, and position rather than leaving the selection stuck on the old index (which could point to another image). If ambiguous or no longer present, clear the selection.
Three holes in the shared text box's history:
- Formatting applied with the paragraph open left typing_from as it
was, so when the format left the text unchanged the box kept its
history, and Redo put typing undone before the format back on top of
it. applied() now resets typing_from, so the next claim clears it.
- Undo or Redo from the menu in the same frame as a tab switch ran
before the box was drawn, on the history of the other tab's box: Undo
put tab B's text into tab A's box, and Redo put A's undone typing into
B's. undo_in_page_box and redo_in_page_box now make the box claim the
text box first (claim_typing), as drawing it does.
- A box new to the text box cleared only the last box's history and
kept its caret and selection; it now starts from a default state.
claim_typing on LineEditor and TextDraft is now the one way a box takes
the text box, for drawing and for the menu.
Carried from #4179 (aa326f37). On this branch the rows' alignments by
text restart with the history, so a Redo past a format can't bring
back an alignment from before it.
Three holes in the shared text box's history:
- Formatting applied with the paragraph open left typing_from as it
was, so when the format left the text unchanged the box kept its
history, and Redo put typing undone before the format back on top of
it. applied() now resets typing_from, so the next claim clears it.
- Undo or Redo from the menu in the same frame as a tab switch ran
before the box was drawn, on the history of the other tab's box: Undo
put tab B's text into tab A's box, and Redo put A's undone typing into
B's. undo_in_page_box and redo_in_page_box now make the box claim the
text box first (claim_typing), as drawing it does.
- A box new to the text box cleared only the last box's history and
kept its caret and selection; it now starts from a default state.
claim_typing on LineEditor and TextDraft is now the one way a box takes
the text box, for drawing and for the menu.
Prepare Form deletes the selected widget: one radio button of a group or
one copy of a duplicated field, as Acrobat does; a field's last widget
takes the field with it. The widget leaves its page, the field's /Kids
and /CO; a per-widget /Opt loses its entry, and a group that was on only
through it turns Off. form_delete_field takes an optional widget.
UserRegex::find now returns an error instead of silently stopping at
10,000 matches, so redact_mark cannot report success while later matches
stay readable. Empty-match detection probes several short texts so
patterns like \b are refused with the clear message. Schema notes that
the 1024 limit is in bytes.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The tabs share one text box, and its Undo history was cleared whenever
another document's box took it: opening a paragraph in tab B wiped tab
A's typing steps, so Edit ▸ Undo back in A found none and closed A's
paragraph instead of taking the typing back. The box being left now
keeps a copy of its history and caret aside, under its document, and
the same box gets it back on its return; a box new to the text box
still starts with none, so typing still never reaches another tab. The
copy is a deep one: a state's history is shared between its clones.
Carried from #4179 (abc378c0). On this branch the rows' alignments by
text go aside and come back with the history, so Undo after the trip
still restores a deleted row's alignment.
The tabs share one text box, and its Undo history was cleared whenever
another document's box took it: opening a paragraph in tab B wiped tab
A's typing steps, so Edit ▸ Undo back in A found none and closed A's
paragraph instead of taking the typing back. The box being left now
keeps a copy of its history and caret aside, under its document, and
the same box gets it back on its return; a box new to the text box
still starts with none, so typing still never reaches another tab. The
copy is a deep one: a state's history is shared between its clones.
Review of #2815 (FredApps): two ways the detector took real content for a
page's own white backdrop and replaced it by default.
- A `gs` sets only the keys its dictionary has, but each one replaced the
whole opacity decision and read every key it left out as its default,
so `/Transparent gs /LineOnly gs 1 g ... re f` (ca 0.5, then only a
line width) counted as opaque. Fill alpha, soft mask and blend mode are
now kept one by one, through `gs` and `q`/`Q`.
- A transfer function was never read: TR or TR2 mapping 1 to 0 paints
`1 g` black, and the fill was still replaced. The transfer function is
tracked too, TR2 over TR in the same dictionary, and only /Identity
(and /Default for TR2) counts; anything else leaves the fill alone.
Tests: nine graphics states that must keep the fill (each also checks Add
Background leaves the content as it was) and nine that still find the
backdrop (keys set back, TR2 /Default over a TR function, q/Q restoring),
plus an end-to-end render of the reviewer's translucent case under a red
background. All the keep cases fail on the code before this change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A nonempty aligns counted as a style change, so every row of the
paragraph was rebuilt from the text state: rows left unselected lost
their source operators, and with TJ word gaps their words moved by
about a point and a half while the row's outer width stayed the same.
aligns no longer makes an edit non-plain; a row whose own line has an
alignment override is rewritten, and the others keep their operators.
egui's typing history keeps only text and caret, so Undo bringing back
a deleted row or line (added text, or a paragraph) gave it the
alignment of the row before it, and finishing the box could save that.
Each page box now keeps the texts it has shown through its own typing,
with every row's alignment then (follow_typing): Undo or Redo back to
one of them restores those alignments, and a new text follows the edit
with remap. An alignment picked since makes the older ones stale; they
are dropped, so Undo never takes back a pick. The record is cleared
with the box's typing history and holds 100 texts, as egui's does. It
covers typing, the keys and the menu's Undo and Redo.
On this branch the two-tab test also runs the menu's Redo in the copy,
where the box, with no Redo of its own, passes the step on and closes;
that step no longer requires the editor to stay open.
Also carries #4179's stronger two-tab test (dd47c4f9): the copy's
paragraph must be open before the key Redo and after it.
Edit ▸ Undo with typing in a paragraph or added text box that the page
doesn't have yet applied the typing (a new edit, which dropped the
document's waiting Redo), closed the box and undid the typing all at
once; the key takes it back a step at a time in the box. Menu Undo now
goes to the box first, as Redo does, and is enabled while the box holds
such typing. Undo and Redo share typing_step for the box's own history.
Main took integration batch 6 (#4566). Conflict in edit_text_ui.rs: the
overlay keeps this PR's view_id with main's interact_pos comment. The
two TextDraft literals from #4441's tests take selection and
typing_from.
CodeRabbit on #4560:
- The bookmark titles are the document's text, so the edit now needs
copying permission as well as assembly, and Document::text_styles (the
dialog's samples) is empty when copying is withheld; the automation
text_styles tool already checked it.
- A heading went on to the next row whenever it was close below in the
same style, so same-style headings in two columns on staggered rows ran
together into one bookmark. A line continues a heading only when it lies
under it.
- Lines found their style by a scan over every style so far; they are now
indexed by font, weight, slant and quarter-point size, so a page with
thousands of styles no longer makes the scan quadratic.
Regression tests for the first two (each fails without its fix).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LymhVaGZCWwB9HNEbLzeMM
Main took integration batch 6 (#4566). Conflict in edit_text_ui.rs: the
overlay keeps this PR's view_id and main's switch to interact_pos for
clicks outside the document.
Bookmark options > New bookmarks from text styles... lists the styles the
document's text is set in (font without its subset tag, the size shown,
bold, italic, how many lines, a sample), the largest first, and takes one
style per bookmark level. Every line in a level's style becomes a
bookmark of that level under a new first "Untitled" bookmark, as from
structure; a heading set on several rows is one bookmark, and each goes
to the top of its heading.
The detection lives in engine::text_style_bookmarks on top of
edit::text_lines, reading each page top to bottom then left to right, so
two headings on one row stay two. text_styles and
bookmark_from_text_styles reach it headlessly, and the command
bookmark.from_text_styles opens the dialog. OutlineEntry gets an
optional top for the /XYZ destination; structure bookmarks keep theirs.
If the copy's editor had closed before or during Redo, the check for the
other tab's typing passed on an empty text. It now requires the editor
to be open before Redo and after it.
Edit ▸ Undo with typing in a paragraph or added text box that the page
doesn't have yet applied the typing (a new edit, which dropped the
document's waiting Redo), closed the box and undid the typing all at
once; the key takes it back a step at a time in the box. Menu Undo now
goes to the box first, as Redo does, and is enabled while the box holds
such typing. Undo and Redo share typing_step for the box's own history.
The dialog previews a colour as a tint of the page's thumbnail (main's #3009). It tinted every
page, so with Replace unticked a page that keeps its own white backdrop previewed coloured,
though OK leaves it white. A page a picture covers (a scan) previewed coloured too.
background_tint() now shows no colour where the page will still hide the background after OK:
a scan, or a white backdrop with Replace unticked. It reads the page from the dialog's backdrop
check (BackdropCheck::found, for the current version of the document only); a page the check
hasn't reached yet previews coloured, as before.
Tests, both seen failing with the fix reverted:
- marks_ui::tests::the_preview_shows_a_background_only_where_ok_lets_it_show (the rule);
- it::marks::the_background_preview_follows_the_replace_checkbox (what the dialog paints, per
page, ticked and unticked).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>