# GreekTranscoder 2 Version History

**Important**
Only GreekTranscoder 2.0.5 (or later) is fully compatible with the WinGreek encoding. Because they use the `.docx` document format exclusively, versions 2.0.0–2.0.4 may silently delete WinGreek quote characters. Please make sure you upgrade to the latest version of the program before using it.

## Version 2.0.5: 2026.03.03

### 1. WinGreek Compatibility

- WinGreek C0 control characters are silently stripped from `.docx` files on save (see "VBA Bugs and Quirks" below for details). GreekTranscoder 2 now saves the `.xcoded` working copy in `.doc` format when targeting WinGreek, preserving those characters.
- When converting to WinGreek, a specific bilingual alert replaces the standard working-copy notice.
- The native WinGreek quotes `ChrW(7)` (LEFT-POINTING DOUBLE ANGLE QUOTATION MARK "«"), `ChrW(28)` (LEFT SINGLE QUOTATION MARK "‘") and `ChrW(29)` (RIGHT SINGLE QUOTATION MARK "’") have been demoted to "alternate" characters: recognized in original WinGreek `.doc` documents, but replaced by XML-compatible marker sequences in new conversions.
- Previous conversions that relied on these characters should be redone from the original source `.doc` document.
- The font previously listed as "GRAMMATA (WinGreek encoding)" is actually called "Grammata" in Word.

### 2. Beta Code Bracket-Digit Protection

- Beta Code uses bracket-digit sequences (e.g., `[5`, `[73`, `]8`) so that source text containing numbered sections in square brackets (e.g., `[5]`, `[67]`, `[142]`) could be corrupted during conversion.
- A new `BetaCodeDigitsChecker` function now protects those sequences by converting them to Unicode in Times New Roman, colored green.

### 3. Color Cleanups

- The `BetaCode/SPIonic Digit Cleanup` now only runs if neither SPIonic nor Beta Code is the target encoding, since they only support digits as control modifiers.
- Post-conversion, if Times New Roman is the target font, rescued characters (green) are switched to `wdColorAutomatic`.
- Post-conversion, if Unicode is the target encoding, unconverted characters already in the target font (red) are switched to `wdColorAutomatic`.

### 4. Quote Marker Improvements

**Backward Compatibility**
- In v 2.0.4, the quote marker system was updated so that BibleWorks, SGreek and WinGreek use encoding-specific exclamation mark characters and the corresponding `ChrW(33)`-based marker patterns were removed from the `GreekRemoveQuoteMarkers` module.
- 8 backward-compatibility patterns restored in the SINGLE ! MARKERS section: Vilnius `ChrW(171)`/`ChrW(187)`, BibleWorks `ChrW(185)`/`ChrW(190)`.

**WinGreek**
- The WinGreek quote marker system has been entirely redone in order to demote C0 control characters to "alternate" status (see above §1).
- `ChrW(123)` (LEFT CURLY BRACKET "{") is now used instead of `ChrW(28)` and `ChrW(125)` (RIGHT CURLY BRACKET "}") instead of `ChrW(29)`.
- ANGLE QUOTATION MARKS now use `ChrW(8218)` as a distinctive marker and the sequence `ChrW(128) & ChrW(8218)` replaces `ChrW(7)` as the canonical entry for the LEFT-POINTING DOUBLE ANGLE QUOTATION MARK "«".
- Because `ChrW(7)`, `ChrW(28)` and `ChrW(29)` are unavailable in converted documents, the corresponding quote markers cannot be fully stripped by `GreekRemoveQuoteMarkers` and are switched to `wdColorBlue` instead.

**SmartQuotes Marker System: NBSP Collision Fix**
- The v2.0.0 marker system used NBSP `ChrW(160)` as a directional marker for English curly quotes and French guillemets, causing collisions with contextual NBSPs from French typography in particular.
- Each affected source encoding now uses an encoding-specific unused marker instead of NBSP: `ChrW(64)` ("@") for BetaCode/Ismini/LaserGreek/SuperGreek, `ChrW(182)` ("¶") for BibleWorks/SGreek/Vilnius, `ChrW(179)` ("³" displayed as "@") for PaulinaGreek, `ChrW(37)` ("%" displayed as "Ϲ") for GreekKeys.

**Obsolete NBSP Marker Migration**
- A new `MigrateObsoleteNBSPMarkers` function in `GreekRemoveQuoteMarkers` silently upgrades v2.0.3–2.0.4 NBSP-based blue markers to the new encoding-specific markers before conversion (black markers created by v.2.0.0–2.0.2 will have to be replaced or stripped manually, or the original document converted anew).
- Detection uses blue-colored `ChrW(160)` as a safety constraint: contextual black NBSPs are untouched.

### 5. Database Improvements

**BetaCode**
- `"#15"` was assigned to DOTTED RIGHT POINTING ANGLE (DIPLE PERIESTIGMENE, U+2E16) by mistake, duplicating the correct MORE-THAN SIGN (U+003E).
- `"%25"` was assigned to COMBINING COMMA BELOW (U+0326) and COMBINING OGONEK (U+0328) by mistake: it has been reassigned to the correct COMBINING CEDILLA (U+0327).
- `"%149"` has been assigned to COMBINING OGONEK (U+0328) and COMBINING COMMA BELOW (U+0326) has been removed from Beta Code (it is absent from the TLG reference).
- `"%91"` and `"%92"` were assigned to both NON-COMBINING and COMBINING diacritics, which are legitimate per the TLG reference, but incompatible with the way conversions work. Only the non-combining forms, which carry legacy values, have been kept.

**BibleWorks**
- Archaic letters and apparatus symbols added: RIGHT-POINTING ANGLE QUOTATION MARK, CAPITAL/SMALL LETTER SHO, KAI SYMBOL, CAPITAL LETTER ARCHAIC KOPPA, CAPITAL LETTER STIGMA, CAPITAL LETTER DIGAMMA, CAPITAL LETTER KOPPA, CAPITAL LETTER SAMPI, CAPITAL LUNATE SIGMA SYMBOL, CAPITAL/SMALL LETTER SAN, GREEK RHO WITH STROKE SYMBOL; LATIN SMALL LETTER F WITH HOOK, DAGGER, DOUBLE DAGGER, BLACK-LETTER CAPITAL I, SCRIPT SMALL L, ALEF SYMBOL, LEFT/RIGHT WHITE SQUARE BRACKET, BLACK-LETTER CAPITAL R, COMBINING DOUBLE INVERTED BREVE, COMBINING RING BELOW.
- New standalone records added: ASTERISK OPERATOR, MEDIUM SMALL WHITE CIRCLE, COMBINING TILDE BELOW.
- Several corrections applied to existing records.

**GreekKeys**
- New `GreekKeysAlt` field for characters present in some GreekKeys fonts such as Xanthippe but absent from the default Athenian font.
- 16 new Xanthippe-only records added: 12 are alternates of existing canonical records; 4 are non-canonical (no Athenian equivalent).

**Ismini**
- QUESTION MARK was assigned `ChrW(63)` by mistake, duplicating the correct GREEK ANO TELEIA (ANO STIGME) entry.
- UNDERSCORE was assigned `ChrW(95)` by mistake, duplicating the correct EM DASH entry.
- `ChrW(8211)` reclassified from MIDDLE DOT (U+00B7) to BULLET (U+2022).

**LaserGreek/SuperGreek**
- Linguist Software changed the use of `ChrW(45)` and `ChrW(60)` over the years, creating several inconsistencies in its encodings and associated fonts. GreekTranscoder 2 now adheres to the most recent LaserGreek usage.
- HYPHEN-MINUS: `ChrW(60)` corrected to `ChrW(45)`.
- NON-COMBINING MACRON = EN DASH: corrected to `ChrW(60)`.

**Paulina Greek**
- NON-COMBINING GREEK DASIA AND VARIA: `ChrW(352)` corrected to `ChrW(189)`.
- Added entries for LATIN SMALL LIGATURE OE `ChrW(339)` and PLUS-MINUS SIGN `ChrW(177)`.
- Some corrections applied to existing records.

**SGreek**
- `ChrW(353)` reclassified from MIDDLE DOT (U+00B7) to BULLET (U+2022).

**Vilnius**
- LEFT/RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK AND NO-BREAK SPACE: the SmartQuotes marker for these records now uses `ChrW(33)`, because Word's smart quote folding normalizes `ChrW(171) & ChrW(160)` into `ChrW(8220)` (curly double quote), making a single real NBSP unusable adjacent to native guillemets.

**Ismini, GreekKeys, Paulina Greek**
- DOUBLE SOLIDUS was assigned a single `ChrW(47)` instead of `ChrW(47) & ChrW(47)` in all three encodings.

### 6. Beta Symbol Block Ordering Fix (Unified version)

- The beta symbol pre-conversion check (`ChrW(976)` detection and replacement) was running before the `.xcoded` backup copy was created. Moved to run after versioning, matching the macOS-only version.

### 7. Homonymous Font Warning Fix (macOS-only version)

- The Vilnius University variants of Odyssea and Hellenica are stored as "Odyssea " and "Hellenica " (with a trailing space) to distinguish them from their LaserGreek homonyms.
- The HTML form's `gatherFormData()` was passing trailing-space font names to validation, causing homonymous font confirmation dialogs to silently fail. Fixed by trimming font names after the encoding lookup.

### 8. Interface.frm Dispatcher Refactoring (Unified version)

- The conversion dispatcher has been rewritten from a nested `If/ElseIf` cascade to a `Select Case` structure, aligning it with the macOS `ASEntry` dispatcher.
- Inline font-switching code extracted into a new `Private Sub SwitchFonts`.

## Version 2.0.4: 2026.02.25

### 1. Transcoders' Improvements

**Database: Self-Contained Transcoders**
- In v 2.0.3, several encoding-specific functions were hand-coded in the Engine and UI modules: blue marker coloring (`ColorQuoteMarkers`) and quote marker rescue for SPIonic targets (`RescueQuoteMarkers`). These duplicated pattern data already present in the FileMaker database and required manual synchronization with the character mappings.
- In v 2.0.4, all encoding-specific logic is generated directly from the database and resides in the transcoders.
- Each transcoder is now self-contained and includes, in execution order:
1. **ComposingChecker** — normalizes precomposed/decomposed forms (unchanged).
2. **QuotesRescue** — for X-into-SPIonic only: converts blue marker sequences to Unicode quotes in Times New Roman, colored green. Generated from the same marker records used by `SmartQuotes`.
3. **Rescue** — converts source characters with no target equivalent to Unicode in Times New Roman, colored green. Target-aware exclusion lists prevent collisions with multi-character composed sequences in the main conversion loops.
4. **SmartQuotes** — places quote marker sequences in the target encoding, then colors them blue. Previously, coloring was a separate Engine function; it is now part of the same generated block.
5. **Main conversion loops** — standard character mapping (unchanged).
6. **Catch-all** — colors all remaining source-font characters red (unchanged).

**Engine Module Cleanup**
- Enforcing the original GreekTranscoder's architecture, the Engine no longer contains any encoding-specific dispatch tables, marker pattern data, or coloring logic.
- It is once again a generic service layer: conversion, detection, whitespace cleanup, error logging.

**Three-Color Post-Conversion Scheme and Alerts**
- In previous versions, legacy-encoded characters which could not be converted were colored red, but their meaning was essentially lost. Now, they are "rescued" as legible Unicode code points.
- Post-conversion characters now use three distinct colors:

| Color     | Meaning                    | Font            | Set by                 |  
| --------- | -------------------------- | --------------- | ---------------------- |  
| **Red**   | Unconverted characters     | source font     | Catch-all              |  
| **Green** | Rescued to legible Unicode | Times New Roman | Rescue/QuotesRescue    |  
| **Blue**  | Quote marker sequences     | target font     | SmartQuotes            |  

- The completion dialog now reports 8 possible alert states based on those three independent color flags.
- Blocks are ordered by severity: red (warning), green (informational), blue (informational).

**Transcoders Optimization**
- Removed smart quotes' records from legacy target encodings' conversions (redundant with `SmartQuotes` pre-processing), eliminating ~1,100 no-op Find/Replace operations across 11 transcoders.
- Moved `Select Case iCharTotal` (progress rate computation) out of the `For i = 1 To iCharTotal` loop and into procedure-level code: the value is constant per function.

**Unicode Transcoder Optimization and Fixes**
- In Unicode-to-Unicode conversions, many composing characters are identical to their composed counterparts and only need a font switch instead of a no-op replacement.
- Word's fuzzy character equivalence was conflating straight and curly quotes in Unicode-to-SPIonic conversions. Those conversions now use `bMatchWildcards:=True` scoped to `UnicodeComposedOther_into_SPIonic`.

### 2. Database Improvements

**Systematic Font Audit**
- All 12 legacy font encodings cross-validated against their original font files (BetaCode audited separately via the Beta Code Manual). All 12 phases complete with 0 outstanding issues.
- 9 wrong character values corrected across 5 encodings (Ismini, LaserGreek, SuperGreek, Unicode, Vilnius). 10 new records added. 10 new values added to existing records.

**BetaCode**
- Custom value list for sorting.
- COMBINING COMMA ABOVE (PSILI, U+0313): `")"` changed to `"%177"`. COMBINING REVERSED COMMA ABOVE (DASIA, U+0314): `"("` changed to `"%178"`. Avoids collisions and better aligns with TLG specification.
- 5 new characters: GREEK CAPITAL LETTER HETA (`*#400`, U+0370), GREEK SMALL LETTER HETA (`#400`, U+0371), GREEK CAPITAL LETTER YOT (`*#401`, U+037F), GREEK SMALL LETTER YOT (`#401`, U+03F3), RAISED OMISSION MARKER (`#1204`, U+00B0).
- Half bracket codes added for 3 new records (see LaserGreek/SuperGreek): `[7`/`]7` for top, `[5`/`]5` for bottom. Floor brackets reassigned from `[5`/`]5` to `[8`/`]8`.

**BibleWorks**
- `ChrW(160)` instead of `ChrW(32)` as prefix for all capital letters with standalone VARIA, OXIA, TONOS, or DIALYTIKA (prevents double-space collapsing).
- `CapitalChecker` subscript added to normalize malformed capital letters.

**Ismini**
- OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI (U+1FA2): `ChrW(311)` corrected to `ChrW(711)` (digit transposition).

**LaserGreek/SuperGreek**
- LATIN SMALL LETTER Y: wrong PostScript codepoint `ChrW(180)` (ACUTE ACCENT) corrected to `ChrW(165)`. Both encodings.
- NON-COMBINING PERISPOMENI: LaserGreek `ChrW(96)` corrected to `ChrW(39)` (was indistinguishable from TILDE rec 436). SuperGreek already had `ChrW(39)`.
- LEFT HALF BRACKET (U+2E22): wrong Unicode `ChrW(11776)` corrected to `ChrW(11810)`. LaserGreek/SuperGreek values moved to new rec 555.
- COMBINING CIRCUMFLEX FOR CAPITAL LETTERS: wrong LaserGreek PostScript values deleted (byte 223 is NUMBER 2 SUPERSCRIPT in LaserGreek, CIRCUMFLEX only in SuperGreek).
- COMBINING GRAVE/ACUTE FOR CAPITAL LETTERS: wrong LaserGreek convention values `ChrW(204)`/`ChrW(200)` emptied (these are NUMBER 1 SUPERSCRIPT and DOUBLE SOLIDUS, not convention diacritics).
- 3 new records: half brackets TOP RIGHT, BOTTOM LEFT, BOTTOM RIGHT (U+2E23–U+2E25).
- 5 new malformed records: space/NBSP + breathing marks `ChrW(74)`/`ChrW(106)`, space + tilde `ChrW(96)`.

**PaulinaGreek**
- PLUS-MINUS SIGN (U+00B1): was set by mistake to `ChrW(232)`, corrected to empty.

**SGreek**
- 2 new records: CENT SIGN (U+00A2) `ChrW(199)`, POUND SIGN (U+00A3) `ChrW(198)`.
- 6 new Alt/Malformed values on existing records: overline/underline 3-width variants.

**Titus**
- ETA WITH PSILI AND VARIA (U+1F22): `"^"` corrected to `"^^"` (`"^"` is not allowed in Word's "Replace with" box and is equivalent to "^^" in the "Find box").
- LATIN SMALL LETTER Z WITH CARON (U+017E): added `TitusAlt=ChrW(158)` (Win-1252 byte duplicate at U+009E).

**Unicode**
- VERTICAL LINE EXTENSION (U+23D0) deleted: normalized to VERTICAL BAR (U+007C).
- LEFT HALF BRACKET (U+2E22): wrong `ChrW(11776)` corrected to `ChrW(11810)`.

**Vilnius**
- OMICRON WITH PSILI AND VARIA (U+1F42): `ChrW(211)` corrected to `ChrW(204)` (was duplicate of UPSILON WITH PSILI AND VARIA).
- MIDDLE DOT (U+00B7): `VilniusAlt=ChrW(9729)` corrected to `ChrW(8729)` (digit transposition).

**WinGreek**
- NON-COMBINING DIAERESIS: added `WinGreek=ChrW(64)`.
- EPSILON WITH DASIA AND VARIA: added `ChrW(382)` as an alternate character (Win-1252 for C1 byte).
- RHO WITH DASIA: added `ChrW(8729)` as an alternate character (BULLET OPERATOR, same glyph as canonical `ChrW(183)` MIDDLE DOT).

**TLG Convention Records**
- Fixed an issue where six combining diacritic records covering four code points (`ChrW(768)`, `ChrW(769)`, `ChrW(771)`, `ChrW(787)`) and representing valid TLG vs scholarly convention differences, not malformed data, were not always processed correctly.

**Prefix Collision Fix**
- The last prefix collisions caused by faulty sort orders have been eliminated.
- Only BetaCode, BibleWorks and SGreek were affected and are now fixed.

**Quote Marker Collision Fix**
- The marker system uses `ChrW(33)` (EXCLAMATION MARK) as a default directional marker character. However, three legacy encodings map code point 33 to non-exclamation glyphs: BibleWorks (PLUS SIGN), SGreek (alternate GREEK ANO TELEIA), WinGreek (SOUTH WEST ARROW). In these encodings, marker sequences displayed the wrong glyph and could collide with the encoding's own mapping for code point 33.
- Each of the three encodings now uses its own canonical exclamation mark character as the marker: BibleWorks `ChrW(184)`, SGreek `ChrW(8222)`, WinGreek `ChrW(8218)`. The remaining encodings (GreekKeys, Ismini, LaserGreek, PaulinaGreek, SuperGreek, Titus, Vilnius) retain `ChrW(33)`.
- The `GreekRemoveQuoteMarkers` utility module was updated to match the encoding-specific marker characters in addition to the default `ChrW(33)`.

### 3. macOS-only Version Improvements

**macOS Macros… Dialog Fix**
- Resolved the v 2.0.3 known limitation where macros did not appear in Word for Mac's Macros… dialog at startup (see "VBA Bugs and Quirks" below for details).

**macOS Sandbox Save Fix**
- macOS sandbox blocks `ActiveDocument.Save` when the document is in a folder monitored by a sync agent (iCloud, Google Drive, OneDrive, Dropbox, etc.). This caused a silent Error #0 that aborted conversions.
- Pre-loop calls removed from all generator templates (redundant: each function's checkpoint save covers the next function's start).
- Remaining checkpoint saves wrapped with `On Error Resume Next`.
- When overwrite is blocked, the `SaveAs` retry loop is now capped at `MAX_SAVEAS_RETRIES = 5`.
- The xcoded version-finding loop retains its `MAX_XCODED_VERSIONS = 999` cap for normal use.

**Version Sync Preflight**
- New `GT_DOTM_VERSION` constant in the Launcher module.
- Before launching the external application, the Launcher reads `CFBundleShortVersionString` from the app's `Info.plist` and compares with `GT_DOTM_VERSION` (see "VBA Bugs and Quirks" below for implementation details).
- On mismatch, a bilingual alert shows both version numbers and aborts, preventing unpredictable behavior from running mismatched components.
- Three distinct bilingual warnings prepare the user for a possible macOS sandbox "Grant File Access" dialog depending on the context:
  1. **First launch** (no saved path): explains the upcoming file chooser and sandbox grant dialog.
  2. **Application not found** (saved path invalid): explains relocation and possible sandbox grant.
  3. **Template updated** (dotm version differs from last successful check): explains the sandbox grant may reappear. Skipped when the user has just located the app (cases 1–2 already cover it).
- A `last_checked_version.txt` preference file (alongside the existing `app_path.txt`) records the dotm version that last completed the sandbox grant, enabling detection of dotm updates without redundant warnings on normal runs.

### 4. Windows-only Improvements

**WinGreek and Titus Removed as Target Encodings**
- WinGreek and Titus use byte positions in the C1 control character range (128–159) and DEL (127) for Greek characters. Windows Word cannot write these codepoints in Find/Replace operations, causing conversions *to* these encodings to silently corrupt characters. Conversions *from* these encodings work correctly on all platforms; conversions *to* them work correctly on macOS only.
- Normal mode: WinGreek and Titus fonts are excluded from the target dropdown. They remain available as source fonts.
- Expert mode: WinGreek and Titus encodings can still be selected manually, but a warning with Cancel as default explains the incompatibility (WinGreek: 5 affected characters; Titus: 30 out of 339, including all capitals with dasia or with psili and perispomeni).
- macOS: no changes. Both encodings remain fully functional as targets.

---

## Version 2.0.3: 2026.02.09

### 1. Post-Conversion Marker Highlighting

**Blue Marker Coloring**
- After conversion, quote marker sequences in the target encoding are now colored blue so users can identify them visually.
- Each target encoding's exact marker patterns are matched and colored directly.
- SPIonic and Unicode targets are excluded: SPIonic has no quotation mark records; Unicode uses native typographical quotes.

**Colored Characters Detection**
- After conversion, the Engine now scans for any characters colored red in the source font or blue in the target font.
- Red detection runs after the BetaCode/SPIonic digit cleanup to avoid false positives from digits that are legitimately red before cleanup.
- Both detection functions (red and blue) share a common `DetectColorInFont` helper to avoid code duplication.
- Because `FindText:=""` catches paragraph marks indiscriminately (see "VBA Bugs and Quirks" below), the helper uses patterns built from `ChrW()` ranges with `.MatchWildcards = True` to avoid ghost matches left by the catch-all's format-only replace.
- The helper respects `ReplaceAll` vs. `Selection` mode.

**Four-Way Success Alerts**
- The completion dialog now dynamically reports what colors are present in the converted document: no colors, red only, blue only, or both.
- When blue markers are detected, the alert notes the availability of `GreekTranscoder_RemoveQuoteMarkers` via Tools > Macro > Macros… (macOS) or Alt+F8 (Windows).
- When no red or blue characters are found, the alert is a clean "conversion done" message without unnecessary color warnings.

### 2. Remove Quote Markers: Color-Aware Matching

- The `GreekRemoveQuoteMarkers` utility module (see v2.0.2 §6) now only matches blue-colored marker sequences, leveraging the blue coloring applied by `ColorQuoteMarkers` (§1).
- Find side uses `.Font.Color = wdColorBlue` to restrict matching to markers colored by the conversion engine; replace side resets to `wdColorAutomatic`. Both constraints require `.Format = True`.

### 3. Font-Switch Color Setting

**Database Change**
- The FileMaker database was updated to support the new coloring features: all generated `CharConverter` calls now pass an explicit `lFontColor:=wdColorAutomatic` parameter.

**Engine**
- The `CharConverter` function's default `lFontColor` parameter changed from `wdColorAutomatic` to `-1` (sentinel meaning "preserve existing color").
- All three `.Font.Color = lFontColor` assignment sites in `ProcessStoryRange` and `ProcessSelectionRange` are now guarded with `If lFontColor <> -1`.
- This ensures that font-switch operations (same encoding, different fonts) no longer reset text color to `Automatic`, preserving blue markers from a prior conversion.

**Beta Symbol Color Fix**
- Because the improved color preservation in `CharConverter` removed the incidental color reset, beta symbols colored red by the catch-all retained their red color after being switched to the target font.
- The beta symbol cleanup (`ChrW(976)` font switch for Unicode targets supporting U+03D0) now explicitly passes `lFontColor:=wdColorAutomatic`.


### 4. Post-Conversion Whitespace Cleanup

**Ghost-Red Whitespace Problem**
- The catch-all in each transcoder colors all remaining source-font characters red via a format-only replace (`findChar:=""`). This legitimately flags unconverted characters, but also colors structural marks (paragraph marks, line breaks, section breaks) and Unicode exotic spaces.
- These characters become "ghost red": they carry red formatting in the document XML but are invisible on screen and cannot be found using a color filter (see "VBA Bugs and Quirks" below). 
- In addition, the document-final paragraph mark, once colored red by the catch-all's format-only replace, cannot be found or modified by any subsequent Find/Replace operation.

**CleanUpWhiteSpace Function**
- New `CleanUpWhiteSpace` Engine function runs after digit cleanup and before `DetectRedCharacters` in both `ReplaceAll` and `Selection` modes.
- Uses a single-pass wildcard `CharConverter` call covering structural marks (U+000B–U+000D) and Unicode exotic spaces (U+2000–U+200A, U+202F, U+205F).
- Font-only search (no `lFindFontColor`) with `lFontColor:=wdColorAutomatic` since color filtering does not work on ghost-red characters.
- The document's final paragraph mark is handled separately and directly, bypassing Find/Replace entirely (see "VBA Bugs and Quirks" below).

### 5. Selection Boundary Shift Fix

**Problem**
- The v2.0.3 post-conversion pipeline (CleanUpWhiteSpace, ColorMarkerSequence, DetectRedCharacters) runs multiple `^&` format-only Find/Replace operations sequentially. Word's Find/Replace with `^&` self-replacement shifts all live `Range` objects and the `Selection` in the same story as a side effect, even when operating on a `.Duplicate`. Cumulative drift across 8–10 pipeline calls pushes the final marker sequence outside the selection boundary.

**Body Text Branch**
- `ProcessSelectionRange` now saves `Selection.Start`/`.End` before Find/Replace and restores them after `^&` operations (guarded by `If replaceChar = "^&"`). Non-`^&` calls (main conversion) are unaffected since text length changes must be reflected in `Selection`.

**Non-Body Stories Branch (Footnotes, Endnotes, Headers, Footers)**
- Same drift affects `m_OriginalRange` and the `Selection` (which is back in the footnote after `StartRange.Select`). `ProcessSelectionRange` now saves and restores both `m_OriginalRange.Start`/`.End` and `Selection.Start`/`.End` for `^&` operations.

**Beta Symbol Detection in Non-Body Stories**
- Beta symbol detection and replacement (`ChrW(976)` → `ChrW(946)`) in Interface.frm and ASEntry.bas used `Selection.Range` to scope the search. On Windows, the modal UserForm steals focus from the footnote; on macOS, the view switch to Normal kicks the cursor out. Both cause `Selection.Range` to resolve to body text instead of the footnote.
- New `GetStoredRange()` public getter on both Engines returns `m_OriginalRange.Duplicate`. Detection and replacement now use it for non-body stories (`HasStoredSelection() And GetStoredStoryType() <> wdMainTextStory`), falling back to `Selection.Range` for body text.

### 6. VBA Code Change

**`IsMacOS()` Made Public (Unified Engine Only)**
- The Unified Engine's `IsMacOS()` function was changed from `Private` to `Public` with a bogus `Optional` parameter to hide it from the Macros menu.
- This allows the Unified Interface form to branch alert text at runtime based on the current platform (macOS menu path vs. Windows Alt+F8).
- The macOS Engine's `IsMacOS()` remains `Private` since `ASEntry.bas` always knows it is running on macOS.

**Installer Refactoring**
- Language preference detection consolidated in the Launcher module. Both Installers now delegate to `GetLanguagePreference()` in the Launcher instead of duplicating the detection logic.

### 7. Known Limitation: macOS Macros Dialog (resolved in 2.0.4 §3)

- In the macOS-only distribution, GreekTranscoder macros do not appear in Word's Tools > Macro > Macros… dialog until the macOS application has been opened at least once from the Ribbon during the current Word session.
- Once the application is launched from the Ribbon, Word for Mac rebuilds its internal state and macros appear for the rest of the session (see "VBA Bugs and Quirks" below).
- All macros remain fully functional from the Ribbon, but `GreekTranscoder_RemoveQuoteMarkers` is only available via the Macros… dialog.

---

## Version 2.0.2: 2026.02.02

### 1. Language-Aware Alerts

**Monolingual Alert Display**
- Whenever possible, all user-facing alerts now respect the saved language preference (English or French).
- When a preference is set, alerts are displayed in the selected language only.
- When no preference is set (first run or preference cleared), alerts fall back to bilingual display (English + French) for accessibility.
- `If sLang = "en"/ElseIf sLang = "fr"/Else` three-branch pattern across all alert functions in all VBA modules (Launcher, Engine, Installer, Interface) and the macOS HTML form.

**Language Preference Infrastructure**
- Added `GetLanguagePreference()` function to Engine and Installer modules for reading saved preferences.
- macOS: reads from sandbox path `~/Library/Application Support/GreekTranscoder/language.txt` (where `~` is Word's sandboxed HOME).
- Windows: reads from Registry `HKCU\Software\VB and VBA Program Settings\GreekTranscoder\Preferences\Language`.
- Returns "en", "fr", or "" (empty for bilingual fallback).

**Word/System Language Fallback (First Run)**
- When no preference file exists, alerts now detect the user's language from Word or the OS.
- VBA modules (Engine, Installer): fall back to Word's UI language via `Application.Language`.
- AppleScript: falls back to macOS system language via `defaults read -g AppleLanguages`.
- The detected language is saved automatically, so subsequent runs use the file-based preference.

### 2. Smarter Startup Validation

**STARTUP Load Warning (Windows-only)**
- New `AutoExec` macro in the Installer modules runs automatically on Windows when the templates load from STARTUP as add-ins.
- Triggers `CheckInstallation` and displays warnings immediately.
- Note: `AutoExec` must be `Public` to function, so it appears in the Macros menu on both platforms; this is harmless.

**Improved Case 0: Wrong Platform Check (macOS Installer)**
- Previously: opening the macOS-only template on Windows always showed "Wrong Version Installed" error.
- Case 0a (new): Wrong platform, but correct version installed = informational message ("Wrong Version for This Platform").
- Case 0b: Wrong platform, correct version not installed = error with replacement guidance.

**Improved Case 2: Template Location Check**
- Previously: any template opened from outside the Startup folder triggered a "Not Installed" error.
- Case 2a (new): Running from outside, but installed = informational message ("Running from Outside Startup Folder").
- Case 2b: Running from outside, not installed = error with installation guidance.

**Ribbon Button Warning**
- When the macOS-only template is used on Windows, clicking the Ribbon button now displays a "Wrong Version" warning.
- Detection uses `PingmacOS` signature function.

### 3. Improved Pre-flight Validation Checks

**New Pre-flight Check: Template Documents Rejected**
- GreekTranscoder is designed to convert text in regular documents, not in template files.
- New Check 2b rejects `.dotm`, `.dotx`, and `.dot` template files with a bilingual alert.
- See v2.0.0 §2 for the full list of pre-flight checks.

### 4. VBA Bug Workarounds

**#If Mac Compile-Time Directive Bug**
- VBA's `#If Mac`/`#If Not Mac` compile-time directives do not work reliably when a template is opened via File > Open (see "VBA Bugs and Quirks" below).
- Workaround: replaced compile-time checks with runtime `IsMacOS()` function (`Application.PathSeparator = "/"`) in the macOS-only Installer module where platform detection is critical.

**Selection.Font.Name Fails Inside HTTP(S) Hyperlinks**
- Accessing `Selection.Font.Name` inside an HTTP(S) hyperlink causes Word to attempt URL resolution and generates an initialization error (see "VBA Bugs and Quirks" below).
- Workaround: new `IsSelectionInHyperlink()` helper duplicates the selection range, expands to word level, then checks for hyperlinks. If detected, font pre-fill is skipped and the Source Font dropdown is left empty.

### 5. Interface Fixes

**macOS VBA Form: Resizing and Helvetica Font**
- Form scaled up from 560×495 to 660×584 for better readability on Retina displays.
- Added programmatic font assignment via private constant in .frm file.
- Default font is now Helvetica (14pt labels, 13pt comboboxes, 11pt copyright).

**Windows VBA Form: Segoe UI Font and Resizing**
- Replaced Arial with Segoe UI (11pt labels, 10pt comboboxes, 9pt copyright).
- Form scaled down from 660×584 to 500×440 with all control positions recalculated.

**Windows VBA Form: Language Loading Order**
- Fixed bug where the homonymous font warning (Hellenica/Odyssea) was displayed before the language preference was loaded. Moved language loading earlier in `UserForm_Initialize`, before font auto-detection.
- The warning is now displayed in the user's preferred language instead of always being bilingual.

**Alert Message Review**
- Reviewed and harmonized all alert messages across both Windows and macOS versions for consistent content, formatting, and bilingual presentation.

### 6. New Utility Module: Remove Quote Markers

**Purpose**
- GreekTranscoder's marker system preserves typographical quote information (curly quotes, guillemets) when converting through legacy Greek encodings that only support straight quotes.
- The new `GreekRemoveQuoteMarkers` module provides a way to strip these markers, "dumbing down" the text to plain quotes for users who prefer or need this.

**Usage**
- Run the macro `GreekTranscoder_RemoveQuoteMarkers` from the Macros menu (Tools > Macro > Macros…).
- The macro displays a warning before proceeding, as this is a one-way, destructive operation.
- If no selection, processes the entire document including footnotes, endnotes, headers, etc.

---

## Version 2.0.1: 2026.01.26

### 1. Startup Validation

**Version Conflict Detection**
- New startup checks detect installation issues before any conversion.
- All alerts are bilingual and offer to reveal/open Word's Startup folder.
- Detection uses platform-specific no-op functions (`PingmacOS`, `PingUnified`) as module signatures.

**New Startup Checks**
- Case 0: Wrong platform — macOS-only template on Windows (macOS Installer only).
- Case 1: Startup folder missing or not configured.
- Case 2: Template not in Startup folder.
- Case 3: Both Unified and macOS-only templates installed (Unified Engine and macOS application).
- Case 4: v1.x template coexisting with v2 (informational warning).

**Installer Module Fork**
- macOS-only `GreekTranscoder__Installer.bas`: includes Case 0; Windows code paths removed.
- Unified `GreekTranscoder__Installer.bas`: retains platform conditionals.

### 2. Interface Cleanup

- Standardized folder-action verbs across platforms and languages.
- Fixed inconsistent NBSP usage around "/" in bilingual alert titles.

---

## Version 2.0.0: 2026.01.24

### 1. Critical Bug Fixes (Functional)

**Story Iteration: Footnotes & Endnotes**
- Fixed broken footnote/endnote/header/footer/comment processing caused by incomplete story iteration that only processed the first story of each type instead of following Word's `NextStoryRange` chain.
- Implemented `Selection.Range.Duplicate` to preserve the selection before UserForm steals focus.
- Worked around a bug where `Selection.StoryType` incorrectly returns `wdMainTextStory` when UserForm is displayed.

**Document Safety**
- Implemented document versioning system with Yes/No/Cancel prompts.
- Added comprehensive error handling around all `SaveAs` operations with automatic fallback to versioned filenames (`xcoded2`, `xcoded3`, etc.).

**Track Changes Detection**
- Implemented post-conversion detection of Track Changes corruption caused by the unreliable `TrackRevisions` property (see "VBA Bugs and Quirks" below).
- Critical warning with recovery instructions displayed when corruption detected; document not saved automatically.

**Locked File Detection**
- Implemented `GetAttr()` pre-flight check to detect locked files before conversion (see "VBA Bugs and Quirks" below).
- Two check points: Launcher (source document) and `ASEntry`/`frm` (`xcoded` overwrite scenario).

**Unicode Transcoding**
- Fixed 40 records (Modern Greek tonos vowels, non-combining diacritics, combining accents) being incorrectly excluded from Unicode-to-legacy conversion functions.
- Fixed `UnicodeComposing` field inconsistencies (mixed TLG/scholarly characters) causing bidirectional conversion failures.
- Resolved duplicate character mappings causing conversion conflicts (KORONIS/PSILI, MIDDLE DOT/ANO TELEIA).
- Added missing reverse Unicode conversion functions for scholarly-to-NFC transformations.
- Fixed composing mode not properly decomposing composed characters.

**Checker Functions and Malformed Record Sorting**
- Systematic verification and debugging of all initial "Checker" functions that normalize malformed character sequences before conversion.
- Analyzed sort order requirements for malformed records to ensure longer patterns are processed before shorter ones that could match prematurely.

**Cross-platform Encoding Fix**
- Converted all accented French characters in string literals to `ChrW()` calls to prevent encoding corruption when transferring files between macOS and Windows and to allow for proper French and English typography.

**Word 2011 for Mac Path Bug Workaround**
- Implemented detection and workaround for a Word 2011 for Mac `ActiveDocument.Path` bug (see "VBA Bugs and Quirks" below). Applied defensively to both codepaths as a no-op safeguard.

**Quotation Mark Handling**
- Implemented comprehensive lossless quotation mark transcoding system using marker sequences.
- Preserves opening/closing distinction for curly quotes (`""` `''`) and guillemets (`«»`) through "dumb" encodings that use a single character for both.
- Marker position encodes direction: marker AFTER quote = left/opening, marker BEFORE quote = right/closing.
- Markers: `!` for plain guillemets, NBSP for English curly quotes, NBSP×2 for French guillemets (actual NBSP present), `!!!`/`!!`/`!` for Titus (no NBSP support).
- BetaCode uses TLG codes (`"6`/`"7`/`"3`) + NBSP/`!` markers; other legacy encodings use their native quote character + markers.
- SPIonic is inherently lossy and marker sequences conflict with its NBSP + diacritic system for capitals.
- Quick reference master table:

| Characters | Unicode       | BetaCode  | Titus      | Other Legacy |  
| ---------- | ------------- | --------- | ---------- | ------------ |  
| «+NBSP     | U+00AB U+00A0 | `"6`+NBSP | char+`!!!` | char+NBSP×2  |  
| «          | U+00AB        | `"6`+`!`  | char+`!`   | char+`!`     |  
| NBSP+»     | U+00A0 U+00BB | NBSP+`"6` | `!!!`+char | NBSP×2+char  |  
| »          | U+00BB        | `!`+`"6`  | `!`+char   | `!`+char     |  
| "          | U+201C        | `"7`+NBSP | char+`!!`  | char+NBSP    |  
| "          | U+201D        | NBSP+`"7` | `!!`+char  | NBSP+char    |  
| '          | U+2018        | `"3`+NBSP | char+`!`   | char+NBSP    |  
| '          | U+2019        | NBSP+`"3` | `!`+char   | NBSP+char    |  

---

### 2. Major Architectural Changes

**Engine Rewrite**
- Complete rewrite with modular helper functions replacing monolithic code.
- Restructured `CharConverter` function.
- New platform strategy separating macOS and Windows codepaths.
- Added optional `lFindFontColor` parameter to `CharConverter` for find-by-color operations.

**Public/Private Function Architecture**
- Converted monolithic `Public` functions to `Public` dispatcher + `Private` main function pattern following the architecture already used by complex encodings (Unicode, SuperGreek, LaserGreek, etc.).

**macOS HTML Form Interface**
- Created AppleScriptObjC + `WKWebView` solution to provide a modern, reliable interface on macOS.
- The original VBA UserForm remains functional on macOS but UserForms cannot be edited any longer in the Visual Basic Editor on macOS, making maintenance impossible without a Windows machine.
- The native macOS application hosts an HTML form in a `WKWebView`, providing pixel-perfect rendering and full editability.
- `WKScriptMessageHandler` implementation for JavaScript-to-AppleScript communication.
- Custom message dialog system compatible with `WKWebView` modal constraints.
- `ASEntry` bridge module for AppleScript-to-VBA parameter passing.
- Critical error handling with automatic quit: the standalone macOS app quits after displaying bilingual alerts for "Word not running" (at startup) and "VBA modules not installed" conditions.
- The HTML form intentionally replicates the VBA UserForm's visual design to ensure consistency across platforms.

**Unified Cross-Platform Architecture**
- Both Windows/macOS and macOS-only versions share the same VBA conversion engine (all transcoder modules, helper functions, and core logic).
- Platform differences are isolated to the interface layer: VBA UserForm on Windows/macOS, AppleScriptObjC + HTML on macOS.
- Validation logic synchronized between HTML form (macOS-only) and VBA form (Windows/macOS) to ensure identical behavior.

**New Launcher Module**
- Created cross-platform initialization module.
- Implemented macOS app path discovery and persistence in `~/Library/Containers/com.microsoft.Word/Data/Library/Application Support/GreekTranscoder/`.
- Implemented Windows folder writability fallback chain.

**Pre-flight Validation Checks**
- Check 0: Word must be running (macOS standalone app only, uses System Events to check without launching Word).
- Check 1: Document must be open (macOS only).
- Check 2: Document must not be empty.
- Check 3: Document must be saved at least once.
- Check 4a: Document must be unlocked in Finder/File Explorer (`xcoded` files only).
- Check 4b: Document must not be protected (Word protection).
- Check 5: Output folder must be writable.
- Check 6a: Document must not contain pending tracked changes.
- Check 6b: Track Changes must be disabled.
- Check 7: Document format must be compatible (RTF, TXT, HTML, PDF blocked).
- Check 8: Master Documents with unexpanded subdocuments warning.
- Check 9: Field codes display warning with OS-specific shortcuts (Alt+F9/Option+F9).
- Check 10: Source font must exist in document.

**Internal Validation Checks**
- Check 1: Font list must load successfully.
- Check 2: Array initialization must succeed.

---

### 3. New Features

**New Encoding Support**
- Implemented BibleWorks transcoder and added BibleWorks fonts (Bwgrki, Bwgrkl, Bwgrkn).
- Implemented Titus transcoder and added Titus fonts (Titus Greek, TITUS-Griechisch, TITUS GRIECHISCH).

**Unicode Normalization Options**
- Implemented four distinct Unicode modes: Composed Scholarly, Composed NFC, Composing Scholarly, Composing TLG.
- NFC and Composing options being mutually exclusive, only two checkboxes are needed to control all four modes.

**Ribbon Support**
- Full Ribbon integration for both macOS and Windows versions of Microsoft Word.

**Font List Updates**
- Fonts are now grouped by encoding.
- Removed obsolete fonts: Arial Unicode MS, Garamond Classical, GentiumAlt, GR Andale Mono, GR Cambridge, GR Lucida Sans, GR Mellonta, GR Oxford, GR Times New Roman, GR Uncial, Thryomanes, TITUS Cyberbit Basic, Vusillus Old Face.
- Added new (mostly Unicode) fonts as modern alternatives: Adobe Text Pro, Alfios, Anaktoria, AncientGreekBetaCode (Beta Code), Arial, Aristarcoj (WinGreek, with source warning due to font's ability to display both WinGreek and Unicode text), Arno Pro, BosporosU, Brill, EB Garamond, Calibri, Gentium Book Plus, Gentium Plus, GFS DidotClassic, GFS Porson, Hypatia Sans Pro, KadmosU, Minion 3, Noto Sans, Noto Serif, Palatino (macOS version), SBL Greek.

**Source-Only Font Filtering**
- Implemented source-only font filtering: fonts with known rendering issues are excluded from the target dropdown while remaining available as source fonts for conversion.
- Source-only fonts (available in source dropdown, excluded from target): SGRead, Aisa, Aristarcoj, Greek, Code2000.
- Expert Mode only fonts (removed from both dropdowns, accessible only via Expert Mode): Bosporos, Kadmos, BSTGreek, IsminiPC, Ismini Regular.
- Expert Mode warnings trigger when these fonts are manually entered as target: incomplete character sets (BSTGreek, Code2000, SGRead), NBSP collision in older versions (Bosporos, Kadmos), missing NBSP glyph breaking marker system (Aristarcoj), display problems (Aisa, Greek, IsminiPC, Ismini Regular).

**Greek Beta Symbol Handling**
- Automatic cleanup of orphaned GREEK BETA SYMBOL characters (U+03D0) in Unicode-to-Unicode conversions: when a target font supports U+03D0, any instances left in substitution fonts (like Cambria) are switched to the target font.
- New warning when converting from Unicode to any legacy encoding: detects GREEK BETA SYMBOL characters (used in the French editorial tradition as medial betas) and offers to convert them to regular GREEK SMALL LETTER BETA characters (U+03B2). If declined, they remain in their original font and are colored in red as unconvertible characters.

**BetaCode/SPIonic Digit Cleanup**
- These encodings use digits as control character modifiers; unconverted digits are colored red by the catch-all function.
- Post-conversion cleanup finds red digits in any font (not just the source font) and normalizes them to target font with automatic color. This handles digits that fell through from prior conversions and remained in a different font.
- Respects selection boundaries in Selection mode.

**GreekBetaSymbol Utility**
- Integrated utility for two-way conversion between GREEK SMALL LETTER BETA (β: U+03B2) and GREEK BETA SYMBOL (ϐ: U+03D0).
- Using curly betas as medial betas is a French typographical convention dating back to the Renaissance.
- `GreekBetaSymbol`: converts medial betas to beta symbols using context-aware detection (only converts betas following Greek letters or hyphens).
- `GreekBetaSmall`: converts all beta symbols back to small letter betas.
- Both functions respect the current selection if any text is selected, otherwise process the entire document.
- Accessible via dedicated Ribbon buttons.

---

### 4. Database Fixes

**Character Mapping Corrections**
- Fixed composed character variants "v" and "^" in SGreek.
- Fixed `UnicodeComposing` field: standardized to scholarly characters (varia, oxia, psili).
- Fixed `UnicodeMalformed` field for proper checker function operation.
- Added 24 new character mappings for NT apparatus symbols and non-combining diacritics.
- Corrected UPSILON and ALPHA record `UnicodeComposing` values.
- Improved quotation marks mappings to make their lossless transcoding possible.

**WinGreek and Unicode Variant Symbol Normalization**
- Added `WinGreekAlt` values to 5 canonical Greek letter records (SMALL LETTER THETA, EPSILON, KAPPA, RHO and PHI) to normalize WinGreek variant symbol positions `ChrW(2)` through `ChrW(6)` to standard letters during conversion.
- Added `SGreekAlt` `ChrW(74)` to GREEK SMALL LETTER THETA record for variant normalization.
- Added WinGreek `ChrW(1)` to LUNATE SIGMA SYMBOL record (U+03F2).
- Added `UnicodeMalformed` entries to normalize 5 mathematical Greek variant symbols (U+03D1 THETA SYMBOL, U+03F5 LUNATE EPSILON SYMBOL, U+03F0 KAPPA SYMBOL, U+03F1 RHO SYMBOL, U+03D5 PHI SYMBOL) to their standard Greek letter equivalents.
- Added `UnicodeMalformed` entries to normalize spacing diacritics (U+02D8 BREVE, U+00AF MACRON) to TLG metrical characters (U+23D1 METRICAL BREVE,  U+2013 EN DASH).
- Added `UnicodeMalformed` entry to normalize U+2010 HYPHEN to U+002D HYPHEN-MINUS for compatibility.
- Deleted redundant GREEK THETA SYMBOL record.

**Duplicate Resolution**
- Resolved KORONIS/PSILI conflict (PSILI takes precedence).
- MIDDLE DOT vs ANO TELEIA (scholarly default via processing order).
- Of 89 duplicate entries found, 24 causing conversion conflicts were fixed.

---

### 5. Interface Improvements

**Installation Helper**
- New `GreekTranscoder__Installer` module detects when template is opened from outside Word's Startup folder and displays bilingual installation guidance.
- Offers to reveal Word's Startup folder in Finder (macOS) or File Explorer (Windows) for easy template installation.
- On Windows, if the Startup folder does not exist, offers to create it automatically before revealing.
- On macOS, if the Startup folder has not been configured, displays instructions for setting it via Word's preferences (File Locations).
- macOS standalone app: "Reveal" button available in the "VBA modules not installed" alert, with fallback instructions if Startup folder is not configured.

**Common Features**
- User's language preference saved (Windows: Registry; macOS: `~/Library/Application Support/GreekTranscoder/language.txt`).
- Selection detection logic improved (insertion point vs actual selection).
- Default button standardized to "Yes/Continue" (first button) across all confirmation dialogs for consistent keyboard navigation.
- Dynamic encoding descriptions in both English and French.
- Comprehensive tooltips.

**Validation Dialog Improvements**
- Consolidated composing diacritics warning into single pre-validation check, eliminating duplicate warning blocks from conversion dispatcher.
- Implemented complete 8-case Unicode-to-Unicode confirmation dialogs with detailed explanations:
  - Same font: Cases 1–4 (no options, NFC, composing scholarly, composing TLG)
  - Different fonts: Cases 5–8 (same four combinations, with font-switch hint where applicable)
- Validation order synchronized between VBA form and HTML form.

**macOS HTML Form**
- AppleScript WKWebView integration.
- macOS sandbox permission error handling (error #5487): Word runs in a sandboxed environment and may require folder access via the "Grant File Access" dialog; clear bilingual instructions provided.
- Keyboard shortcut: Cmd+Return implemented for macOS form (workaround for WKWebView consuming Enter).
- Selection state validation at conversion time with user prompts when selection changes after form launch.

**Windows/macOS VBA Form**

- Windows-only: WinGreek encoding warning for C1 control character positions (129, 141, 143, 144, 157).
- Fixed bug where Unicode options (Use Composing Characters, TLG Usage/NFC Normalization) remained visually checked but disabled when switching from a Unicode target font to a legacy target font.
- The checkbox state and underlying boolean variables are now properly reset when the target encoding changes to non-Unicode.

**Warning Messages**
- Track Changes corruption: bilingual critical warning with 5-step recovery instructions.
- Locked file: bilingual warning with unlock instructions.

---

### 6. Code Quality Improvements

**Error Handling**
- Comprehensive error handling replacing prior silent suppression.
- Date-based error logging with session tracking.

**Defensive Programming: Engine Hardening**
- `StoryRanges` validation with automatic fallback to main body conversion when document structure is corrupted.
- Find object state cleanup via `.ClearFormatting` after each processing operation (avoids re-adding formatting criteria).
- Application-level Find state cleanup (`Selection.Find`) ensures Word's Find/Replace dialog is completely clean after conversion.
- Session-aware warning system (warnings shown only once per conversion session).

**AutoFormat Options Preservation**
- All 25 Word `AutoFormat` options (13 `AutoFormatAsYouType` + 12 `AutoFormat`) are now saved at conversion start and restored on completion.
- Previously, GreekTranscoder disabled these options during conversion but did not restore the user's original settings.
- `ScreenUpdating` and `DisplayAlerts` application states are now saved and restored instead of being systematically set to `False` then `True`.

**Defensive Programming: Error Recovery**
- Range object cleanup in error handlers to prevent orphaned references.
- `GTParams` property deletion verification with non-critical error logging.

**Defensive Programming: AppleScript-VBA Communication**
- JSON-safe font name escaping for WebView initialization data.
- Pre-flight parameter validation before Word macro calls.
- Specific error handling: immediate failure for fatal errors (-1728 Word not accessible, -10810 Word not found, -1708 VBA modules not installed), retry logic for transient errors (4198).

**General Code Cleanup**
- Consolidated boolean flags and font/encoding lists using arrays and helper functions.

**Typography Compliance**
- French typography: non-breaking space (and narrow non-breaking space where applicable in the HTML form) before high punctuation (? ! : ;), proper guillemets with interior spaces (« … ») and curly apostrophes.
- English typography: curly quotes and curly apostrophes.

**Documentation**
- Inline documentation of Word VBA bugs discovered during development.
- Module identification blocks in all files.
- Improved comments in VBA code.
- Updated web site and documentation.
- GPL 3.0 license update.

---

## Word VBA Bugs and Quirks

This section documents Word VBA bugs and quirks discovered during GreekTranscoder development. These are provided as a reference for developers working with Word VBA, particularly on macOS.

### Find/Replace Behavior

**FindText:="" Matches Paragraph Marks**
- Word's Find with `.Text = ""` (format-only search) matches paragraph marks in addition to text characters. This causes two distinct failure modes:
  1. **Selection mode**: when the selection contains paragraph marks, font-only searches fail or return incorrect results.
  2. **Format-only detection**: paragraph marks whose `pPr/rPr` carries the target formatting (e.g., font color set by a prior format-only replace) are matched even though those properties are invisible in Word's UI and unreachable by Word's own Find & Replace dialog. This causes false positives.
- The `^?` special character and the equivalent `?` wildcard also match paragraph marks and cannot be used as alternatives.
- Fix: use `.Text = "^$"` (any single letter) for letter-only searches, or `.MatchWildcards = True` with explicit character class ranges (e.g., `[ChrW(32)-ChrW(255)]`) for searches that must include non-letter characters such as NBSP or punctuation. Both approaches exclude control characters including the paragraph mark (CR = 13).
- `"^$"` was the original v1.0 method to detect the `findFont`'s presence in the document and has proven reliable for 20+ years.

**Word Find Normalizes Unicode Characters**
- Word's Find function treats certain Unicode characters as equivalent, even when they are distinct code points.
- Example: GREEK BETA SYMBOL (ϐ: U+03D0) and GREEK SMALL LETTER BETA (β: U+03B2) are treated as the same character in normal searches.
- This causes false positives when searching for specific Unicode variants.
- Workaround: use `.MatchWildcards = True` to force exact character matching.

**Wildcard Character Ranges Use Windows-1252 Ordering on Windows**
- In `.MatchWildcards = True` mode, bracket expressions support ranges with hyphens (e.g., `[^0135-^0140]` for "characters 135 through 140"). On macOS, Word evaluates the range endpoints by raw character code: 135 < 140, valid. On Windows, Word resolves `^0nnn` codes through Windows-1252 before comparing, mapping C1 control positions (128–159) to scattered Unicode codepoints. If the Windows-1252 mapping of the start character has a higher Unicode value than the end character, the range is backwards and Word raises Error #5590 ("The Find What text contains a range that is not valid").
- Example: `[^0135-^0140]` — on Windows, `^0135` maps to U+2021 DOUBLE DAGGER (codepoint 8225) and `^0140` maps to U+0152 LATIN CAPITAL LIGATURE OE (codepoint 338). Since 8225 > 338, the range is invalid.
- This affects only the five Windows-1252 "holes" at positions 129, 141, 143, 144, 157 (which have no defined mapping) and any range whose endpoints, after Windows-1252 resolution, are not in ascending Unicode order.
- The bug is silent on macOS and may go undetected for years if testing is limited to one platform.
- Workaround: replace hyphen ranges with explicit character enumeration (`[^0135^0136^0137^0138^0139^0140]`). This avoids range interpretation entirely and works identically on both platforms.

**Ghost-Red Characters: Colored Structural Marks Become Unfindable**
- A format-only replace (`findChar:=""`, `replaceChar:=""` with color formatting) colors structural characters (paragraph marks, line breaks, section breaks) and Unicode exotic spaces (U+2000–U+200A, U+202F, U+205F).
- However, a subsequent Find operation with a color filter (e.g., `Font.Color = wdColorRed`) cannot find these characters, even though the Font dialog confirms they carry the color. A Find for the font name alone (without color filter) works.
- The characters are "ghost colored": the formatting exists in the document XML (`pPr/rPr`) but is invisible in Word's UI and unreachable by Find.
- Workaround: use a font-only search (no color filter) with a wildcard character class to find and reset these characters. The `^&` replacement text preserves the character while changing only the formatting.

**Document's Final Paragraph Mark Is Immune to Find/Replace**
- The last paragraph mark in a Word document cannot be found or modified by any Find/Replace operation, even format-only replaces that work on all other paragraph marks.
- It can be colored by a blanket format-only replace (`findChar:=""`), but once colored, it cannot be reset by any Find/Replace operation — not even the same kind of format-only replace targeting its font.
- The `ActiveDocument.Content.Characters.Last` Range object provides direct access to this character and allows reading and writing its font properties (`.Font.Name`, `.Font.Color`). This is the only reliable method.
- The `Collapse wdCollapseEnd`/`MoveStart wdCharacter, -1` approach does NOT land on the same Range as `Characters.Last` and fails to modify the mark.

**Format-Only Find/Replace Overflows Selection Boundary**
- In Selection mode, a format-only Find/Replace with `findChar:=""` and `replaceChar:=""` and `Wrap:=wdFindStop` does not stop at the end ("Down") or at the beginning ("Up") of the selection: it continues past the selection boundary and processes the rest of the document downward or upward.
- Workaround: before the empty-string replacement, perform a character-specific replacement on the first character of the selection (`Selection.Characters(1).Text`), replacing it with itself in the target font. This "anchors" Word's Find engine to the selection boundary. The subsequent empty-string replacement then respects the end or the beginning of the selection as expected.

### Document Format & XML

**XML 1.0 Control Characters Silently Stripped on .docx Save**
- The `.docx` format stores document content as XML 1.0, which only permits three control characters below U+0020: TAB (U+0009), LINE FEED (U+000A), and CARRIAGE RETURN (U+000D). All other control characters in the C0 range (U+0000--U+0008, U+000B--U+000C, U+000E--U+001F) are invalid and Word silently discards them when saving.
- Characters created via `ChrW()` in VBA exist in Word's in-memory document model and participate normally in Find/Replace operations during the current session. However, they do not survive a save/reopen cycle: they are stripped from the XML on save with no warning or error.
- This affects any encoding that maps glyphs to control character positions. In GreekTranscoder, three WinGreek characters were affected: `ChrW(7)` BELL (left guillemet), `ChrW(28)` FILE SEPARATOR (left single curly quote), and `ChrW(29)` GROUP SEPARATOR (right single curly quote). In-session conversions appeared to work because the characters were present in memory, but reopening a saved intermediate .docx file showed the characters had vanished.
- This limitation is specific to the Office Open XML formats (`.docx`, `.docm`, `.dotx`, `.dotm`). The legacy binary format (`.doc`) stores text as raw bytes and preserves all control characters.
- Workaround: remap affected characters to XML-safe codepoints in the C1 range or above (see version 2.0.5 §1 for details). The legacy `.doc` binary format is unaffected and preserves all control characters, which is why GreekTranscoder 2.0.5 now saves WinGreek working copies in `.doc` format.

### Track Changes & Document State

**TrackRevisions Property Unreliable**
- In certain document states, reading `TrackRevisions` returns False when TC is actually ON.
- Setting `TrackRevisions = False` may silently fail.
- Workaround: check `Revisions.Count > 0` after conversion to detect corruption.

**Selection.Font.Name Fails Inside HTTP(S) Hyperlinks**
- Accessing `Selection.Font.Name` when the cursor or selection is inside an HTTP(S) hyperlink causes Word to attempt URL resolution and generates an initialization error.
- `mailto:` and internal bookmark links are not affected.
- `Selection.Hyperlinks.Count` returns 0 even when the cursor is inside a hyperlink (it only counts hyperlinks fully contained within the selection).
- Workaround: new `IsSelectionInHyperlink()` helper function duplicates the selection range, expands to word level, then checks for hyperlinks. If detected, font pre-fill is skipped and the Source Font dropdown is left empty.

### File System & Paths

**Word Error 5155 on Locked Files**
- When saving a Finder-locked file, Word shows error 5155 followed by two `SaveAs` dialogs.
- VBA cannot intercept between dialogs; control returns only after both complete.
- Workaround: pre-flight `GetAttr()` check before any conversion work.

**ActiveDocument.Path Returns FullName (Word 2011 for Mac)**
- In Word 2011 for Mac (version 14), `ActiveDocument.Path` returns the full file path instead of the directory path.
- Example: returns `/Users/john/Documents/MyDoc.doc` instead of `/Users/john/Documents`.
- This causes malformed paths when constructing save locations for the versioning system.
- Detection: if `ActiveDocument.Path = ActiveDocument.FullName`, the bug is present.
- Workaround: extract directory using `InStrRev()` to find the last path separator.

**Environ("HOME") Returns Sandboxed Path on macOS**
- Inside Word's sandbox on macOS, `Environ("HOME")` returns the sandboxed home path, not the real user home.
- Real HOME: `/Users/username`
- Sandboxed HOME: `/Users/username/Library/Containers/com.microsoft.Word/Data`
- Code that constructs paths by appending `/Library/Containers/com.microsoft.Word/Data/...` to `Environ("HOME")` creates doubled, invalid paths.
- Workaround: use `Environ("HOME") & "/Library/Application Support/..."` since the sandboxed HOME already points to the container's data directory.

**Full Disk Access Does Not Affect Word Sandbox**
- macOS Full Disk Access (FDA) controls access to privacy-protected areas (Mail, Messages, Safari data, etc.). Word's App Sandbox is a separate permission system: VBA file operations are governed by the sandbox, not FDA.
- When Word needs folder access, it displays a "Grant File Access" dialog; FDA status is irrelevant.

### MacScript & AppleScript

**MacScript Error 5 With Non-Trivial AppleScript Expressions**
- VBA's `MacScript()` function in Word for Mac raises Error 5 ("Invalid procedure call or argument") when the AppleScript expression involves paths containing spaces, regardless of quoting method.
- `do shell script` commands with single-quoted paths, `quoted form of` variables, and backslash-escaped spaces all fail identically when the path contains a space (e.g., `/Applications/GreekTranscoder 2.app`). The same commands succeed with space-free paths (e.g., `/Applications/Safari.app`).
- `tell application "System Events"` commands fail unconditionally (sandbox blocks inter-process communication), even with simple space-free targets.
- `PlistBuddy` as an alternative to `defaults read` also fails with spaced paths.
- Simple expressions (`MacScript("return ""ok""")`, `MacScript("do shell script ""echo ok""")`) work reliably.
- Workaround: for file reads, use VBA's native `Open`/`Line Input` statements instead of shelling out via `MacScript`. For launching applications, `MacScript("do shell script ""open "" & quoted form of ""path""")` works because `open` is a simple single-argument command that does not require path quoting within AppleScript itself.

### Compile-Time Directives

**#If Mac Compile-Time Directive Unreliable**
- VBA's `#If Mac` and `#If Not Mac` compile-time conditional compilation directives do not work reliably when a template is opened via File > Open.
- When a template loads from the Startup folder (normal operation), the directives work correctly.
- When the same template is opened manually (File > Open or double-click), code from both `#If Mac` and `#If Not Mac` branches may execute.
- This appears to be a bug in how Word evaluates compile-time constants for manually opened templates.
- Workaround: use runtime platform detection instead: `If Application.PathSeparator = "/" Then` (macOS) or `If Application.PathSeparator = "\" Then` (Windows).

**Function Inside #If Mac Block Causes Compile Error**
- When a function is defined inside an `#If Mac Then` block but called from code outside that block, Windows VBA raises "Sub or Function not defined" at compile time.
- This occurs because Windows VBA excludes the function definition during compilation, but still compiles the call site.
- Workaround: move cross-platform functions outside `#If Mac Then` blocks, using internal `#If Mac Then/#Else` branches for platform-specific implementation.

**Macros Invisible When Module's Final Code Section Is Inside #If Mac Block**
- When a VBA module's final code section is entirely inside a large `#If Mac Then ... #End If` block with no functions (public or private) defined between the main code and that block, public macros defined in *other* modules of the same project may not appear in the Macros menu on Windows.
- This occurs both when the template is loaded from the STARTUP folder as an add-in and when it is opened manually via File > Open.
- Root cause: unclear, but appears related to how Windows VBA initializes projects when a significant portion of a module is excluded by compile-time conditionals.
- Adding *any* function (even a trivial private function) outside the `#If Mac Then` block causes the macros to appear normally.
- Example: in v2.0.1 macOS-only, the Launcher module ended with `#End If`, hiding the Engine's `GreekTranscoder` macro on Windows. Adding `GetLanguagePreference()` outside the block in v2.0.2 resolved the issue.

**msoLanguageIDUI Constant Prevents Module Loading**
- Using the `msoLanguageIDUI` constant (from the Microsoft Office Object Library) inside a `#If Mac Then` block can prevent the module from loading correctly when the template is loaded from the STARTUP folder.
- Symptoms: `AutoExec` does not fire, yet the same code works when the template is opened manually or when triggered via Ribbon buttons.
- Root cause: the constant may not be resolved during early module initialization when Word loads add-ins from STARTUP.
- Workaround: use `Application.Language` instead of `Application.LanguageSettings.LanguageID(msoLanguageIDUI)`, or use the numeric value directly (`msoLanguageIDUI = 2`).
- Example: `Select Case Application.LanguageSettings.LanguageID(msoLanguageIDUI)` fails silently; `lLangID = Application.Language` followed by `Select Case lLangID` works reliably.

**`Application.Run` Breaks `AutoExec` When Called During STARTUP Loading**
- Calling `Application.Run "MacroName"` during `AutoExec` execution (when templates are loading from STARTUP) can break the `AutoExec` sequence.
- Symptoms: `AutoExec` fires but subsequent code does not execute; the same code works when triggered manually or via Ribbon buttons.
- This affects version conflict detection that uses `Application.Run` to check for signature functions in other templates.
- Workaround: use file-based detection instead of `Application.Run` for checks that must run during `AutoExec`.
- Example: instead of `Application.Run "PingUnified"` to detect if the Unified template is loaded, check `Dir(Application.StartupPath & "/GreekTranscoder 2.dotm") <> ""` to see if it is installed.

### UserForm & UI Rendering (macOS)

**VBA MsgBox Unicode Rendering (macOS)**
- `ChrW(8984)` ⌘ and `ChrW(8997)` ⌥ are displayed as placeholders or underscores.
- Workaround: use text equivalents ("Cmd", "Option").

**VBA UserForm Rendering (macOS)**
- Word for Mac's VBA UserForm implementation has regular rendering issues: garbled text, disappearing controls, incorrect font display.
- These issues are specific to macOS; the same forms render correctly on Windows.
- The Visual Basic Editor on macOS cannot edit UserForms nor view them.
- GreekTranscoder 2's VBA UserForm remains functional but may display visual artifacts on some macOS/Word version combinations.

**Stub UserForm .Show Does Not Raise Error**
- When a template includes a stub UserForm (minimal `.cls` file to prevent compile errors), calling `.Show` on that form does not raise a VBA error, even though the form is not displayed properly.
- This prevents error-trapping approaches from detecting whether a functional form exists.
- Workaround: use alternative detection methods (e.g., checking for module-specific signatures like `PingmacOS`) instead of trying to show the form and catching errors.

**Macros Invisible Without Macro Command Directory on macOS**
- Word for Mac populates the Macros dialog (Tools > Macro > Macros…) from a macro command directory (`<wne:mcds>`) stored in `vbaData.xml` inside the .dotm archive.
- Word for Windows writes this directory only when the project contains a real UserForm (with controls and event handlers). A minimal or empty UserForm is not sufficient.
- When the directory is absent, macros do not appear in the Macros dialog, though they execute correctly from the Ribbon or via `Application.Run`.
- Saving the `.dotm` from Word for Mac always writes the directory, regardless of project structure. This is why re-saving a Windows-built `.dotm` from Word for Mac resolves the issue (and adds ~100–200 KB of platform-specific data, including per-module SRP p-code streams).
- Once the application is launched from the Ribbon, Word for Mac rebuilds its internal state and macros appear for the rest of the session.
- Workaround: inject the `<wne:mcds>` block into `vbaData.xml` as a post-build step.
- This is distinct from the `#If Mac Then` block visibility bug (see "Compile-Time Directives" above), which affects both platforms and is resolved by code placement.

### Module Loading

**Module Name Collision with Multiple Templates Loaded**
- When two templates are loaded simultaneously (e.g., one from STARTUP, one opened manually) and both contain a module with the same name, VBA's module resolution becomes unpredictable.
- Example: calling `GreekTranscoder__Engine.PingmacOS` when both macOS-only and Unified templates are loaded may resolve to the wrong module, causing "Method or data member not found" compile errors.
- This is an edge case that occurs when a user has the macOS-only template in STARTUP and manually opens the Unified template (or vice versa).
- No workaround: users should only have one version of GreekTranscoder installed at a time.

---

*GreekTranscoder 2.0.5 — © 2005–2026 David-Artur Daix*
