strans/vi.c
2026-02-08 16:57:52 +09:00

161 lines
3.3 KiB
C

#include "dat.h"
#include "fn.h"
static struct {
Rune base;
Rune tone[5]; /* s f r x j */
} vitone[] = {
{L'a', {L'á', L'à', L'', L'ã', L''}},
{L'â', {L'', L'', L'', L'', L''}},
{L'ă', {L'', L'', L'', L'', L''}},
{L'e', {L'é', L'è', L'', L'', L''}},
{L'ê', {L'ế', L'', L'', L'', L''}},
{L'i', {L'í', L'ì', L'', L'ĩ', L''}},
{L'o', {L'ó', L'ò', L'', L'õ', L''}},
{L'ô', {L'', L'', L'', L'', L''}},
{L'ơ', {L'', L'', L'', L'', L''}},
{L'u', {L'ú', L'ù', L'', L'ũ', L''}},
{L'ư', {L'', L'', L'', L'', L''}},
{L'y', {L'ý', L'', L'', L'', L''}},
{L'A', {L'Á', L'À', L'', L'Ã', L''}},
{L'Â', {L'', L'', L'', L'', L''}},
{L'Ă', {L'', L'', L'', L'', L''}},
{L'E', {L'É', L'È', L'', L'', L''}},
{L'Ê', {L'', L'', L'', L'', L''}},
{L'I', {L'Í', L'Ì', L'', L'Ĩ', L''}},
{L'O', {L'Ó', L'Ò', L'', L'Õ', L''}},
{L'Ô', {L'', L'', L'', L'', L''}},
{L'Ơ', {L'', L'', L'', L'', L''}},
{L'U', {L'Ú', L'Ù', L'', L'Ũ', L''}},
{L'Ư', {L'', L'', L'', L'', L''}},
{L'Y', {L'Ý', L'', L'', L'', L''}},
};
static int
istone(Rune c)
{
return c == 's' || c == 'f' || c == 'r' || c == 'x' || c == 'j';
}
static int
toneidx(Rune c)
{
switch(c){
case 's': return 0;
case 'f': return 1;
case 'r': return 2;
case 'x': return 3;
case 'j': return 4;
}
return -1;
}
static int
isvowel(Rune c)
{
int i;
for(i = 0; i < nelem(vitone); i++)
if(vitone[i].base == c)
return 1;
return 0;
}
static Rune
removetone(Rune c)
{
int i, j;
for(i = 0; i < nelem(vitone); i++){
if(vitone[i].base == c)
return c;
for(j = 0; j < 5; j++)
if(vitone[i].tone[j] == c)
return vitone[i].base;
}
return c;
}
static Rune
applytone(Rune c, int tidx)
{
int i;
Rune base;
base = removetone(c);
for(i = 0; i < nelem(vitone); i++)
if(vitone[i].base == base)
return vitone[i].tone[tidx];
return c;
}
Emit
transvi(Im *im, Rune c)
{
Emit e;
Str mapped, pre;
int i, tidx, vi, last, penult;
Rune v, b1, b2;
if(!istone(c) && c != 'z')
return transmap(im, c);
memset(&e, 0, sizeof e);
if(im->pre.n == 0){
sputr(&e.s, c);
return e;
}
if(im->pre.r[im->pre.n - 1] == '\\'){
pre = im->pre;
pre.n--;
if(!mapget(im->l->map, &pre, &mapped))
mapped = pre;
sputr(&mapped, c);
e.eat = 1;
e.s = mapped;
return e;
}
if(!mapget(im->l->map, &im->pre, &mapped))
mapped = im->pre;
last = -1;
penult = -1;
for(i = 0; i < mapped.n; i++){
v = removetone(mapped.r[i]);
if(isvowel(v)){
penult = last;
last = i;
}
}
vi = -1;
if(last >= 0){
if(last < mapped.n - 1 || penult < 0)
vi = last;
else{
b1 = removetone(mapped.r[penult]);
b2 = removetone(mapped.r[last]);
if((b1 == 'o' || b1 == 'O') && (b2 == 'a' || b2 == 'A' || b2 == 'e' || b2 == 'E'))
vi = last;
else if((b1 == 'u' || b1 == 'U') && (b2 == 'y' || b2 == 'Y'))
vi = last;
else
vi = penult;
}
}
if(vi < 0){
e.eat = 1;
e.s = mapped;
sputr(&e.s, c);
return e;
}
if(c == 'z')
mapped.r[vi] = removetone(mapped.r[vi]);
else{
tidx = toneidx(c);
mapped.r[vi] = applytone(mapped.r[vi], tidx);
}
e.eat = 1;
e.next = mapped;
return e;
}