frm_modific2024, pgfArticole.PAGE3 - editare in memorie, fara scriere in Oracle (aceea ramane S5). - sub-blocul A: cantitate/pret/pret_cu_tva editabile inline, marcaj lmodificat pe linie, coloana valoare pe linie - sub-blocul B: stergere logica de linii (sters/DynamicForeColor gri) si adaugare de linii prin frm_articol_factura, cu alegerea articolului prin caut_articol() - sub-blocul C: bara de totaluri sub grid (total linii convertit RON la cursul documentului, discount de antet editabil, total net), ascunsa pe transfer/custodie; verdict de corelatie ACT/RUL informativ, cu 3 stari - suma ACT: sold net debit-credit, cont pe tip de document (4111 / 418 / 461, iar pe rate/contract 4111, 411 sau 461) - suma RUL: doar ID_TIP_RULAJ = 0, adica miscarile reale; perechile ID_TIP_RULAJ = 3 sunt virtuale (tin locul procesului verbal de schimbare de pret) si nu intra in suma. Corectie cu liniile nestocate, marcata "ajustat" - adaugarea de linii pe document in valuta: dialogul primeste tip_valuta si cursul documentului de pe tvanz, deci pretul se introduce direct in valuta; ofacturare.vc2 ramane neatins - cei 5 apelanti frm_modific2024 (afisjurcom, anaf_efactura, cele doua .sc2 de import) pregatesc cursorul de articole inainte de Createobject, gardat pe SET PROCEDURE - registrul jurnal din ROACONT/ROAGEST ramane neschimbat Teste headless pe MARIUSM_AUTO, suite care isi descopera singure documentele: test_page3_articole 14/2 (cele 2 = artefact de grid nematerializat headless, acoperit pe ecran), test_incarca_vanzare_din_nota 5/0, test_adauga_linie_articol 20/0, test_adauga_linie_valuta 16/0, test_ui_sterge_linie 8/0, test_verdict_act_rul 26/0. docs/todos.txt: punctele 13 si 20, scrise de Marius. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
5.2 KiB
Capcană: corupere diacritice la editarea .sc2/.vc2
Partajat între proiectele ROA* — capcana ține de formatul .sc2/.vc2 produs de FoxBin2Prg,
nu de un proiect anume.
De ce se întâmplă
Fișierele .sc2/.vc2 sunt cp1250 (Windows-1250, Europa Centrală), nu UTF-8 — deși
antetul FoxBin2Prg declară CPID="1252". Eticheta din antet nu corespunde conținutului:
controalele care poartă text cu diacritice au FontCharSet = 238 (Europa de Est), adică VFP
le randează tot ca cp1250. Diferența nu e cosmetică — un ă real scris prin cp1252 nu are
echivalent în acel codepage și s-ar pierde; scris prin cp1250 (encoding-ul real al fișierului)
e pur și simplu octetul 0xE3, corect și stabil.
Dacă un editor/tool citește fișierul ca UTF-8, fiecare byte >= 0x80 (diacritic) devine invalid
ca secvență UTF-8 și e înlocuit cu U+FFFD. Dacă tool-ul apoi salvează tot ca UTF-8, acel
U+FFFD e scris ca 3 octeți (0xEF 0xBF 0xBD) — care, citiți înapoi ca cp1250 (cum face
FoxBin2Prg la write-back), apar ca �. Caracterul original e ireversibil pierdut
(recuperabil DOAR din altă sursă: git history, backup).
Octeții diacriticelor din codebase-ul ROA, cu adevărul (cp1250) și aparența dacă îi decodezi greșit ca cp1252:
| Literă românească | Byte | Aparență dacă decodezi ca cp1252 |
|---|---|---|
| ă | 0xE3 |
ã (a-tilde) |
| Ă | 0xC3 |
à |
| î | 0xEE |
î (identic — zonă comună cp1250/cp1252) |
| Î | 0xCE |
Î (identic — zonă comună cp1250/cp1252) |
| â | 0xE2 |
â (identic — zonă comună cp1250/cp1252) |
| ț | 0xFE |
þ (thorn minuscul) |
| Ș (majusculă) | 0xAA |
ª (ordinal masculin) |
| ș (minusculă) | 0xBA |
º (ordinal feminin) |
Decodate cp1250 (encoding-ul real), aceste litere sunt diacritice românești normale — exact
ce apare în formular când fișierul e sănătos. Par "gunoi"/typo (ã, þ, ª, º) doar
dacă le decodezi cu codepage-ul greșit — nu le "corecta" fără să verifici encoding-ul real.
Cum se verifică dacă un fișier .sc2/.vc2 e corupt
Verificarea se face pe octeți, nu pe text decodat: un codepage single-byte (1250 sau 1252)
mapează fiecare octet la un caracter, deci nu produce niciodată U+FFFD — o căutare de
[char]0xFFFD în textul decodat nu găsește nimic nici pe un fișier stricat. Ce se caută e
secvența de trei octeți pe care a lăsat-o tool-ul care a stricat fișierul:
$b = [System.IO.File]::ReadAllBytes("<path>.vc2")
$n = 0
for ($i = 0; $i -lt $b.Length - 2; $i++) {
if ($b[$i] -eq 0xEF -and $b[$i+1] -eq 0xBF -and $b[$i+2] -eq 0xBD) { $n++; $i += 2 }
}
"EF BF BD (U+FFFD) x $n" # orice valoare > 0 = fisier stricat
Echivalentul din Bash, util și pentru censul complet înainte/după orice editare (vezi
reguli_lucru.md, punctul 7):
od -An -tx1 <path>.vc2 | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c
Censul crește la stricare — un octet cp1250 devine trei octeți de U+FFFD — deci nu urmări
doar scăderile. Decodat cp1250, EF BF BD apare ca ďż˝ în caption.
Cum se repară
- Nu edita orbește peste corupere — caracterul original e deja pierdut din fișierul curent.
- Dacă corupera s-a întâmplat într-o sesiune anterioară necomisă (HEAD-ul git încă e curat):
recuperează originalul convertind binarul din HEAD în text:
Dacă și HEAD e deja corupt (corupera a fost comisă), caută ultima versiune curată cu
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_outgit cat-file blob <commit>:<cale>(din Bash, niciodată cu>din PowerShell 5.1 — adaugă BOM și re-encodează) sausvn cat <fișier>— ambele surse independente de encoding-ul curent al fișierului. Apoi decodează ambele fișiere (versiunea curată + curent corupt) ca cp1250 și compară linie cu linie (PowerShell, nudiff/Bash direct — nu decodează cp1250 corect la afișare, deși detectează totuși diferența de octeți). - Reconstruiește fișierul text pornind de la versiunea curată, reaplicând DOAR modificările intenționate din sesiunea curentă (nu invers — nu cârpi fișierul corupt caracter cu caracter).
- Scrie rezultatul înapoi ca bytes cp1250
(
[System.Text.Encoding]::GetEncoding(1250).GetBytes(...)), NU ca string UTF-8/Out-Fileimplicit. - 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ă
trebuie făcută la nivel de octeți cu encoding cp1250 explicit, nu presupunând UTF-8.
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ă riscul pe scurt; acest fișier
e detalierea completă (tabel de caractere, pași de recuperare din git).