#include <string.h>
#include "macro.h"
//---------------------------------------------------------------------------
/* EDITOR GLOBALS */
extern int left; // left border (1..78)
extern int right; // right border (2..79)
//---------------------------------------------------------------------------
/* LINE GLOBALS */
extern int prev; // previous str real size (= length previous str)
extern int is_red; // indicator: if red-line str
extern int last; // previus word end
extern int word_cnt; // words count in str
extern int len; // real str length
extern int found; // indicator: if in word
//---------------------------------------------------------------------------
char ANSI_to_ASCII(char sym) // ANSI(Windows) -> ASCII(DOS)
{
if((sym >= 'А') && (sym <= 'п'))
sym -= 64;
else if((sym >= 'р') && (sym <= 'я'))
sym -= 16;
return sym;
}
//---------------------------------------------------------------------------
char ASCII_to_ANSI(unsigned char sym) // ASCII(DOS) -> ANSI(Windows)
{
if((sym >= 128) && (sym <= 175))
sym += 64;
else if((sym >= 224) && (sym <= 239))
sym += 16;
return sym;
}
//---------------------------------------------------------------------------
void get_ASCII_line(char* str) // ANSI-str -> ASCII-str
{
while(*str)
{
*str = ANSI_to_ASCII(*str);
str++;
}
return;
}
//---------------------------------------------------------------------------
int glasn(int sym) // return 1 - if glasn, else return 0
{
if((sym == 'а') ||(sym == 'А') ||(sym == 'Е') ||(sym == 'е') ||(sym == 'Ё') ||
(sym == 'ё') ||(sym == 'И') ||(sym == 'и') ||(sym == 'О') ||(sym == 'о') ||
(sym == 'У') ||(sym == 'у') ||(sym == 'ы') ||(sym == 'Э') ||(sym == 'э') ||
(sym == 'Ю') ||(sym == 'ю') ||(sym == 'Я') ||(sym == 'я'))
return 1;
else
return 0;
}
//---------------------------------------------------------------------------
int is_rus_letter(int sym) // if symbol from russian alphabet
{
if((sym >= 'А') && (sym <= 'я'))
return 1;
else
return 0;
}
//---------------------------------------------------------------------------
int soglasn(int sym) // return 1 - if soglasn, else return 0
{
if(is_rus_letter(sym) && (!glasn(sym)))
return 1;
else
return 0;
}
//---------------------------------------------------------------------------
// if any visible symbol not BACKSPACE, GAP, ENTER
int rus_graph(int sym)
{
if(is_rus_letter(sym) || (sym >= 0x21 && sym <= 0x7E))
return 1;
else
return 0;
}
//---------------------------------------------------------------------------
// return 1 - if there is glasn in str else return 0
int find_glasn(char* str)
{
while(*str)
{
if(glasn(*str))
return 1;
else if(!is_rus_letter(*str))
return 0;
str++;
}
return 0;
}
//---------------------------------------------------------------------------
void get_lower(char* str) // str -> lower register
{
while(*str)
{
if((*str >= 'А') && (*str <= 'Я'))
*str += 32;
str++;
}
return;
}
//---------------------------------------------------------------------------
// binary search: return first word index with first letter sym, kol - words_count
// else: return -1
int bs(char sym, char** mas, int kol)
{
int x, l, r;
r = kol - 1; // right member
l = 0; // left member
while(l < r)
{
x = (r + l) / 2; // choose middle member
if(mas[x][0] >= sym)
r = x;
else
l = x + 1;
}
if(mas[l][0] == sym)
return l;
else
return -1;
}
//---------------------------------------------------------------------------
// separate prefix, return index of next word part after prefix or 0
int get_pref(char* str)
{
int i = 0; // index in str
int len = 0; // prefix length
int n; // str length
char* pref_list[] = {"без", "беc", "воз", "вос", "дез", "за", "из", "ис", "контр",
"меж", "на", "не", "низ", "нис", "обо", "об", "пан", "пол",
"пост", "под", "по", "пред", "пре", "при", "раз", "рас",
"рос", "сверх", "со", "суб", "транс", "чрез", "чрес" };
// at first largest prefixes, for example, "под", "по"
char* curr_pref; // current prefix
char temp_str[MAXSTR]; // to duplicate str
int found = FALSE; // found = TRUE - prefix found
int pref_count = sizeof(pref_list) / sizeof(char*);
n = strlen(str);
strcpy(temp_str, str); // store str in temp_str
i = bs(str[0], pref_list, pref_count); // first letter prefix
if(i == -1) // not found first letter
{
strcpy(str, temp_str); //restore str
return 0;
}
do
{
curr_pref = pref_list[i]; // get new prefix
// cmp with mask of next prefix
if(!(strncmp(curr_pref, str, strlen(curr_pref))))
{
found = TRUE;
break;
}
i++;
}
while((i < pref_count) && (pref_list[i][0] == str[0]));
// while not end of pref_list and prefix begins from the same letter
if(found == FALSE)
{
strncpy(str, temp_str, n); //restore str
return 0;
}
len = strlen(curr_pref); // get prefix length
// example: "подъ-езд" , "пой-ти" -> increase len
if((str[len] == 'ъ') || ((str[len] == 'й') && glasn(str[len - 1])))
len++;
// if prefix ends with soglasn nd next letter "ы", example: "ра-зыграть"
// "раз-ыграть" - error
// -> decrease len
else
{ // "об-ыскать" - error
if((str[len] == 'ы') && soglasn(str[len - 1]) && len > 2)
len--; // "по-дыскать"
else if((str[len] == 'ы') && soglasn(str[len - 1]) && len <= 2)
len = 0; // "о-быскать" - error
}
strcpy(str, temp_str); //restore str
return len;
}
//---------------------------------------------------------------------------
/* return 0 - if position i is not valid for perenos
else return valid perenos index
str - word, i - index for checking, rpos - max vlid index for perenos
*/
int rule_gl(char* str, int i, int rpos)
{
int k, j;
int pos;
pos = k = j = 0;
if(str[i + 1] == 'й')
j = 1; // glasn + 'й' = one letter
if((str[i - 1] == 'ъ') ||(str[i - 1] == 'ь'))
k = 1; // soglasn + 'ъ' = one letter
// if next letter - glasn, prev letter - soglasn, at least 2 letters after possible perenos
if(glasn(str[i + j + 1]) && soglasn(str[i - k - 1]) &&
is_rus_letter(str[i + j + 2]))
{
pos = (pos > rpos) ? 0 : (i + j);
}
// if next letter - soglasn, prev letter - glasn, there is at least one glasn in rpart
else if(soglasn(str[i + j + 1]) && soglasn(str[i - k - 1]) && find_glasn(str + i + j + 2))
{
pos = (pos > rpos) ? 0 : (i + j);
}
return pos;
}
//---------------------------------------------------------------------------
/* return 0 - if position i is not valid for perenos
else return valid perenos index
str - word, i - index for checking, rpos - max vlid index for perenos
*/
int rule_sogl(char* str, int i, int rpos)
{
int j;
int pos = 0;
pos = j = 0;
if((str[i + 1] == 'ъ') ||(str[i + 1] == 'ь'))
j = 1; // soglasn + 'ъ' = one letter
// if next letter - soglasn, prev letter - glasn, there is at least one glasn in rpart
if(soglasn(str[i + j + 1]) && glasn(str[i - 1]) &&
find_glasn(str + i + j + 2))
{
pos = (pos > rpos) ? 0 : (i + j);
}
return pos;
}
//---------------------------------------------------------------------------
// rpos - max right perenos position, lpart - left_str + '-', rpart - right_str
void get_perenos(char* str, int rpos, char* lpart, char* rpart)
{
int len;
int t = 0; // word part after non-letter symbols - (, " e.t.c.
int st = 0; // word part after prefix
int i; // current str index
int pos = 0; // found perenos position
int max = FALSE; // indicator: if maxlen str without perenos
char temp[MAXSTR]; // to duplicate str
if(rpos <= 1) // if there is space for only letter - > impossible
{
*lpart = '\0';
strcpy(rpart, str);
return;
}
strcpy(temp, str); // store str
get_lower(str); // get str in lower register
while(str[t] && !is_rus_letter(str[t])) // missing non-letter symbols
{
t++; // count of non-letter symbols
str++; // cut str beginning
}
if((*str == '\0') || (t >= rpos)) // if all str consists of non-letter symbols
{ // or letters are too far to get perenos
*lpart = '\0';
strcpy(rpart, temp); // impossible
return;
}
rpos -= t; // correction rpos for new str
len = strlen(str); // str length
st = get_pref(str); // try to get prefix
if(st > rpos) // if no enough space to get perenos of one_slog prefix
{ // we need 1 position for '-'
*lpart = '\0';
strcpy(rpart, temp); // impossible
return;
}
i = (rpos > (len - 3)) ? (len - 3) : rpos;
// set max possible i index for perenos (at least 2 letters must be for right)
// or pred-pred last letter, or rpos
while(i > st) // try to get perenos after prefix
{
if(glasn(str[i]))
{
if(pos = rule_gl(str, i, rpos))
break;
}
else if(soglasn(str[i]))
{
if(pos = rule_sogl(str, i, rpos))
break;
}
i--; // take prev position to try get perenos
}
// after cycle:
// if found prefix and no perenos after prefix and
// 1) only one letter after prefix or
// 2) no glasn in rpart
if(!pos && st && (((len - st) == 1) || !(find_glasn(str + st))))
{
*lpart = '\0'; // impossible
strcpy(rpart, temp);
return;
}
// if no prefix and no perenos
if(!pos && !st)
{
if((len < (right - left + 1 - is_red - t))) // if not the whole str without perenos
{
*lpart = '\0';
strcpy(rpart, temp);
return;
}
else
{
pos = len - 2; // if "ппппппппппппппппп" (only soglasn without glasn)
max = TRUE;
}
}
// if 1) found prefix
// 2) no perenos after prefix
// 3) rpart - not one letter
// 4) first glasn after prefix - Ы
if(!pos && st && ((len - st) > 1))
if(str[st] == 'ы')
pos = st - 2; // "по-дытожить"
else
pos = st - 1; // "под-ставить"
pos += t; // return folowwing non-letter symbols
strncpy(lpart, temp, pos + 1); // fill lpart
if(!max) // if not the whole str without perenos
{
lpart[pos + 1] = '-'; // add '-'
lpart[pos + 2] = '\0';
}
else
lpart[pos + 1] = '\0'; // without '-'
strcpy(rpart, temp + pos + 1); // fill rpart
return;
}