1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
| /****** grmxtd.c - грамматический перенос 08.12.92 ***/
#include "a.h"
#include "xtd.h"
void *malc();
static char LW[] = "аеиоуэюяыaeoui";
asi word = 0; /* 1 - не разбивать слова */
static char *fr;
static perno(int a, int b); /* Поиск возможного переноса в fr[a:b] */
/* Возвращает место возможного переноса или 0 */
/************************* Поиск гласной в fr[a,b] *******/
static choilw(int a, int b); /* Возвращает номер гласной или -1 */
/* ------------------ */
XTD *grmxtd(char *from, int nt)
{ int k, rw1, rw2, bw1, bw2, bp, nf, j, r1, r2, kf;
XTD *x; char *to; char frnt;
/* r1 - разделитель до переноса */
/* r2 - разделитель после переносимого слова */
/* rw1 - гласная до переноса */
/* rw2 - гласная после переноса */
/* bw1 - есть ли гласная до переноса */
/* bw2 - есть ли гласная после переноса */
/* bp - анализ и пропуск пробела */
x = genxtd();
if (nt<1) return(x);
to = malc(nt+1);
if (from==NULL) fr="";
else fr = from;
a: nf=strlen(fr);
if (nf==0) {
if (x->ns==0) asgxtd(x,fr);
free(to);
return(x);
}
bp = bw1 = bw2 = 0;
memst(to, ' ', nt);
/* Символ '@' вызывает насильственный перенос */
k=(nf>nt) ? nt+1 : nf;
afc(j,k) {
if (fr[j]=='@') {
memcpy(to,fr,j);
kf = j+1;
goto a2;
}
}
if (nf<=nt) { /* Все и так помещается */
kf = nf; goto a1; }
frnt=fr[nt];
if ( frnt==' ' || frnt=='(' ||
(frnt=='"' && !isbu(fr[nt-1])) || nt < 3 ) { /* Естественная разбивка */
kf=nt; bp=1; goto a1; }
for (r1=nt-1;r1>=0; r1--)
if (isbu(fr[r1])==0) break;
/* на выходе из этого цикла r1=номеру разделителя или -1 */
if ( r1==nt-1 || r1==nt-2 ) /* Перенос по концу слова */
goto forc2;
if (r1==nt-3) {
if (fr[r1] !='(' && !(fr[r1]=='"' && !isbu(fr[r1-1])) || nt==3) r1++;
kf=r1;
goto a1;
}
if (word) goto forc;
if ((rw1=choilw(r1+1,nt-2))>=0) bw1=1;
if (!bw1) goto forc; /* Нету гласных */
afcn(r2,nt,nf) /* Поиск разделителя после слова */
if (isbu(fr[r2])==0) break;
/* Теперь слово ограничено r1 и r2 */
afcn(j,r1+1,r2-1) /* Если в слове есть цифры - грубый перенос */
if ('0'<=fr[j] && fr[j]<='9') goto forc;
for (rw2=nt-1; rw2<r2; rw2++) /* Поиск гласной за переносом */
if (strchr(LW,tolow(fr[rw2]))!=NULL) { bw2=1; break; }
/* Начальная попытка */
if (rw2==r2-1 && rw2==nt-1)
k = perno(rw1,nt-3);
else
if (bw2) k = perno(rw1,nt-2);
else k=0;
while (k==0) { /* Пока перенос не найден */
if ((j=choilw(r1+1,rw1-1)) < 0 )
goto forc; /* Гласные кончились - грубый перенос */
rw2=rw1; rw1=j;
k = perno(rw1,rw2-1);
}
/* нашли перенос после fr[k] */
kf = k+1;
to[kf] = '-';
goto a1;
forc: /* Грубый перенос */
if (r1<1) {
kf = nt;
goto a1;
}
forc2: /* Перенос по концу слова */
kf=r1;
if ( fr[r1] != '(' && !(fr[r1]=='"' && !isbu(fr[r1-1]))) kf++;
bp=1;
a1: memcpy(to,fr,kf);
if (bp && fr[kf]==' ') kf++;
a2: fr += kf;
asgxtd(x,to);
goto a;
}
/************************* Поиск гласной в fr[a,b] *******/
static choilw(int a, int b) /* Возвращает номер гласной или -1 */
{ int j;
for(j=b; j>=a; j--)
if (strchr(LW, tolow(fr[j]))!=NULL) return(j);
return(-1); }
/*************************/
static perno(int a, int b) /* Поиск возможного переноса в fr[a:b] */
/* Возвращает место возможного переноса или 0 */
{ int j; char s_1,s0,s1;
for (j=b; j>=a; j--) { /* Изучение возможности переноса после j-того символа */
s1=tolow(fr[j+1]);
/* Чтоб Ь и Ъ не отрывались */
if (s1=='ъ' || s1=='ь') continue;
/* согласная - гласная : нехорошо */
s0=fr[j];
if (strchr(LW,s1)!=NULL && strchr(LW,s0)==NULL
&& strchr("ьъ",s0)==NULL) continue;
/* гласная - Й : нехорошо */
if (strchr(LW,s0)!=NULL && s1=='й' ) continue;
/* гласная гласная - : нехорошо */
s_1=tolow(fr[j-1]);
if (strchr(LW,s_1)!=NULL && strchr(LW,s0)!=NULL) continue;
/* ХХ- и -ХХ : нехорошо */
if (s0==s_1) continue;
if (fr[j+1]==fr[j+2]) continue;
/* Чтоб одна буква не оставалась */
if (isbu(s_1)==0) return(0);
return(j);
}
return (0); }
/****************/
set_grm_word(int k)
{ int OldWord;
OldWord = word;
word = k;
return(OldWord);
}
/**************/ |