fix vietnamese telex: qu-/gi- onset tone placement and dd+tone
transvi fixes: 1. qu-/gi- onset tone placement. The u after q, and the i after g when a vowel follows, are onset glides rather than the rime nucleus, so the tone must skip them: qua -> quá (was qúa), gia -> giá. The onset was previously passed straight through to the app, so transvi never saw it and toned the glide. Keep the onset in the preedit by adding qu-/gi- clusters to telex.map (mktelex.py onsets(), appended additively to the curated map), and add onsetglide() so transvi skips the glide. gi- with no following vowel keeps i as the nucleus (gì, gìn). 2. A tone key on a vowel-less preedit (e.g. "đ" from dd) now commits the preedit and lets the tone key pass through (eat=0), matching the engine commit-on-passthrough invariant, instead of eating it into the commit. Verified against the running engine: qua/quan/quay/quê/quên/quyển, gia/già/giàu/giữ/giúp/giống, gì/gìn, dd+s; unchanged mua->mùa, của, lúa; all non-qu/gi words byte-identical to before. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
32
vi.c
32
vi.c
@@ -89,12 +89,37 @@ applytone(Rune c, int tidx)
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* In qu- and gi- onsets the u/i is a glide that belongs to the onset,
|
||||
* not the rime, so it must not bear the tone (qua -> quá, gia -> giá).
|
||||
* The i of gi- is only a glide when another vowel follows; otherwise it
|
||||
* is the nucleus itself (gì, gìn). Returns the rune index to skip, or -1.
|
||||
*/
|
||||
static int
|
||||
onsetglide(Str *m)
|
||||
{
|
||||
Rune a, b;
|
||||
int i;
|
||||
|
||||
if(m->n < 2)
|
||||
return -1;
|
||||
a = m->r[0];
|
||||
b = removetone(m->r[1]);
|
||||
if((a == 'q' || a == 'Q') && (b == 'u' || b == 'U'))
|
||||
return 1;
|
||||
if((a == 'g' || a == 'G') && (b == 'i' || b == 'I'))
|
||||
for(i = 2; i < m->n; i++)
|
||||
if(isvowel(removetone(m->r[i])))
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Emit
|
||||
transvi(Im *im, Rune c)
|
||||
{
|
||||
Emit e;
|
||||
Str mapped, pre;
|
||||
int i, tidx, vi, last, penult;
|
||||
int i, tidx, vi, last, penult, glide;
|
||||
Rune v, b1, b2;
|
||||
|
||||
if(!istone(c) && c != 'z')
|
||||
@@ -115,9 +140,12 @@ transvi(Im *im, Rune c)
|
||||
}
|
||||
if(!mapget(im->l->map, &im->pre, &mapped))
|
||||
mapped = im->pre;
|
||||
glide = onsetglide(&mapped);
|
||||
last = -1;
|
||||
penult = -1;
|
||||
for(i = 0; i < mapped.n; i++){
|
||||
if(i == glide)
|
||||
continue;
|
||||
v = removetone(mapped.r[i]);
|
||||
if(isvowel(v)){
|
||||
penult = last;
|
||||
@@ -140,9 +168,7 @@ transvi(Im *im, Rune c)
|
||||
}
|
||||
}
|
||||
if(vi < 0){
|
||||
e.eat = 1;
|
||||
e.s = mapped;
|
||||
sputr(&e.s, c);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user