4.6 KiB
Capcană: corupere diacritice la editarea .sc2/.vc2 (encoding cp1252)
Partajat între proiectele ROA* (similar cu PROMPT_cautare_vfp.md din acest folder) — capcana
ține de formatul .sc2/.vc2 produs de FoxBin2Prg, nu de un proiect anume.
Descoperit de 2 ori în aceeași sesiune (2026-07-10, în ROAAUTO): odată în
COMUN/clase/cmd_butoane.vc2 (clasa cmd_select_adv), odată în Clase/ofundal_dev.vc2
(meniul principal) — de fiecare dată un agent anterior a editat text-cache-ul cu un tool care
nu scrie cp1252 nativ, și a corupt TOATE caracterele cu diacritice din fișier, nu doar linia
pe care voia s-o schimbe.
De ce se întâmplă
Fișierele .sc2/.vc2 generate de FoxBin2Prg sunt cp1252 (Windows-1252), nu UTF-8
(vezi antetul fiecărui fișier: CPID="1252"). Dacă un editor/tool citește fișierul ca UTF-8
(sau alt encoding), fiecare byte >= 0x80 (diacritic) devine invalid ca secvență UTF-8 și e
înlocuit cu caracterul de replacement U+FFFD. Dacă apoi tool-ul salvează rezultatul tot ca
UTF-8, acel U+FFFD e scris ca 3 octeți UTF-8 (0xEF 0xBF 0xBD) — care, citiți înapoi ca
cp1252 (cum face FoxBin2Prg la write-back), apar ca �. Rezultatul: caracterul original e
ireversibil pierdut (nu mai există în fișier sub nicio formă) — recuperabil DOAR din altă
sursă (git history, backup).
Codebase-ul ROA folosește un hack vechi de "reciclare" a unor caractere cp1252 needependente de Ș/ă/ț (care nu au echivalent direct în cp1252) pentru diacritice românești:
| Literă românească | Caracter folosit (cp1252) | Byte |
|---|---|---|
| ă | ã (a-tilde) | 0xE3 |
| Ă | Ã | 0xC3 |
| ț | þ (thorn minuscul) | 0xFE |
| Ș (majusculă) | ª (ordinal masculin) | 0xAA |
| ș (minusculă) | º (ordinal feminin) | 0xBA |
| î, â | î, â (existente nativ în cp1252) | 0xEE, 0xE2 |
Aceste caractere par "gunoi"/typo la prima vedere într-un editor UTF-8 (ã, þ, ª, º) —
sunt corecte, nu le "corecta" fără să verifici encoding-ul.
Cum se verifică dacă un fișier .sc2/.vc2 e corupt
$bytes = [System.IO.File]::ReadAllBytes("<path>.vc2")
$text = [System.Text.Encoding]::GetEncoding(1252).GetString($bytes)
$text -split "`r`n" | Select-String ([char]0xFFFD) # cauta caracterul de replacement
Dacă apare � (sau $text conține U+FFFD) în output — fișierul are corupere de encoding.
Cum se repară
- Nu edita orbește peste corupere — caracterul original e deja pierdut din fișierul curent.
- Dacă fișierul e sub control de versiune (git) și corupera s-a întâmplat într-o sesiune
anterioară necomisă (deci HEAD-ul git încă are versiunea curată): recuperează originalul
convertind binarul din HEAD în text și comparând:
apoi decodează ambele fișiere (HEAD curat + curent corupt) ca cp1252 și compară linie cu linie (PowerShell, nu
git show HEAD:<cale>.vcx > /tmp/head.vcx git show HEAD:<cale>.vct > /tmp/head.vct # (sau .VCT, dupa caz) powershell -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source /tmp/head.vcx -CacheRoot /tmp/head_outdiffdirect —diff/Bash nu decodează cp1252 corect pentru afișare, deși detectează totuși diferența de octeți). - Reconstruiește fișierul text pornind de la versiunea HEAD (curată), și reaplică DOAR modificările intenționate din sesiunea curentă peste ea (nu invers — nu încerca să "cârpești" fișierul corupt caracter cu caracter, e mai sigur să repornești de la baza curată).
- Scrie rezultatul înapoi ca bytes cp1252 (
[System.Text.Encoding]::GetEncoding(1252).GetBytes(...)), NU ca string UTF-8/Out-Fileimplicit (care scrie UTF-8 sau UTF-16 după caz). - Rulează write-back (
txt2vcx.ps1 -Force) și verifică fidelity check = zero diferențe.
Cum se evită pe viitor
Când editezi .sc2/.vc2 cu tool-uri text (Read/Edit/Write), verifică întâi dacă fișierul
conține diacritice (ã, þ, ª, º, î, â etc.) — dacă da, orice rescrie completă a
fișierului trebuie făcută la nivel de octeți cu encoding cp1252 explicit, nu presupunând
UTF-8 implicit. Editările punctuale (Edit tool, string replace) sunt sigure DOAR dacă tool-ul
păstrează restul fișierului byte-identic (nu rescrie tot fișierul reîncodat).
Vezi și
PROMPT_cautare_vfp.md din acest folder, pasul 3.c — menționează deja riscul ("Headerul
CPID="1252" poate minți...") pe scurt; acest fișier e detalierea completă (tabel de caractere,
pași de recuperare din git).