Commit Graph

251 Commits

Author SHA1 Message Date
Dejan Port b60d641083 i18n: add Serbian (Latin script) interface translations
Adds Language::Sr ("sr"), following the existing per-language module
pattern (crates/ui-egui/src/i18n/<lang>.rs with a translate(text) ->
Option<&'static str>). All 381 strings in the JAPANESE master list are
covered, verified by the existing completeness test.

Latin script (sr-Latn), ekavian dialect — the common default for
digital/software Serbian. Cyrillic (sr-Cyrl) could follow as a
separate variant if wanted; this keeps the PR to one script, matching
how every other language here is a single variant.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-12 02:14:17 +02:00
Brandon Thomas 3b19cb80e6 Merge pull request #412 from jsymes21-byte/keytips-table-refactor
Keytips: full Excel sequential Alt table — 364 sequences, badges on every control, generated tests (fixes #33, #49)

# Conflicts:
#	contributors/people.toml
2026-10-11 18:06:06 -04:00
Brandon Thomas 63e60de76c Merge pull request #413 from pechnikov2026-star/i18n-fr
i18n: add French (fr) interface
2026-10-11 18:06:05 -04:00
Brandon Thomas a34fe4a7af Merge pull request #436 from LloydNicholson/feat/open-encrypted
Open password-encrypted workbooks (Agile and Standard encryption) (#11)

# Conflicts:
#	ROADMAP.md
#	docs/file-format-parity.md
#	docs/gaps.md
#	docs/target-app-parity.md
2026-10-11 18:06:04 -04:00
Brandon Thomas f170b89a92 Merge pull request #420 from neilcawse/fix/structref
Formulas: trim-reference operators (A1:.E10, A1.:E10, A1.:.E10); read unbracketed [[#This Row],Col]

# Conflicts:
#	docs/function-parity.md
#	docs/gaps.md
2026-10-11 18:05:40 -04:00
Brandon Thomas a96f19f02b Merge pull request #409 from shrshk/fix/formula-arg-count-363
Refuse formulas with the wrong argument count on entry (#363)
2026-10-11 18:05:18 -04:00
Brandon Thomas e6773dac3c Merge pull request #433 from derechopiano/fix/autofit-filter-button-spacing
Fix AutoFit width for table and AutoFilter dropdowns
2026-10-11 18:05:13 -04:00
Fabio Lussi dbc04ddae0 Rotated text follows the cell's alignment (Fixes #435)
Text turned by an angle was drawn at a fixed anchor (bottom-left for upward,
top-left for downward text) and ignored the horizontal and vertical alignment,
so upright text with Middle Align in a tall merged cell sat at the bottom.

rotated_text_pos places the turned galley's bounding box in the cell per the
alignment, then derives the TextShape anchor from it. General/Bottom keep the
old placement for upright text.

Fixes #435

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 00:00:56 +02:00
lloyd 312b4c056e UI: password dialog fixes from review (#11)
OK on the untouched field says the password is incorrect instead of
asking again; the Backstage closes once the workbook opens; app.open on
the control channel takes a password and never opens the dialog. Control
protocol docs cover file.open {password}.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 23:29:28 +02:00
lloyd c882d169ff UI: ask for the password of an encrypted workbook (#11)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 23:29:28 +02:00
derechopiano 1a6c864235 home.autofitColumnWidth: reserve filter dropdown space 2026-10-11 22:09:51 +01:00
James 7a2361de7f T10: resolve conflicts with main; new upstream commands go live (slicer, pivot chart, forecast sheet, show comments) 2026-10-11 23:54:15 +03:00
James 8e7e247589 Resolve James's real-Excel checks: drop QAT/Backstage and nonexistent View sequences; arrow navigation in the colour palette
- Side-by-side and synchronous-scrolling keytips removed (do not exist in
  James's Excel); Copy H,C / Spelling R,S / Fill H,H / Sparklines N,Z,K
  confirmed already correct
- QAT digits 0-9 and Backstage account/home/options + legacy Share Workbook
  sequences dropped (no meaningful GridCraft target; not left as trash)
- Colour palette (H,H fill and F,C font colour): arrow keys move a highlight
  through the swatches, Enter applies; key events are stripped so the grid
  behind the popup does not react
2026-10-11 23:40:23 +03:00
James d2a691aea8 Fix combo navigation edge cases and wire Page Layout Sheet Options badges
- Arrows/Enter while a keytip combo is open now navigate the list instead
  of moving the filter field's text cursor (events stripped from TextEdit)
- Reopening a combo resets the filter: the reset frame requests a repaint
  so the stale filtered list never lingers on screen
- Page Layout Sheet Options: Gridlines View/Print and Headings View/Print
  checkboxes painted with VG/PG/VH/PH badges and keytip toggles
- Background rebound from PG to PGB (Excel's Page Setup GB badge); PG is
  no longer terminal
2026-10-11 23:40:23 +03:00
James 7ba871c6f2 Excel-style combo navigation (type to filter, arrows to move) and complete tab badges
- editable_combo: every dropdown keytip opens with a filter field focused;
  typing narrows the list, Up/Down move the highlight (wrapping), Enter or
  click applies, custom text applies where valid (font size). Fixes arrows
  and typing in ALT+H FF/FS/N.
- Audited all 54 painted ribbon ids against the table: real mismatches fixed
  (Data Sort/Text-to-Columns/Remove-Duplicates/Subtotal, Review Spelling/
  Accessibility/New Comment/Notes, View Zoom/Freeze, Formulas Insert Function/
  Name Manager/Define Name/Use-in-Formula/Error Checking/Evaluate, Insert Link/
  Comment/Header-Footer/Sparklines, Home Protect Sheet).
- keytips.json: dialog kind for real dialog openers; control kind for the 6
  chart-type buttons, 7 formula-category buttons, and Orientation (HFQ added,
  was missing); M-family restructured to Excel semantics (ML/MT/ME/MO/MG/MQ
  fire directly, MI1 opens Financial) with 14 unreachable children dropped;
  383 entries total.
2026-10-11 23:40:23 +03:00
James cbd9bb51c6 Dropdown keytips open their controls instead of firing empty commands; complete View badges
- New Action::Control routes a keytip to its ribbon control (popup/dropdown
  open, checkbox toggle, button handler) instead of an engine command with
  empty params. Fixes ALT+H FF/FS/N/H/H error boxes.
- Ribbon consumes a one-shot ui.keytip_invoke: font/size/number combos
  converted to the popup pattern (ComboBox has no open_memory), fill/font
  color menus force-open via SetOpenCommand, 100% zoom and Formula Bar run
  their handlers.
- keytips.json: FF/FS/N/H/H -> control kind; View/Formulas/Data dialog
  openers (WQ zoom, HFM format cells, HO*, MV, AWG, sparkline types) and
  control WVF; MSP/HVP re-targeted; dropped 15 unreachable Home sub-items
  and non-Excel HWS shrink-to-fit.
- View tab: badges on workbook views, gridlines/headings, formula bar.
- Generated suite: 399 tests incl control-kind arm; direct tests 18.
2026-10-11 23:40:23 +03:00
James 7591fca086 T7: generated per-sequence regression tests (412 tests, catalog-probed)
cargo xtask keytips now emits tests/keytips_generated.rs alongside the
table: one end-to-end test per sequence, asserting exactly what its
action does today. The generator probes the live engine catalog at
generation time (blank workbook, empty params), so each live command
asserts journaled / ran clean / surfaced its missing-params error;
pending asserts silence; dialogs assert the dialog opens; tabs assert
the ribbon switch; group levels assert the prefix stays armed.

- pending-but-landed targets get live assertions and a generation
  warning (HWS home.shrinkToFit and MAA formulas.removeArrows had
  landed since population - flipped to live)
- unreachable-sequence validation: any seq with a terminal prefix
  entry is rejected (HCP dropped - HC Copy fires first)
- ENV_SENSITIVE list keeps the checked-in file byte-stable across
  machines (review.spelling uses the system dictionary)
- sample_sequences_work_with_text_before_key covers IME text-first
  event order for one representative of each action kind
- generated_test_count_matches_the_table pins the table size

518 ui-egui tests green; all 8 CI gates pass.
2026-10-11 23:40:04 +03:00
James cd5f3f0a71 T6: pending keytips resolve at runtime and go live when their command lands
- Action::Pending now consults the engine catalog at fire time: silent
  no-op while the command is missing, runs it once it exists - no table
  edit needed when a future feature lands.
- Stripped stray backticks from 7 pending target ids so catalog lookup
  can ever match them.
- gridcraft-engine: doc(hidden) register_test_command hook so UI tests
  can prove the go-live path without touching production code.
- Tests: pending_sequences_are_silent_no_ops (no dialog/toast/journal),
  pending_sequences_go_live_when_the_command_lands (fake command fires
  via its reserved sequence), every_sequence_terminates_without_panicking
  (all 413 sequences pressed end-to-end).
2026-10-11 23:40:04 +03:00
James 659a4d5bd3 Real-Excel keytip corrections from James (Home/Insert/Formulas)
- HP -> home.percent (was wrongly numberFormat); HN stays the Number dropdown.
- H3 -> home.underline fires directly; H3U/H3D dropped as unreachable.
- HAT/HAM/HAB -> Top/Middle/Bottom Align (were unbound).
- NCM/NZT/NZS -> modern Comment/Text Box/Symbol (NC2/NZTX/NU kept as
  legacy aliases); MI1 -> Financial first item.
- Badges on the three dropdowns (font FF, font size FS, number format N)
  and the vertical alignment buttons; Print Titles paints PI.
2026-10-11 23:39:35 +03:00
neilcawse 9ce910f87f Formulas: trim-reference operators (A1:.E10, A1.:E10, A1.:.E10); read unbracketed [[#This Row],Col]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 16:39:31 -04:00
James 95b3641725 Paint keytip badges on every ribbon control (issue #49)
The badge painter only covered five sites, so pressing Alt+H showed
nothing past the tab letter. Now every control with a catalog command id
paints its badge automatically:

- control_badge(prefix, id): the rest of a control's unique sequence
  (HFC -> "FC" on Font Color), or the common group letter when many
  variants land on one control (HBA..HBW -> "B" on Borders).
- anchor_badge(prefix, targets): menu anchors resolve to the dominant
  group-level candidate (Pictures shows "P", not SmartArt's "M").
- ribbon.rs: 90+ control sites now paint through control_keytip/
  anchor_keytip (mechanical sweep + hand-wired anchors); split buttons
  paint at their arrow rect.
- Offscreen snapshot verified: at prefix H the Home ribbon paints
  V/X/C/FP/1/2/3U/FC/H/FG/FK/AL/AC/AR/5/6/WW/MC/K/0/9/L/T/J/I/D/O.
- Tests: 29 lib + 14 keytips, all 8 CI gates green.
2026-10-11 23:39:11 +03:00
James f11d74ee7c Populate the full Excel keytip table (408 sequences, issues #33 and #49)
Population of keytips.json from the collected Excel Alt-sequence set:
- 408 curated entries: 10 tabs, 354 command binds (64 reserved pending,
  290 live catalog commands), 2 dialog openers, 42 group levels.
- Bind-all policy: sequences whose command does not exist yet bind to the
  canonical future id as Action::Pending -- badge shows, invocation is a
  silent no-op until the command lands (ids from docs/parity-checklist).
- Group levels: 46 command entries that are strict prefixes of deeper
  sequences were demoted to menu openers so the trie never fires early
  (HV must not paste; it waits for the variant letter).
- Fire-immediately restores: HC Copy, HAN Accounting, FA Save As, FO Open,
  FI Info. Unreachable legacy aliases (HCC, HANM, FA1, FAY3, FOC, FOO, FIP)
  dropped: the parent fires first.
- ES stays a terminal dialog opener as in Excel: the A/F/T/V variants are
  dialog mnemonics, not trie sequences.
- Escape pops one trie level and returns to the armed root at a single
  letter; keytips.json is the single modifiable source; xtask keytips now
  emits through rustfmt so --check is byte-stable.
- Tests: 99 pass (27 lib + 14 keytips + suite), all 8 CI gates green.
2026-10-11 23:37:45 +03:00
James 82cf8a6bb3 Keytips: table-driven matcher and badge painting (issues #33, #49)
Move the hardcoded keytip sequence list into keytip_table.rs as the single
source of truth for both the matcher and the ribbon badge painter.

- Generalize Action::Home into Action::Tab(&'static str); the legacy
  Edit/Format prefix special-case in lib.rs is absorbed into the table.
- Badge helpers: tab_sequence (tabs), group_extension (menu anchors),
  item_letter (menu items), control_badges (command controls).
- Add tab letters for Insert (N), Page Layout (P), Formulas (M), Data (A),
  Review (R), View (W); Draw/Automate stay unbadged until contextual
  letters land.
- Tests: 5 table unit tests + tab_letters_switch_to_their_ribbon_tabs
  integration test. All 7 xtask ci gates green.
2026-10-11 23:37:24 +03:00
Shirish Veerabattini 1d1d27f9a4 ui: argument hint shows the function's description
Inside DATEDIF( the hint showed only the signature, so the values unit
takes weren't visible while typing it (#363). The hint now adds the
function's description under the signature, wrapped to the hint's
width, the same text the autocomplete list shows (translated where a
Spanish entry exists).

Claude-Session: https://claude.ai/code/session_01BGBBGBC2gRpQ7GDuwQ6WPt
2026-10-11 15:37:09 -05:00
James e90ebbbbe2 Keytips: keytips.json source + xtask generator (issues #33, #49)
The sequence table is no longer hand-maintained Rust: keytips.json is the
single human-edited source (one line per sequence, grouped by tab, pending
reserves sequences for future commands), and `cargo xtask keytips`
regenerates keytip_table/generated.rs deterministically. `cargo xtask ci`
now fails if the generated table is stale.

- Action::Pending: reserved sequences show their badge and invoke silently
  until the command exists (bind-all policy).
- Intermediate group levels are implicit: the matcher waits whenever a
  pressed letter starts a deeper sequence; only terminal entries are
  listed (two-letter units like Draw's "JI" work with no extra rows).
- First populated sequence beyond the legacy set: W,V,G toggles gridlines,
  proven end-to-end by view_gridlines_sequence_runs_end_to_end.
2026-10-11 23:36:02 +03:00
James eba3957a21 Keytips: multi-letter units and implicit wait levels (Draw = "JI")
Excel shows some access keys as one multi-letter unit (Draw's "JI") that
fires only once complete. The matcher now follows the trie shape:

- A pressed letter that matches a complete sequence fires immediately.
- If it only starts deeper sequences, the matcher waits for more input
  (implicit group level, no table entry required).
- A tab with deeper sequences stays as an active level so group badges
  show; a terminal unit clears the prefix.
- tab_sequence() returns multi-letter tab units as one badge.

Draw: Alt+JI switches to the Draw tab; deeper Draw letters are left
blank for future contributors (GridCraft's Draw differs from Excel's).
2026-10-11 23:36:02 +03:00
James b415d2e835 Keytips: table-driven matcher and badge painting (issues #33, #49)
Move the hardcoded keytip sequence list into keytip_table.rs as the single
source of truth for both the matcher and the ribbon badge painter.

- Generalize Action::Home into Action::Tab(&'static str); the legacy
  Edit/Format prefix special-case in lib.rs is absorbed into the table.
- Badge helpers: tab_sequence (tabs), group_extension (menu anchors),
  item_letter (menu items), control_badges (command controls).
- Add tab letters for Insert (N), Page Layout (P), Formulas (M), Data (A),
  Review (R), View (W); Draw/Automate stay unbadged until contextual
  letters land.
- Tests: 5 table unit tests + tab_letters_switch_to_their_ribbon_tabs
  integration test. All 7 xtask ci gates green.
2026-10-11 23:36:02 +03:00
sanches 2f22346807 i18n: add French (fr) interface
A complete 379-entry catalog covering every JAPANESE key (the coverage
reference), registered as a Fr variant in the Language enum. The
uniqueness/coverage test now asserts French alongside the other
languages; locale tags fr-FR and fr_CA resolve.
2026-10-11 23:27:39 +03:00
Brandon Thomas 3054babe0e Text boxes: their typefaces count as used workbook fonts, so an installed one is bound; restore image_ext's doc comment (review fix-up for #401)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 16:14:41 -04:00
Brandon Thomas 1c3beb2a95 Merge branch 'land' into fix-401
# Conflicts:
#	ROADMAP.md
2026-10-11 16:09:03 -04:00
Brandon Thomas 4a23b9cf4b Merge pull request #404 from vangel76/fix/header-footer-variants
Headers and footers: first-page and even-page variants, Insert › Header & Footer edits in place (#344)

# Conflicts:
#	ROADMAP.md
2026-10-11 16:08:56 -04:00
Brandon Thomas 7cd96b945f Merge pull request #402 from vangel76/fix/ui-font-hebrew-fallback
UI fonts: formula bar falls back to the cell font, so Hebrew isn't boxes (#349)

# Conflicts:
#	ROADMAP.md
2026-10-11 16:08:55 -04:00
Brandon Thomas b2101947ca Merge branch 'land' into fix-388
# Conflicts:
#	docs/ui-parity.md
2026-10-11 16:01:53 -04:00
Brandon Thomas 6cc69494ca Merge branch 'land' into fix-394
# Conflicts:
#	ROADMAP.md
2026-10-11 15:55:10 -04:00
vangel76 cdd71b4d5d Headers and footers: first-page and even-page variants, Insert › Header & Footer edits in place (#344)
XLSX headerFooter kept only oddHeader/oddFooter: a workbook whose header is on a
different first page (differentFirst + firstHeader) or on even pages showed no
header, and saving dropped it. The model now keeps the first/even headers and
footers and the differentFirst / differentOddEven / scaleWithDoc / alignWithMargins
flags; XLSX reads and writes them; the PDF and the Page Layout view use the right
pair per page; in-place editing edits the page's own pair, and the Header & Footer
tab has Different First Page and Different Odd & Even Pages. pageLayout.headerFooter
takes the variants and a page: odd|even|first for one-section edits.

Insert › Header & Footer now switches to Page Layout view and edits the first
page's centre header, as in Excel, instead of opening the codes dialog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:44:49 +02:00
Brandon Thomas f173d6733d Merge pull request #387 from vangel76/fix/sheet-protection-password
Review: Protect Sheet passwords use Excel-compatible hashes, kept in XLSX (#346)

# Conflicts:
#	ROADMAP.md
2026-10-11 15:43:46 -04:00
Brandon Thomas 283b06453e Merge pull request #383 from vangel76/fix/sheetview-top-left-cell
View: restore and save the scroll position (topLeftCell) (#378)

# Conflicts:
#	ROADMAP.md
2026-10-11 15:43:45 -04:00
Brandon Thomas 12b46e6bbe Merge pull request #395 from vangel76/fix/space-selection-shortcuts
Keyboard: Shift+Space and Ctrl+Space select without starting an edit (#338)

# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/grid.rs
2026-10-11 15:43:44 -04:00
Brandon Thomas 8498dedb7d Merge pull request #381 from vangel76/fix/shrink-to-fit
Grid: render Shrink to fit (#375)

# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/grid.rs
2026-10-11 15:43:32 -04:00
Brandon Thomas d90a072d90 Merge pull request #380 from vangel76/fix/merged-range-borders
Grid: merged ranges draw their right and bottom borders (#376)

# Conflicts:
#	ROADMAP.md
2026-10-11 15:43:31 -04:00
vangel76 88bb5677a8 UI fonts: interface text falls back to the cell font (#349)
On macOS the UI font (SF) has no Hebrew and no Hebrew fallback face was
found, while cells in Arial drew it: the formula bar showed boxes. The
interface families now carry the cell face ahead of the script fallbacks,
and the macOS Hebrew candidates include ArialHB.ttc / SFHebrew.ttf /
LucidaGrande.ttc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:42:24 +02:00
vangel76 da1d291d93 Drawing: text box run formatting, alignment, anchor and no-outline (#377)
Text boxes ignored a:rPr (size, bold, italic, typeface, fill, outline),
a:pPr algn, a:bodyPr anchor and spPr/a:ln/a:noFill. They are now read into
Shape::format, drawn on screen and in PDF, and written back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:39:53 +02:00
Brandon Thomas e211f666a6 Merge main into installed-fonts: workbook fonts bind on top of main's per-language font set and fallback faces; only families that survive drop_unparseable_fonts count as bound; a language switch rebinds them (review fix-up for #9)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 15:38:42 -04:00
vangel76 8587c2ba14 Review: Protect Sheet can't replace a sheet's password without unprotecting it
Re-protecting a password-protected sheet would drop its hash and let a
plain Unprotect succeed; it is now refused. The sheet tab menu offers
Unprotect Sheet on a protected sheet, like the ribbon.

Refs #346

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:36:05 +02:00
vangel76 6290bf123a Keyboard: Shift+Space and Ctrl+Space select without starting an edit (#338)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 21:32:57 +02:00
vangel76 ad48f1e3e1 File: desktop Print opens the system PDF viewer, Save As offers PDF/CSV/HTML (#370, #343)
Since #209, printing from the UI hands the print PDF to Services::print, which only
the web build set: on the desktop, Ctrl+P, More › Print, the macOS menu and the
Backstage Print button produced the PDF and dropped it. The desktop app now writes
it to the temporary folder and opens it in the system PDF viewer, whose Print
reaches the printer dialog.

Save As has a Save as type chooser (xlsx, csv, html, pdf); file.save and
file.saveAs with a .pdf path write a PDF of the sheet (they wrote XLSX bytes into
the .pdf and made it the workbook's file). The desktop save picker honours the
suggested type instead of always proposing .xlsx. The macOS Properties item opens
File › Info instead of running file.properties with no fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:32:38 +02:00
vangel76 22978a7e62 Review: Protect Sheet passwords use Excel-compatible hashes, kept in XLSX
Sheet protection stored an internal FNV hash that was never written to
XLSX, and an Excel sheet password was dropped on import, so imported
protected sheets could be unprotected without it. Protect Sheet now
stores a salted SHA-512 hash (spin count 100000) via PasswordHash; the
XLSX sheetProtection password (iterated or legacy) is read and written,
and Unprotect Sheet really verifies it. Hashes from older GridCraft JSON
workbooks are still read and verified.

Refs #346

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:29:10 +02:00
Fabio Lussi 535c502fe7 Draw the outline band for grouped rows and columns
Grouped rows and columns now get Excel's outline band beside the headers:
a bracket per group, a -/+ button on the summary line and level buttons
in the corner. The buttons run data.hideDetail / data.showDetail and the
new data.showLevels, so they undo. Hide Detail marks the summary line
collapsed, Show Detail keeps inner groups that were collapsed on their
own, and Group / Ungroup take by: rows|cols. Show Detail and Hide Detail
are on the Data tab and in the Data menu, the group shortcuts are listed
as Alt+Shift+Right / Left, and shortcut lookup reads navigation keys by
their logical key so the numpad arrows work.

Fixes #373

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:29:03 +02:00
Brandon Thomas 9bf5ecaf04 Merge main into VBA preservation; save macros only into .xlsm (an .xlsx never carries a VBA project); drop the shell round-trip script (review fix-up for #19)
The Rust round-trip test covers what scripts/check-vba-roundtrip.sh checked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 15:20:45 -04:00
vangel76 fbabac15d4 Review: Protect Workbook dialog with an Excel-compatible password (#345)
The ribbon button toggled structure protection silently. It now opens a
Protect Structure and Windows dialog with an optional password; when a
password was set, unprotecting asks for it and really verifies it
(SHA-512, spin count 100000, salted). The password hash is read from and
written to XLSX workbookProtection (workbookAlgorithmName/HashValue/
SaltValue/SpinCount or the legacy workbookPassword); an unreadable one
stays locked. File › Info uses the same flow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:12:24 +02:00