In Edit text & images, a paragraph's width handle is drawn centred on its
box's edge, and the edge grabs from up to 6 px outside the box. Object
selection sees a press first, though, and handed it to the paragraph tool only
on the box itself. A press on the outer half of the handle started an area
selection instead: its rectangle followed the pointer like a resized frame,
and on release the paragraph kept its old width and the text never moved.
Object selection now also leaves a press on a closed paragraph's edge grip to
the paragraph tool, through edit_text_ui::grabs_edge. That uses the same edge
test, box and upright-page rule as the tool itself, so the two can't drift
apart. The rewrap is the existing EditTextBlock with a width, so undo, redo
and save are unchanged.
Fixes#2276
Word count, untagged content, image crop, print as image, signature labels, full screen prompt and the other new interface strings. th.tsv now covers every key any bundled catalog translates (2,672).
A clean-room Thai catalog covering every key the bundled catalogs translate, its LANGUAGES row (one plural form) and Thai month and weekday names in DATE_LANGUAGES.
Taiwan, Japan and China write dates year first with slashes (Windows'
zh-TW short date is yyyy/M/d), and neither the Fill & Sign presets nor
the header and footer date tokens offered it. Both now have yyyy/mm/dd
and yyyy/m/d. The header and footer list gains them at its end, since
its selection is an index.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
eframe stores the window's size and place just before App::save. A
minimized window has none: Windows reports 0 x 0 at (-32000, -32000),
and the next start opened at egui's 64-point floor in the screen's
corner (seen on a 6K display at 225%: a 144 x 206 px window). While the
window is minimized the app now puts back the last settings it was
shown with (or none), and a window that opens at that floor from
settings saved before this fix is given a usable size.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
Prepare a form ▸ Detect form fields places each field on a line or box the
page already draws, but every new widget got a grey /MK /BC and an opaque
white /MK /BG, so the fill hid the printed form underneath. Detected fields
now clear both in the same undoable step; fields drawn by hand keep the
defaults.
Refs #294, #2831.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first fix dropped a stale pick while painting the next frame. The window only redraws on
the next input, so after deleting a picture in Edit text & images its highlight stayed on screen
until the user clicked. Clear the pick in apply_edit, in the same step as the edit, and ask for a
repaint. drop_stale stays for the paths that change the document without apply_edit (Undo, Redo).
An edit-level test checks the pick right after apply_edit with no frame in between; it fails
without the change. The earlier one-frame test could not tell, the test harness redraws more
often than the app does.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Review of #2625: the test checked the argument reveal_command builds but
not how it is passed, so it still passed with raw_arg replaced by args.
The process is now built by reveal_process, and a Windows test runs it
on `cmd /c echo`, which prints its command line back: with Rust's own
quoting the argument comes back wrapped in quotes with the inner ones
escaped, and the test fails.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
Table detection took a sentence whose link was set in another colour
and font, split into blocks that run on into each other, for two table
columns, and took a paragraph's lines, whose box overlaps the line
before, for a cell beside it. The table it built put the paragraph's
first line in one cell, a fragment of the link in another, and dropped
the paragraph's later lines. A block that starts where another on the
same line ends now adds no column of its own, and a row whose cells
overlap is not a table row; a superscript beside a number stays in its
table.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
With the Select tool a click picks a picture and draws a blue highlight over it. The pick was
only cleared by Escape, a drag or another click. Picking a picture, then entering Edit text &
images and deleting it left the highlight on the empty spot, with nothing left to click to
remove it.
The pick now remembers the document's edit generation and is dropped once the document has been
edited since (a delete, a move, Undo), the same condition under which the copy shortcut already
refused it as stale.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Read mode hides the tools, not the navigation panes, as Acrobat's does
and as switch_mode already says, but the floating quick toolbar was
still drawn over the page there. It is now hidden in Read mode, and
entering Read mode puts the current tool down (back to Select), so no
markup tool stays active without a toolbar to show it. The right rail,
the page navigation and the V/H shortcuts are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A file edited after it was made PDF/A or PDF/X can keep claiming a
standard it no longer meets. organize::remove_standard_id removes the
claim: the pdfaid: XMP properties for PDF/A, or GTS_PDFXVersion and
GTS_PDFXConformance in the document information and as pdfxid: XMP
properties for PDF/X. Output intents and other claims (PDF/UA) stay.
The XMP is edited with the packet editor Document Properties already
uses (sync_info and the new remove_properties share its read and write),
so the rest of the packet stays byte for byte and unsafe packets are left
alone. It is one undoable edit, in Standards ▸ PDF/A as a button worded
like its undo label, and the standards_remove_id tool (pdfa or pdfx).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main solved this branch's problem on its own: #1712 replaced the two
duplicated catalog paragraphs with one current paragraph that covers
every shipped language. Two and a half hours later #2320, branched
before that, added its two copies back, so main carries three again.
Keep #1712's paragraph exactly as main wrote it and delete only the two
stale copies, so this branch no longer rewords anything.
Docs only, no code.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
No embedded interface face has Hangul, and the installed fallbacks covered Arabic, Devanagari,
Telugu, Sinhala, Tamil and (for a Chinese interface) Han only, so a Korean file name in a tab,
the title bar or the bookmarks panel drew as boxes (#2747, #407, #1043).
hangul_fallback() adds the first installed Korean face that has the whole syllable block, like
the Telugu and Tamil fallbacks, and it ends every family next to them. The probe is U+D7A3 (힣),
the last of the 11,172 modern syllables: Droid Sans Fallback has 가 but few other syllables, so
a 가 probe would accept a face that still draws boxes. Candidates: NanumGothic, UnDotum,
Baekmuk Dotum (Linux), Malgun Gothic, Gulim, Batang (Windows), Apple SD Gothic Neo, AppleGothic
(macOS). Noto CJK and Source Han are left out, as for Chinese (AGENTS.md §1.1).
PDFCRAFT_SYSTEM_FONTS=0 turns it off like the others.
Test: system_fallback_covers_hangul (skips on Linux without an installed Korean face).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNjF2Pc6JWeHW1UVPK8uVg