| 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; | |||||
| } |