return IsLetter(tr, letter, LETTERGP_VOWEL2); | return IsLetter(tr, letter, LETTERGP_VOWEL2); | ||||
} | } | ||||
static int Unpronouncable2(Translator *tr, char *word) | |||||
{ | |||||
int c; | |||||
int end_flags; | |||||
char ph_buf[N_WORD_PHONEMES]; | |||||
ph_buf[0] = 0; | |||||
c = word[-1]; | |||||
word[-1] = ' '; // ensure there is a space before the "word" | |||||
end_flags = TranslateRules(tr, word, ph_buf, sizeof(ph_buf), NULL, FLAG_UNPRON_TEST, NULL); | |||||
word[-1] = c; | |||||
if ((end_flags == 0) || (end_flags & SUFX_UNPRON)) | |||||
return 1; | |||||
return 0; | |||||
} | |||||
int Unpronouncable(Translator *tr, char *word, int posn) | |||||
{ | |||||
/* Determines whether a word in 'unpronouncable', i.e. whether it should | |||||
be spoken as individual letters. | |||||
This function may be language specific. This is a generic version. | |||||
*/ | |||||
int c; | |||||
int c1 = 0; | |||||
int vowel_posn = 9; | |||||
int index; | |||||
int count; | |||||
ALPHABET *alphabet; | |||||
utf8_in(&c, word); | |||||
if ((tr->letter_bits_offset > 0) && (c < 0x241)) { | |||||
// Latin characters for a language with a non-latin alphabet | |||||
return 0; // so we can re-translate the word as English | |||||
} | |||||
if (((alphabet = AlphabetFromChar(c)) != NULL) && (alphabet->offset != tr->letter_bits_offset)) { | |||||
// Character is not in our alphabet | |||||
return 0; | |||||
} | |||||
if (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 1) | |||||
return 0; | |||||
if (((c = *word) == ' ') || (c == 0) || (c == '\'')) | |||||
return 0; | |||||
index = 0; | |||||
count = 0; | |||||
for (;;) { | |||||
index += utf8_in(&c, &word[index]); | |||||
if ((c == 0) || (c == ' ')) | |||||
break; | |||||
if ((c == '\'') && ((count > 1) || (posn > 0))) | |||||
break; // "tv'" but not "l'" | |||||
if (count == 0) | |||||
c1 = c; | |||||
if ((c == '\'') && (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 3)) { | |||||
// don't count apostrophe | |||||
} else | |||||
count++; | |||||
if (IsVowel(tr, c)) { | |||||
vowel_posn = count; // position of the first vowel | |||||
break; | |||||
} | |||||
if ((c != '\'') && !iswalpha(c)) | |||||
return 0; | |||||
} | |||||
if ((vowel_posn > 2) && (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 2)) { | |||||
// Lookup unpronounable rules in *_rules | |||||
return Unpronouncable2(tr, word); | |||||
} | |||||
if (c1 == tr->langopts.param[LOPT_UNPRONOUNCABLE]) | |||||
vowel_posn--; // disregard this as the initial letter when counting | |||||
if (vowel_posn > (tr->langopts.max_initial_consonants+1)) | |||||
return 1; // no vowel, or no vowel in first few letters | |||||
return 0; | |||||
} | |||||
int GetVowelStress(Translator *tr, unsigned char *phonemes, signed char *vowel_stress, int *vowel_count, int *stressed_syllable, int control) | int GetVowelStress(Translator *tr, unsigned char *phonemes, signed char *vowel_stress, int *vowel_count, int *stressed_syllable, int control) | ||||
{ | { | ||||
// control = 1, set stress to 1 for forced unstressed vowels | // control = 1, set stress to 1 for forced unstressed vowels |
const char *GetTranslatedPhonemeString(int phoneme_mode); | const char *GetTranslatedPhonemeString(int phoneme_mode); | ||||
int GetVowelStress(Translator *tr, unsigned char *phonemes, signed char *vowel_stress, int *vowel_count, int *stressed_syllable, int control); | int GetVowelStress(Translator *tr, unsigned char *phonemes, signed char *vowel_stress, int *vowel_count, int *stressed_syllable, int control); | ||||
int IsVowel(Translator *tr, int letter); | int IsVowel(Translator *tr, int letter); | ||||
int Unpronouncable(Translator *tr, char *word, int posn); | |||||
void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags, int tonic, int control); | void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags, int tonic, int control); | ||||
void AppendPhonemes(Translator *tr, char *string, int size, const char *ph); | void AppendPhonemes(Translator *tr, char *string, int size, const char *ph); | ||||
int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, char *end_phonemes, int word_flags, unsigned int *dict_flags); | int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, char *end_phonemes, int word_flags, unsigned int *dict_flags); |
static int NonAsciiNumber(int letter); | static int NonAsciiNumber(int letter); | ||||
static char *SpeakIndividualLetters(Translator *tr, char *word, char *phonemes, int spell_word, ALPHABET *current_alphabet, char word_phonemes[]); | static char *SpeakIndividualLetters(Translator *tr, char *word, char *phonemes, int spell_word, ALPHABET *current_alphabet, char word_phonemes[]); | ||||
static int TranslateLetter(Translator *tr, char *word, char *phonemes, int control, ALPHABET *current_alphabet); | static int TranslateLetter(Translator *tr, char *word, char *phonemes, int control, ALPHABET *current_alphabet); | ||||
static int Unpronouncable(Translator *tr, char *word, int posn); | |||||
static int Unpronouncable2(Translator *tr, char *word); | |||||
int TranslateWord3(Translator *tr, char *word_start, WORD_TAB *wtab, char *word_out, bool *any_stressed_words, ALPHABET *current_alphabet, char word_phonemes[], size_t size_word_phonemes) | int TranslateWord3(Translator *tr, char *word_start, WORD_TAB *wtab, char *word_out, bool *any_stressed_words, ALPHABET *current_alphabet, char word_phonemes[], size_t size_word_phonemes) | ||||
{ | { | ||||
} | } | ||||
return -1; | return -1; | ||||
} | } | ||||
static int Unpronouncable(Translator *tr, char *word, int posn) | |||||
{ | |||||
/* Determines whether a word in 'unpronouncable', i.e. whether it should | |||||
be spoken as individual letters. | |||||
This function may be language specific. This is a generic version. | |||||
*/ | |||||
int c; | |||||
int c1 = 0; | |||||
int vowel_posn = 9; | |||||
int index; | |||||
int count; | |||||
ALPHABET *alphabet; | |||||
utf8_in(&c, word); | |||||
if ((tr->letter_bits_offset > 0) && (c < 0x241)) { | |||||
// Latin characters for a language with a non-latin alphabet | |||||
return 0; // so we can re-translate the word as English | |||||
} | |||||
if (((alphabet = AlphabetFromChar(c)) != NULL) && (alphabet->offset != tr->letter_bits_offset)) { | |||||
// Character is not in our alphabet | |||||
return 0; | |||||
} | |||||
if (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 1) | |||||
return 0; | |||||
if (((c = *word) == ' ') || (c == 0) || (c == '\'')) | |||||
return 0; | |||||
index = 0; | |||||
count = 0; | |||||
for (;;) { | |||||
index += utf8_in(&c, &word[index]); | |||||
if ((c == 0) || (c == ' ')) | |||||
break; | |||||
if ((c == '\'') && ((count > 1) || (posn > 0))) | |||||
break; // "tv'" but not "l'" | |||||
if (count == 0) | |||||
c1 = c; | |||||
if ((c == '\'') && (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 3)) { | |||||
// don't count apostrophe | |||||
} else | |||||
count++; | |||||
if (IsVowel(tr, c)) { | |||||
vowel_posn = count; // position of the first vowel | |||||
break; | |||||
} | |||||
if ((c != '\'') && !iswalpha(c)) | |||||
return 0; | |||||
} | |||||
if ((vowel_posn > 2) && (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 2)) { | |||||
// Lookup unpronounable rules in *_rules | |||||
return Unpronouncable2(tr, word); | |||||
} | |||||
if (c1 == tr->langopts.param[LOPT_UNPRONOUNCABLE]) | |||||
vowel_posn--; // disregard this as the initial letter when counting | |||||
if (vowel_posn > (tr->langopts.max_initial_consonants+1)) | |||||
return 1; // no vowel, or no vowel in first few letters | |||||
return 0; | |||||
} | |||||
static int Unpronouncable2(Translator *tr, char *word) | |||||
{ | |||||
int c; | |||||
int end_flags; | |||||
char ph_buf[N_WORD_PHONEMES]; | |||||
ph_buf[0] = 0; | |||||
c = word[-1]; | |||||
word[-1] = ' '; // ensure there is a space before the "word" | |||||
end_flags = TranslateRules(tr, word, ph_buf, sizeof(ph_buf), NULL, FLAG_UNPRON_TEST, NULL); | |||||
word[-1] = c; | |||||
if ((end_flags == 0) || (end_flags & SUFX_UNPRON)) | |||||
return 1; | |||||
return 0; | |||||
} |