From a83d55b29673bfd70c51d2dc316f99281d88e653 Mon Sep 17 00:00:00 2001 From: qwell Date: Wed, 30 Dec 2009 22:30:21 +0000 Subject: [PATCH] Add app_voicemail and say.c support for Vietnamese. Also add an XXX comment that I'm baffled nobody has ever complained about. We say "first message", and then we go into language-specific stuff where we proceed to say..."first message". (closes issue #15053) Reported by: dinhtrung Patches: vietnamese.ods uploaded by dinhtrung (license 776) app_voicemail.c.diff uploaded by dinhtrung (license 776) (closes issue #15626) Reported by: dinhtrung Patches: say.c.diff uploaded by dinhtrung (license 776) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@237050 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_voicemail.c | 81 +++++++++- doc/lang/vietnamese.ods | Bin 0 -> 20503 bytes main/say.c | 338 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 415 insertions(+), 4 deletions(-) create mode 100644 doc/lang/vietnamese.ods diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index c29da2f2c..ee66a6ef9 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -6966,6 +6966,8 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL); } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL); + } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */ + res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' A 'digits/day' dB 'digits/year' Y 'digits/at' k 'hours' M 'minutes'", NULL); } else { res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL); } @@ -7122,6 +7124,7 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc } if (!res) { + /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */ /* POLISH syntax */ if (!strncasecmp(chan->language, "pl", 2)) { if (vms->curmsg && (vms->curmsg != vms->lastmsg)) { @@ -7159,6 +7162,19 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc res = wait_file2(chan, vms, "vm-number"); res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f"); } + /* VIETNAMESE syntax */ + } else if (!strncasecmp(chan->language, "vi", 2)) { + if (!vms->curmsg) { + res = wait_file2(chan, vms, "vm-message"); + res = wait_file2(chan, vms, "vm-first"); + } else if (vms->curmsg == vms->lastmsg) { + res = wait_file2(chan, vms, "vm-message"); + res = wait_file2(chan, vms, "vm-last"); + } else { + res = wait_file2(chan, vms, "vm-message"); + res = wait_file2(chan, vms, "vm-number"); + res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f"); + } } else { if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */ res = wait_file2(chan, vms, "vm-meddelandet"); /* "message" */ @@ -7492,6 +7508,8 @@ static int vm_play_folder_name(struct ast_channel *chan, char *box) return vm_play_folder_name_pl(chan, box); } else if (!strncasecmp(chan->language, "ua", 2)) { /* Ukrainian syntax */ return vm_play_folder_name_ua(chan, box); + } else if (!strncasecmp(chan->language, "vi", 2)) { + return ast_play_and_wait(chan, box); } else { /* Default English */ cmd = ast_play_and_wait(chan, box); return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */ @@ -8365,6 +8383,37 @@ static int vm_intro_zh(struct ast_channel *chan, struct vm_state *vms) return res; } +/* Vietnamese syntax */ +static int vm_intro_vi(struct ast_channel *chan, struct vm_state *vms) +{ + int res; + + /* Introduce messages they have */ + res = ast_play_and_wait(chan, "vm-youhave"); + if (!res) { + if (vms->newmessages) { + res = say_and_wait(chan, vms->newmessages, chan->language); + if (!res) + res = ast_play_and_wait(chan, "vm-INBOX"); + if (vms->oldmessages && !res) + res = ast_play_and_wait(chan, "vm-and"); + } + if (!res && vms->oldmessages) { + res = say_and_wait(chan, vms->oldmessages, chan->language); + if (!res) + res = ast_play_and_wait(chan, "vm-Old"); + } + if (!res) { + if (!vms->oldmessages && !vms->newmessages) { + res = ast_play_and_wait(chan, "vm-no"); + if (!res) + res = ast_play_and_wait(chan, "vm-message"); + } + } + } + return res; +} + static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms) { char prefile[256]; @@ -8417,6 +8466,8 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm return vm_intro_se(chan, vms); } else if (!strncasecmp(chan->language, "ua", 2)) { /* UKRAINIAN syntax */ return vm_intro_multilang(chan, vms, "n"); + } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */ + return vm_intro_vi(chan, vms); } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */ return vm_intro_zh(chan, vms); } else { /* Default to ENGLISH */ @@ -9012,6 +9063,30 @@ static int vm_browse_messages_zh(struct ast_channel *chan, struct vm_state *vms, return cmd; } +/*! + * \brief Vietnamese syntax for 'You have N messages' greeting. + * \param chan + * \param vms + * \param vmu + * + * \return zero on success, -1 on error. + */ +static int vm_browse_messages_vi(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu) +{ + int cmd = 0; + + if (vms->lastmsg > -1) { + cmd = play_message(chan, vmu, vms); + } else { + cmd = ast_play_and_wait(chan, "vm-no"); + if (!cmd) { + snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox); + cmd = ast_play_and_wait(chan, vms->fn); + } + } + return cmd; +} + /*! * \brief Top level method to invoke the language variant vm_browse_messages_XX function. * \param chan The channel for the current user. We read the language property from this. @@ -9035,8 +9110,10 @@ static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, st return vm_browse_messages_it(chan, vms, vmu); } else if (!strncasecmp(chan->language, "pt", 2)) { /* PORTUGUESE */ return vm_browse_messages_pt(chan, vms, vmu); - } else if (!strncasecmp(chan->language, "zh", 2)){ - return vm_browse_messages_zh(chan, vms, vmu); /* CHINESE (Taiwan) */ + } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE */ + return vm_browse_messages_vi(chan, vms, vmu); + } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) */ + return vm_browse_messages_zh(chan, vms, vmu); } else { /* Default to English syntax */ return vm_browse_messages_en(chan, vms, vmu); } diff --git a/doc/lang/vietnamese.ods b/doc/lang/vietnamese.ods new file mode 100644 index 0000000000000000000000000000000000000000..8094c42f0805de727b91ddf93b7b344ba035de51 GIT binary patch literal 20503 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 literal 0 HcmV?d00001 diff --git a/main/say.c b/main/say.c index c3ca18565..89ff4f6bf 100644 --- a/main/say.c +++ b/main/say.c @@ -350,12 +350,14 @@ static int ast_say_number_full_ka(struct ast_channel *chan, int num, const char static int ast_say_number_full_hu(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd); static int ast_say_number_full_th(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd); static int ast_say_number_full_ur(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd); +static int ast_say_number_full_vi(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd); /* Forward declarations of language specific variants of ast_say_enumeration_full */ static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd); static int ast_say_enumeration_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd); static int ast_say_enumeration_full_de(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd); static int ast_say_enumeration_full_he(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd); +static int ast_say_enumeration_full_vi(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd); /* Forward declarations of ast_say_date, ast_say_datetime and ast_say_time functions */ static int ast_say_date_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang); @@ -383,6 +385,7 @@ static int ast_say_date_with_format_pt(struct ast_channel *chan, time_t t, const static int ast_say_date_with_format_zh(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone); static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone); static int ast_say_date_with_format_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone); +static int ast_say_date_with_format_vi(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone); static int ast_say_time_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang); static int ast_say_time_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang); @@ -496,6 +499,8 @@ static int say_number_full(struct ast_channel *chan, int num, const char *ints, return ast_say_number_full_zh(chan, num, ints, language, audiofd, ctrlfd); } else if (!strncasecmp(language, "ur", 2)) { /* Urdu syntax */ return ast_say_number_full_ur(chan, num, ints, language, options, audiofd, ctrlfd); + } else if (!strncasecmp(language, "vi", 2)) { /* Vietnamese syntax */ + return ast_say_number_full_vi(chan, num, ints, language, audiofd, ctrlfd); } /* Default to english */ @@ -2612,6 +2617,101 @@ static int ast_say_number_full_th(struct ast_channel *chan, int num, const char return res; } +/*! \brief ast_say_number_full_vi: Vietnamese syntax */ +static int ast_say_number_full_vi(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd) +{ + int res = 0; + int playh = 0; + int playoh = 0; + int playohz = 0; + int playz = 0; + int playl = 0; + char fn[256] = ""; + if (!num) + return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd); + while (!res && (num || playh)) { + if (num < 0) { + ast_copy_string(fn, "digits/minus", sizeof(fn)); + if ( num > INT_MIN ) { + num = -num; + } else { + num = 0; + } + } else if (playl) { + snprintf(fn, sizeof(fn), "digits/%da", num); + playl = 0; + num = 0; + } else if (playh) { + ast_copy_string(fn, "digits/hundred", sizeof(fn)); + playh = 0; + } else if (playz) { + ast_copy_string(fn, "digits/odd", sizeof(fn)); + playz = 0; + } else if (playoh) { + ast_copy_string(fn, "digits/0-hundred", sizeof(fn)); + playoh = 0; + } else if (playohz) { + ast_copy_string(fn, "digits/0-hundred-odd", sizeof(fn)); + playohz = 0; + } else if (num < 20) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num < 100) { + snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10); + num %= 10; + if ((num == 5) || (num == 4) || (num == 1)) playl++; + } else { + if (num < 1000) { + snprintf(fn, sizeof(fn), "digits/%d", (num/100)); + num %= 100; + if (num && (num < 10)) { + playz++; + playh++; + } else { + playh++; + } + } else { + if (num < 1000000) { /* 1,000,000 */ + res = ast_say_number_full_vi(chan, num / 1000, ints, language, audiofd, ctrlfd); + if (res) + return res; + num %= 1000; + snprintf(fn, sizeof(fn), "digits/thousand"); + if (num && (num < 10)) { + playohz++; + } else if (num && (num < 100)){ + playoh++; + } else { + playh = 0; + playohz = 0; + playoh = 0; + } + } else { + if (num < 1000000000) { /* 1,000,000,000 */ + res = ast_say_number_full_vi(chan, num / 1000000, ints, language, audiofd, ctrlfd); + if (res) + return res; + num %= 1000000; + ast_copy_string(fn, "digits/million", sizeof(fn)); + } else { + res = -1; + } + } + } + } + if (!res) { + if (!ast_streamfile(chan, fn, language)) { + if ((audiofd > -1) && (ctrlfd > -1)) + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); + else + res = ast_waitstream(chan, ints); + } + ast_stopstream(chan); + } + } + return res; +} + /*! \brief ast_say_enumeration_full: call language-specific functions */ /* Called from AGI */ static int say_enumeration_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd) @@ -2624,6 +2724,8 @@ static int say_enumeration_full(struct ast_channel *chan, int num, const char *i return ast_say_enumeration_full_de(chan, num, ints, language, options, audiofd, ctrlfd); } else if (!strncasecmp(language, "he", 2)) { /* Hebrew syntax */ return ast_say_enumeration_full_he(chan, num, ints, language, options, audiofd, ctrlfd); + } else if (!strncasecmp(language, "vi", 2)) { /* Vietnamese syntax */ + return ast_say_enumeration_full_vi(chan, num, ints, language, audiofd, ctrlfd); } /* Default to english */ @@ -2729,6 +2831,25 @@ static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const return res; } +static int ast_say_enumeration_full_vi(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd) +{ + int res = 0; + char fn[256] = ""; + ast_copy_string(fn, "digits/h", sizeof(fn)); + if (!res) { + if (!ast_streamfile(chan, fn, language)) { + if ((audiofd > -1) && (ctrlfd > -1)) { + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); + } else { + res = ast_waitstream(chan, ints); + } + } + ast_stopstream(chan); + } + + return ast_say_number_full_vi(chan, num, ints, language, audiofd, ctrlfd); +} + /*! \brief ast_say_enumeration_full_da: Danish syntax */ static int ast_say_enumeration_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd) { @@ -3534,6 +3655,8 @@ static int say_date_with_format(struct ast_channel *chan, time_t t, const char * return ast_say_date_with_format_zh(chan, t, ints, lang, format, tzone); } else if (!strncasecmp(lang, "zh", 2)) { /* Taiwanese / Chinese syntax */ return ast_say_date_with_format_zh(chan, t, ints, lang, format, tzone); + } else if (!strncasecmp(lang, "vi", 2)) { /* Vietnamese syntax */ + return ast_say_date_with_format_vi(chan, t, ints, lang, format, tzone); } /* Default to English */ @@ -7515,12 +7638,223 @@ static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t t, const return res; } +/* Vietnamese syntax */ +int ast_say_date_with_format_vi(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone) +{ + struct timeval when = { t, 0 }; + struct ast_tm tm; + int res = 0, offset, sndoffset; + char sndfile[256], nextmsg[256]; + if (format == NULL) + format = "A 'digits/day' eB 'digits/year' Y 'digits/at' k 'hours' M 'minutes' p"; + ast_localtime(&when, &tm, tzone); + + for (offset=0 ; format[offset] != '\0' ; offset++) { + ast_debug(1, "Parsing %c (offset %d) in %s\n", format[offset], offset, format); + switch (format[offset]) { + /* NOTE: if you add more options here, please try to be consistent with strftime(3) */ + case '\'': + /* Literal name of a sound file */ + sndoffset = 0; + for (sndoffset = 0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++) + sndfile[sndoffset] = format[offset]; + sndfile[sndoffset] = '\0'; + res = wait_file(chan, ints, sndfile, lang); + break; + case 'A': + case 'a': + /* Sunday - Saturday */ + snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday); + res = wait_file(chan, ints, nextmsg, lang); + break; + case 'B': + case 'b': + case 'h': + /* January - December */ + snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon); + res = wait_file(chan, ints, nextmsg, lang); + break; + case 'm': + /* Month enumerated */ + res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, (char *) NULL); + break; + case 'd': + case 'e': + /* 1 - 31 */ + res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL); + break; + case 'Y': + /* Year */ + if (tm.tm_year > 99) { + res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL); + } else if (tm.tm_year < 1) { + /* I'm not going to handle 1900 and prior */ + /* We'll just be silent on the year, instead of bombing out. */ + } else { + res = wait_file(chan, ints, "digits/19", lang); + if (!res) { + if (tm.tm_year <= 9) { + /* 1901 - 1909 */ + res = wait_file(chan, ints, "digits/odd", lang); + } + + res |= ast_say_number(chan, tm.tm_year, ints, lang, (char *) NULL); + } + } + break; + case 'I': + case 'l': + /* 12-Hour */ + if (tm.tm_hour == 0) + ast_copy_string(nextmsg, "digits/12", sizeof(nextmsg)); + else if (tm.tm_hour > 12) + snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour - 12); + else + snprintf(nextmsg, sizeof(nextmsg), "digits/%d", tm.tm_hour); + res = wait_file(chan, ints, nextmsg, lang); + break; + case 'H': + case 'k': + /* 24-Hour */ + if (format[offset] == 'H') { + /* e.g. oh-eight */ + if (tm.tm_hour < 10) { + res = wait_file(chan, ints, "digits/0", lang); + } + } else { + /* e.g. eight */ + if (tm.tm_hour == 0) { + res = wait_file(chan, ints, "digits/0", lang); + } + } + if (!res) { + if (tm.tm_hour != 0) { + int remaining = tm.tm_hour; + if (tm.tm_hour > 20) { + res = wait_file(chan, ints, "digits/20", lang); + remaining -= 20; + } + if (!res) { + snprintf(nextmsg, sizeof(nextmsg), "digits/%d", remaining); + res = wait_file(chan, ints, nextmsg, lang); + } + } + } + break; + case 'M': + case 'N': + /* Minute */ + res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL); + break; + case 'P': + case 'p': + /* AM/PM */ + if (tm.tm_hour > 11) + ast_copy_string(nextmsg, "digits/p-m", sizeof(nextmsg)); + else + ast_copy_string(nextmsg, "digits/a-m", sizeof(nextmsg)); + res = wait_file(chan, ints, nextmsg, lang); + break; + case 'Q': + /* Shorthand for "Today", "Yesterday", or ABdY */ + /* XXX As emphasized elsewhere, this should the native way in your + * language to say the date, with changes in what you say, depending + * upon how recent the date is. XXX */ + { + struct timeval now = ast_tvnow(); + struct ast_tm tmnow; + time_t beg_today; + + gettimeofday(&now, NULL); + ast_localtime(&now, &tmnow, tzone); + /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */ + /* In any case, it saves not having to do ast_mktime() */ + beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec); + if (beg_today < t) { + /* Today */ + res = wait_file(chan, ints, "digits/today", lang); + } else if (beg_today - 86400 < t) { + /* Yesterday */ + res = wait_file(chan, ints, "digits/yesterday", lang); + } else if (beg_today - 86400 * 6 < t) { + /* Within the last week */ + res = ast_say_date_with_format_vi(chan, t, ints, lang, "A", tzone); + } else if (beg_today - 2628000 < t) { + /* Less than a month ago - "Chu nhat ngay 13 thang 2" */ + res = ast_say_date_with_format_vi(chan, t, ints, lang, "A 'digits/day' dB", tzone); + } else if (beg_today - 15768000 < t) { + /* Less than 6 months ago - "August seventh" */ + res = ast_say_date_with_format_vi(chan, t, ints, lang, "'digits/day' dB", tzone); + } else { + /* More than 6 months ago - "April nineteenth two thousand three" */ + res = ast_say_date_with_format_vi(chan, t, ints, lang, "'digits/day' dB 'digits/year' Y", tzone); + } + } + break; + case 'q': + /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */ + /* XXX As emphasized elsewhere, this should the native way in your + * language to say the date, with changes in what you say, depending + * upon how recent the date is. XXX */ + { + struct timeval now; + struct ast_tm tmnow; + time_t beg_today; + + now = ast_tvnow(); + ast_localtime(&now, &tmnow, tzone); + /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */ + /* In any case, it saves not having to do ast_mktime() */ + beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec); + if (beg_today < t) { + /* Today */ + } else if ((beg_today - 86400) < t) { + /* Yesterday */ + res = wait_file(chan, ints, "digits/yesterday", lang); + } else if (beg_today - 86400 * 6 < t) { + /* Within the last week */ + res = ast_say_date_with_format_en(chan, t, ints, lang, "A", tzone); + } else if (beg_today - 2628000 < t) { + /* Less than a month ago - "Chu nhat ngay 13 thang 2" */ + res = ast_say_date_with_format_vi(chan, t, ints, lang, "A 'digits/day' dB", tzone); + } else if (beg_today - 15768000 < t) { + /* Less than 6 months ago - "August seventh" */ + res = ast_say_date_with_format_vi(chan, t, ints, lang, "'digits/day' dB", tzone); + } else { + /* More than 6 months ago - "April nineteenth two thousand three" */ + res = ast_say_date_with_format_vi(chan, t, ints, lang, "'digits/day' dB 'digits/year' Y", tzone); + } + } + break; + case 'R': + res = ast_say_date_with_format_vi(chan, t, ints, lang, "HM", tzone); + break; + case 'S': + /* Seconds */ + res = ast_say_number(chan, tm.tm_sec, ints, lang, (char *) NULL); + break; + case 'T': + res = ast_say_date_with_format_vi(chan, t, ints, lang, "H 'hours' M 'minutes' S 'seconds'", tzone); + break; + case ' ': + case ' ': + /* Just ignore spaces and tabs */ + break; + default: + /* Unknown character */ + ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset); + } + /* Jump out on DTMF */ + if (res) { + break; + } + } + return res; +} /*********************************** Georgian Support ***************************************/ - - /* Convert a number into a semi-localized string. Only for Georgian. res must be of at least 256 bytes, preallocated.