f5b2bdff149667955a6f431bcc12ccbbc4e74d43
[asterisk/asterisk.git] / main / say.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  * George Konstantoulakis <gkon@inaccessnetworks.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20 /*! \file
21  *
22  * \brief Say numbers and dates (maybe words one day too)
23  *
24  * \author Mark Spencer <markster@digium.com>
25  * 
26  * \note 12-16-2004 : Support for Greek added by InAccess Networks (work funded by HOL, www.hol.gr) George Konstantoulakis <gkon@inaccessnetworks.com>
27  *                                              
28  * \note 2007-02-08 : Support for Georgian added by Alexander Shaduri <ashaduri@gmail.com>,
29  *                                              Next Generation Networks (NGN).
30  * \note 2007-03-20 : Support for Thai added by Dome C. <dome@tel.co.th>,
31  *                                              IP Crossing Co., Ltd.
32  */
33
34 #include "asterisk.h"
35
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37
38 #include <netinet/in.h>
39 #include <time.h>
40 #include <ctype.h>
41 #include <math.h>
42
43 #ifdef SOLARIS
44 #include <iso/limits_iso.h>
45 #endif
46
47 #include "asterisk/file.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/say.h"
50 #include "asterisk/lock.h"
51 #include "asterisk/localtime.h"
52 #include "asterisk/utils.h"
53 #include "asterisk/app.h"
54
55 /* Forward declaration */
56 static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang);
57
58
59 static int say_character_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
60 {
61         const char *fn;
62         char fnbuf[10], asciibuf[20] = "letters/ascii";
63         char ltr;
64         int num = 0;
65         int res = 0;
66
67         while (str[num] && !res) {
68                 fn = NULL;
69                 switch (str[num]) {
70                 case ('*'):
71                         fn = "digits/star";
72                         break;
73                 case ('#'):
74                         fn = "digits/pound";
75                         break;
76                 case ('!'):
77                         fn = "letters/exclaimation-point";
78                         break;
79                 case ('@'):
80                         fn = "letters/at";
81                         break;
82                 case ('$'):
83                         fn = "letters/dollar";
84                         break;
85                 case ('-'):
86                         fn = "letters/dash";
87                         break;
88                 case ('.'):
89                         fn = "letters/dot";
90                         break;
91                 case ('='):
92                         fn = "letters/equals";
93                         break;
94                 case ('+'):
95                         fn = "letters/plus";
96                         break;
97                 case ('/'):
98                         fn = "letters/slash";
99                         break;
100                 case (' '):
101                         fn = "letters/space";
102                         break;
103                 case ('0'):
104                 case ('1'):
105                 case ('2'):
106                 case ('3'):
107                 case ('4'):
108                 case ('5'):
109                 case ('6'):
110                 case ('7'):
111                 case ('8'):
112                 case ('9'):
113                         strcpy(fnbuf, "digits/X");
114                         fnbuf[7] = str[num];
115                         fn = fnbuf;
116                         break;
117                 default:
118                         ltr = str[num];
119                         if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A';         /* file names are all lower-case */
120                         strcpy(fnbuf, "letters/X");
121                         fnbuf[8] = ltr;
122                         fn = fnbuf;
123                 }
124                 if ((fn && ast_fileexists(fn, NULL, lang) > 0) ||
125                         (snprintf(asciibuf + 13, sizeof(asciibuf) - 13, "%d", str[num]) > 0 && ast_fileexists(asciibuf, NULL, lang) > 0 && (fn = asciibuf))) {
126                         res = ast_streamfile(chan, fn, lang);
127                         if (!res) {
128                                 if ((audiofd  > -1) && (ctrlfd > -1))
129                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
130                                 else
131                                         res = ast_waitstream(chan, ints);
132                         }
133                         ast_stopstream(chan);
134                 }
135                 num++;
136         }
137
138         return res;
139 }
140
141 static int say_phonetic_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
142 {
143         const char *fn;
144         char fnbuf[256];
145         char ltr;
146         int num = 0;
147         int res = 0;
148
149         while (str[num] && !res) {
150                 fn = NULL;
151                 switch (str[num]) {
152                 case ('*'):
153                         fn = "digits/star";
154                         break;
155                 case ('#'):
156                         fn = "digits/pound";
157                         break;
158                 case ('!'):
159                         fn = "letters/exclaimation-point";
160                         break;
161                 case ('@'):
162                         fn = "letters/at";
163                         break;
164                 case ('$'):
165                         fn = "letters/dollar";
166                         break;
167                 case ('-'):
168                         fn = "letters/dash";
169                         break;
170                 case ('.'):
171                         fn = "letters/dot";
172                         break;
173                 case ('='):
174                         fn = "letters/equals";
175                         break;
176                 case ('+'):
177                         fn = "letters/plus";
178                         break;
179                 case ('/'):
180                         fn = "letters/slash";
181                         break;
182                 case (' '):
183                         fn = "letters/space";
184                         break;
185                 case ('0'):
186                 case ('1'):
187                 case ('2'):
188                 case ('3'):
189                 case ('4'):
190                 case ('5'):
191                 case ('6'):
192                 case ('7'):
193                 case ('8'):
194                         strcpy(fnbuf, "digits/X");
195                         fnbuf[7] = str[num];
196                         fn = fnbuf;
197                         break;
198                 default:        /* '9' falls here... */
199                         ltr = str[num];
200                         if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A';         /* file names are all lower-case */
201                         strcpy(fnbuf, "phonetic/X_p");
202                         fnbuf[9] = ltr;
203                         fn = fnbuf;
204                 }
205                 if (fn && ast_fileexists(fn, NULL, lang) > 0) {
206                         res = ast_streamfile(chan, fn, lang);
207                         if (!res) {
208                                 if ((audiofd  > -1) && (ctrlfd > -1))
209                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
210                                 else
211                                         res = ast_waitstream(chan, ints);
212                         }
213                         ast_stopstream(chan);
214                 }
215                 num++;
216         }
217
218         return res;
219 }
220
221 static int say_digit_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
222 {
223         const char *fn;
224         char fnbuf[256];
225         int num = 0;
226         int res = 0;
227
228         while (str[num] && !res) {
229                 fn = NULL;
230                 switch (str[num]) {
231                 case ('*'):
232                         fn = "digits/star";
233                         break;
234                 case ('#'):
235                         fn = "digits/pound";
236                         break;
237                 case ('-'):
238                         fn = "digits/minus";
239                         break;
240                 case '0':
241                 case '1':
242                 case '2':
243                 case '3':
244                 case '4':
245                 case '5':
246                 case '6':
247                 case '7':
248                 case '8':
249                 case '9':
250                         strcpy(fnbuf, "digits/X");
251                         fnbuf[7] = str[num];
252                         fn = fnbuf;
253                         break;
254                 }
255                 if (fn && ast_fileexists(fn, NULL, lang) > 0) {
256                         res = ast_streamfile(chan, fn, lang);
257                         if (!res) {
258                                 if ((audiofd  > -1) && (ctrlfd > -1))
259                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
260                                 else
261                                         res = ast_waitstream(chan, ints);
262                         }
263                         ast_stopstream(chan);
264                 }
265                 num++;
266         }
267
268         return res;
269 }
270
271 /* Forward declarations */
272 /*! \page Def_syntaxlang Asterisk Language Syntaxes supported
273     \note Not really language codes.
274         For these language codes, Asterisk will change the syntax when
275         saying numbers (and in some cases dates and voicemail messages
276         as well)
277       \arg \b da    - Danish
278       \arg \b de    - German
279       \arg \b en    - English (US)
280       \arg \b en_GB - English (British)
281       \arg \b es    - Spanish, Mexican
282       \arg \b fr    - French
283       \arg \b he    - Hebrew
284       \arg \b it    - Italian
285       \arg \b nl    - Dutch
286       \arg \b no    - Norwegian
287       \arg \b pl    - Polish       
288       \arg \b pt    - Portuguese
289       \arg \b pt_BR - Portuguese (Brazil)
290       \arg \b se    - Swedish
291       \arg \b tw    - Taiwanese / Chinese
292       \arg \b ru    - Russian
293       \arg \b ge    - Georgian
294       \arg \b hu    - Hungarian
295
296  \par Gender:
297  For Some languages the numbers differ for gender and plural.
298  \arg Use the option argument 'f' for female, 'm' for male and 'n' for neuter in languages like Portuguese, French, Spanish and German.
299  \arg use the option argument 'c' is for commune and 'n' for neuter gender in nordic languages like Danish, Swedish and Norwegian.
300  use the option argument 'p' for plural enumerations like in German
301  
302  Date/Time functions currently have less languages supported than saynumber().
303
304  \todo Note that in future, we need to move to a model where we can differentiate further - e.g. between en_US & en_UK
305
306  See contrib/i18n.testsuite.conf for some examples of the different syntaxes
307
308  \par Portuguese
309  Portuguese sound files needed for Time/Date functions:
310  pt-ah
311  pt-ao
312  pt-de
313  pt-e
314  pt-ora
315  pt-meianoite
316  pt-meiodia
317  pt-sss
318
319  \par Spanish
320  Spanish sound files needed for Time/Date functions:
321  es-de
322  es-el
323
324  \par Italian
325  Italian sound files needed for Time/Date functions:
326  ore-una
327  ore-mezzanotte
328
329 */
330
331 /* Forward declarations of language specific variants of ast_say_number_full */
332 static int ast_say_number_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
333 static int ast_say_number_full_cz(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
334 static int ast_say_number_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
335 static int ast_say_number_full_de(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
336 static int ast_say_number_full_en_GB(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
337 static int ast_say_number_full_es(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
338 static int ast_say_number_full_fr(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
339 static int ast_say_number_full_he(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
340 static int ast_say_number_full_it(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
341 static int ast_say_number_full_nl(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
342 static int ast_say_number_full_no(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
343 static int ast_say_number_full_pl(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
344 static int ast_say_number_full_pt(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
345 static int ast_say_number_full_se(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
346 static int ast_say_number_full_zh(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
347 static int ast_say_number_full_gr(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
348 static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
349 static int ast_say_number_full_ge(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
350 static int ast_say_number_full_hu(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
351 static int ast_say_number_full_th(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
352 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);
353
354 /* Forward declarations of language specific variants of ast_say_enumeration_full */
355 static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
356 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);
357 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);
358 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);
359
360 /* Forward declarations of ast_say_date, ast_say_datetime and ast_say_time functions */
361 static int ast_say_date_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
362 static int ast_say_date_da(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
363 static int ast_say_date_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
364 static int ast_say_date_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
365 static int ast_say_date_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
366 static int ast_say_date_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
367 static int ast_say_date_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
368 static int ast_say_date_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
369 static int ast_say_date_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
370 static int ast_say_date_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
371 static int ast_say_date_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
372
373 static int ast_say_date_with_format_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
374 static int ast_say_date_with_format_da(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
375 static int ast_say_date_with_format_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
376 static int ast_say_date_with_format_es(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
377 static int ast_say_date_with_format_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
378 static int ast_say_date_with_format_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
379 static int ast_say_date_with_format_it(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
380 static int ast_say_date_with_format_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
381 static int ast_say_date_with_format_pl(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
382 static int ast_say_date_with_format_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
383 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);
384 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);
385 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);
386
387 static int ast_say_time_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
388 static int ast_say_time_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
389 static int ast_say_time_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
390 static int ast_say_time_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
391 static int ast_say_time_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
392 static int ast_say_time_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
393 static int ast_say_time_zh(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
394 static int ast_say_time_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
395 static int ast_say_time_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
396 static int ast_say_time_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
397 static int ast_say_time_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
398 static int ast_say_time_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
399
400 static int ast_say_datetime_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
401 static int ast_say_datetime_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
402 static int ast_say_datetime_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
403 static int ast_say_datetime_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
404 static int ast_say_datetime_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
405 static int ast_say_datetime_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
406 static int ast_say_datetime_zh(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
407 static int ast_say_datetime_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
408 static int ast_say_datetime_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
409 static int ast_say_datetime_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
410 static int ast_say_datetime_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
411 static int ast_say_datetime_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
412
413 static int ast_say_datetime_from_now_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
414 static int ast_say_datetime_from_now_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
415 static int ast_say_datetime_from_now_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
416 static int ast_say_datetime_from_now_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
417 static int ast_say_datetime_from_now_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
418
419 static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang) 
420 {
421         int res;
422         if ((res = ast_streamfile(chan, file, lang)))
423                 ast_log(LOG_WARNING, "Unable to play message %s\n", file);
424         if (!res)
425                 res = ast_waitstream(chan, ints);
426         return res;
427 }
428
429 /*! \brief  ast_say_number_full: call language-specific functions */
430 /* Called from AGI */
431 static int say_number_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
432 {
433         if (!strcasecmp(language, "en") ) {     /* English syntax */
434            return(ast_say_number_full_en(chan, num, ints, language, audiofd, ctrlfd));
435         } else if (!strcasecmp(language, "cz") ) {      /* Czech syntax */
436            return(ast_say_number_full_cz(chan, num, ints, language, options, audiofd, ctrlfd));
437         } else if (!strcasecmp(language, "da") ) {      /* Danish syntax */
438            return(ast_say_number_full_da(chan, num, ints, language, options, audiofd, ctrlfd));
439         } else if (!strcasecmp(language, "de") ) {      /* German syntax */
440            return(ast_say_number_full_de(chan, num, ints, language, options, audiofd, ctrlfd));
441         } else if (!strcasecmp(language, "en_GB") ) {   /* British syntax */
442            return(ast_say_number_full_en_GB(chan, num, ints, language, audiofd, ctrlfd));
443         } else if (!strcasecmp(language, "no") ) {      /* Norwegian syntax */
444            return(ast_say_number_full_no(chan, num, ints, language, options, audiofd, ctrlfd));
445         } else if (!strcasecmp(language, "es") || !strcasecmp(language, "mx")) {        /* Spanish syntax */
446            return(ast_say_number_full_es(chan, num, ints, language, options, audiofd, ctrlfd));
447         } else if (!strcasecmp(language, "fr") ) {      /* French syntax */
448            return(ast_say_number_full_fr(chan, num, ints, language, options, audiofd, ctrlfd));
449         } else if (!strcasecmp(language, "he") ) {      /* Hebrew syntax */
450            return(ast_say_number_full_he(chan, num, ints, language, options, audiofd, ctrlfd));
451         } else if (!strcasecmp(language, "hu") ) {      /* Hungarian syntax */
452            return(ast_say_number_full_hu(chan, num, ints, language, audiofd, ctrlfd));
453         } else if (!strcasecmp(language, "it") ) {      /* Italian syntax */
454            return(ast_say_number_full_it(chan, num, ints, language, audiofd, ctrlfd));
455         } else if (!strcasecmp(language, "nl") ) {      /* Dutch syntax */
456            return(ast_say_number_full_nl(chan, num, ints, language, audiofd, ctrlfd));
457         } else if (!strcasecmp(language, "pl") ) {      /* Polish syntax */
458            return(ast_say_number_full_pl(chan, num, ints, language, options, audiofd, ctrlfd));
459         } else if (!strcasecmp(language, "pt") || !strcasecmp(language, "pt_BR")) {     /* Portuguese syntax */
460            return(ast_say_number_full_pt(chan, num, ints, language, options, audiofd, ctrlfd));
461         } else if (!strcasecmp(language, "se") ) {      /* Swedish syntax */
462            return(ast_say_number_full_se(chan, num, ints, language, options, audiofd, ctrlfd));
463         } else if (!strncasecmp(language, "zh", 2) ) {  /* Taiwanese / Chinese syntax */
464            return(ast_say_number_full_zh(chan, num, ints, language, audiofd, ctrlfd));
465         } else if (!strcasecmp(language, "gr") ) {      /* Greek syntax */
466            return(ast_say_number_full_gr(chan, num, ints, language, audiofd, ctrlfd));
467         } else if (!strcasecmp(language, "ru") ) {      /* Russian syntax */
468            return(ast_say_number_full_ru(chan, num, ints, language, options, audiofd, ctrlfd));
469         } else if (!strcasecmp(language, "th") ) {      /* Thai syntax */
470            return(ast_say_number_full_th(chan, num, ints, language, audiofd, ctrlfd));
471         } else if (!strcasecmp(language, "ur") ) {      /* Urdu syntax */
472                 return(ast_say_number_full_ur(chan, num, ints, language, options, audiofd, ctrlfd));
473         } else if (!strcasecmp(language, "ge") ) {      /* Georgian syntax */
474            return(ast_say_number_full_ge(chan, num, ints, language, options, audiofd, ctrlfd));
475         }
476
477         /* Default to english */
478         return(ast_say_number_full_en(chan, num, ints, language, audiofd, ctrlfd));
479 }
480
481 /*! \brief  ast_say_number_full_en: English syntax */
482 /* This is the default syntax, if no other syntax defined in this file is used */
483 static int ast_say_number_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
484 {
485         int res = 0;
486         int playh = 0;
487         char fn[256] = "";
488         if (!num) 
489                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
490
491         while (!res && (num || playh)) {
492                 if (num < 0) {
493                         ast_copy_string(fn, "digits/minus", sizeof(fn));
494                         if ( num > INT_MIN ) {
495                                 num = -num;
496                         } else {
497                                 num = 0;
498                         }       
499                 } else if (playh) {
500                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
501                         playh = 0;
502                 } else  if (num < 20) {
503                         snprintf(fn, sizeof(fn), "digits/%d", num);
504                         num = 0;
505                 } else  if (num < 100) {
506                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
507                         num %= 10;
508                 } else {
509                         if (num < 1000){
510                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100));
511                                 playh++;
512                                 num %= 100;
513                         } else {
514                                 if (num < 1000000) { /* 1,000,000 */
515                                         res = ast_say_number_full_en(chan, num / 1000, ints, language, audiofd, ctrlfd);
516                                         if (res)
517                                                 return res;
518                                         num %= 1000;
519                                         snprintf(fn, sizeof(fn), "digits/thousand");
520                                 } else {
521                                         if (num < 1000000000) { /* 1,000,000,000 */
522                                                 res = ast_say_number_full_en(chan, num / 1000000, ints, language, audiofd, ctrlfd);
523                                                 if (res)
524                                                         return res;
525                                                 num %= 1000000;
526                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
527                                         } else {
528                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
529                                                 res = -1;
530                                         }
531                                 }
532                         }
533                 }
534                 if (!res) {
535                         if (!ast_streamfile(chan, fn, language)) {
536                                 if ((audiofd  > -1) && (ctrlfd > -1))
537                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
538                                 else
539                                         res = ast_waitstream(chan, ints);
540                         }
541                         ast_stopstream(chan);
542                 }
543         }
544         return res;
545 }
546
547 static int exp10_int(int power)
548 {
549         int x, res= 1;
550         for (x=0;x<power;x++)
551                 res *= 10;
552         return res;
553 }
554
555 /*! \brief  ast_say_number_full_cz: Czech syntax */
556 /* files needed:
557  * 1m,2m - gender male
558  * 1w,2w - gender female
559  * 3,4,...,20
560  * 30,40,...,90
561  * 
562  * hundereds - 100 - sto, 200 - 2ste, 300,400 3,4sta, 500,600,...,900 5,6,...9set 
563  * 
564  * for each number 10^(3n + 3) exist 3 files represented as:
565  *              1 tousand = jeden tisic = 1_E3
566  *              2,3,4 tousands = dva,tri,ctyri tisice = 2-3_E3
567  *              5,6,... tousands = pet,sest,... tisic = 5_E3
568  *
569  *              million = _E6
570  *              miliard = _E9
571  *              etc...
572  *
573  * tousand, milion are  gender male, so 1 and 2 is 1m 2m
574  * miliard is gender female, so 1 and 2 is 1w 2w
575  */
576 static int ast_say_number_full_cz(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
577 {
578         int res = 0;
579         int playh = 0;
580         char fn[256] = "";
581         
582         int hundered = 0;
583         int left = 0;
584         int length = 0;
585         
586         /* options - w = woman, m = man, n = neutral. Defaultl is woman */
587         if (!options)
588                 options = "w";
589         
590         if (!num) 
591                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
592         
593         while (!res && (num || playh)) {
594                 if (num < 0) {
595                         ast_copy_string(fn, "digits/minus", sizeof(fn));
596                         if ( num > INT_MIN ) {
597                                 num = -num;
598                         } else {
599                                 num = 0;
600                         }       
601                 } else if (num < 3 ) {
602                         snprintf(fn, sizeof(fn), "digits/%d%c", num, options[0]);
603                         playh = 0;
604                         num = 0;
605                 } else if (num < 20) {
606                         snprintf(fn, sizeof(fn), "digits/%d", num);
607                         playh = 0;
608                         num = 0;
609                 } else if (num < 100) {
610                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
611                         num %= 10;
612                 } else if (num < 1000) {
613                         hundered = num / 100;
614                         if ( hundered == 1 ) {
615                                 ast_copy_string(fn, "digits/1sto", sizeof(fn));
616                         } else if ( hundered == 2 ) {
617                                 ast_copy_string(fn, "digits/2ste", sizeof(fn));
618                         } else {
619                                         res = ast_say_number_full_cz(chan, hundered, ints, language, options, audiofd, ctrlfd);
620                                 if (res)
621                                         return res;
622                                 if (hundered == 3 || hundered == 4) {   
623                                         ast_copy_string(fn, "digits/sta", sizeof(fn));
624                                 } else if ( hundered > 4 ) {
625                                         ast_copy_string(fn, "digits/set", sizeof(fn));
626                                 }
627                         }
628                         num -= (hundered * 100);
629                 } else { /* num > 1000 */
630                         length = (int)log10(num)+1;  
631                         while ( (length % 3 ) != 1 ) {
632                                 length--;               
633                         }
634                         left = num / (exp10_int(length-1));
635                         if ( left == 2 ) {  
636                                 switch (length-1) {
637                                         case 9: options = "w";  /* 1,000,000,000 gender female */
638                                                 break;
639                                         default : options = "m"; /* others are male */
640                                 }
641                         }
642                         if ( left > 1 ) { /* we dont say "one thousand" but only thousand */
643                                 res = ast_say_number_full_cz(chan, left, ints, language, options, audiofd, ctrlfd);
644                                 if (res) 
645                                         return res;
646                         }
647                         if ( left >= 5 ) { /* >= 5 have the same declesion */
648                                 snprintf(fn, sizeof(fn), "digits/5_E%d", length - 1);   
649                         } else if ( left >= 2 && left <= 4 ) {
650                                 snprintf(fn, sizeof(fn), "digits/2-4_E%d", length - 1);
651                         } else { /* left == 1 */
652                                 snprintf(fn, sizeof(fn), "digits/1_E%d", length - 1);
653                         }
654                         num -= left * (exp10_int(length-1));
655                 }
656                 if (!res) {
657                         if (!ast_streamfile(chan, fn, language)) {
658                                 if ((audiofd > -1) && (ctrlfd > -1)) {
659                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
660                                 } else {
661                                         res = ast_waitstream(chan, ints);
662                                 }
663                         }
664                         ast_stopstream(chan);
665                 }
666         }
667         return res; 
668 }
669
670 /*! \brief  ast_say_number_full_da: Danish syntax */
671 /* New files:
672  In addition to English, the following sounds are required: "1N", "millions", "and" and "1-and" through "9-and" 
673  */
674 static int ast_say_number_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
675 {
676         int res = 0;
677         int playh = 0;
678         int playa = 0;
679         int cn = 1;             /* +1 = commune; -1 = neuter */
680         char fn[256] = "";
681         if (!num) 
682                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
683
684         if (options && !strncasecmp(options, "n", 1)) cn = -1;
685
686         while (!res && (num || playh || playa )) {
687                 /* The grammar for Danish numbers is the same as for English except
688                 * for the following:
689                 * - 1 exists in both commune ("en", file "1N") and neuter ("et", file "1")
690                 * - numbers 20 through 99 are said in reverse order, i.e. 21 is
691                 *   "one-and twenty" and 68 is "eight-and sixty".
692                 * - "million" is different in singular and plural form
693                 * - numbers > 1000 with zero as the third digit from last have an
694                 *   "and" before the last two digits, i.e. 2034 is "two thousand and
695                 *   four-and thirty" and 1000012 is "one million and twelve".
696                 */
697                 if (num < 0) {
698                         ast_copy_string(fn, "digits/minus", sizeof(fn));
699                         if ( num > INT_MIN ) {
700                                 num = -num;
701                         } else {
702                                 num = 0;
703                         }       
704                 } else if (playh) {
705                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
706                         playh = 0;
707                 } else if (playa) {
708                         ast_copy_string(fn, "digits/and", sizeof(fn));
709                         playa = 0;
710                 } else if (num == 1 && cn == -1) {
711                         ast_copy_string(fn, "digits/1N", sizeof(fn));
712                         num = 0;
713                 } else if (num < 20) {
714                         snprintf(fn, sizeof(fn), "digits/%d", num);
715                         num = 0;
716                 } else if (num < 100) {
717                         int ones = num % 10;
718                         if (ones) {
719                                 snprintf(fn, sizeof(fn), "digits/%d-and", ones);
720                                 num -= ones;
721                         } else {
722                                 snprintf(fn, sizeof(fn), "digits/%d", num);
723                                 num = 0;
724                         }
725                 } else {
726                         if (num < 1000) {
727                                 int hundreds = num / 100;
728                                 if (hundreds == 1)
729                                         ast_copy_string(fn, "digits/1N", sizeof(fn));
730                                 else
731                                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
732
733                                 playh++;
734                                 num -= 100 * hundreds;
735                                 if (num)
736                                         playa++;
737
738                         } else {
739                                 if (num < 1000000) {
740                                         res = ast_say_number_full_da(chan, num / 1000, ints, language, "n", audiofd, ctrlfd);
741                                         if (res)
742                                                 return res;
743                                         num = num % 1000;
744                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
745                                 } else {
746                                         if (num < 1000000000) {
747                                                 int millions = num / 1000000;
748                                                 res = ast_say_number_full_da(chan, millions, ints, language, "c", audiofd, ctrlfd);
749                                                 if (res)
750                                                         return res;
751                                                 if (millions == 1)
752                                                         ast_copy_string(fn, "digits/million", sizeof(fn));
753                                                 else
754                                                         ast_copy_string(fn, "digits/millions", sizeof(fn));
755                                                 num = num % 1000000;
756                                         } else {
757                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
758                                                 res = -1;
759                                         }
760                                 }
761                                 if (num && num < 100)
762                                         playa++;
763                         }
764                 }
765                 if (!res) {
766                         if (!ast_streamfile(chan, fn, language)) {
767                                 if ((audiofd > -1) && (ctrlfd > -1)) 
768                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
769                                 else  
770                                         res = ast_waitstream(chan, ints);
771                         }
772                         ast_stopstream(chan);
773                 }
774         }
775         return res;
776 }
777
778 /*! \brief  ast_say_number_full_de: German syntax */
779 /* New files:
780  In addition to English, the following sounds are required:
781  "millions"
782  "1-and" through "9-and" 
783  "1F" (eine)
784  "1N" (ein)
785  NB "1" is recorded as 'eins'
786  */
787 static int ast_say_number_full_de(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
788 {
789         int res = 0, t = 0;
790         int mf = 1;                            /* +1 = male and neuter; -1 = female */
791         char fn[256] = "";
792         char fna[256] = "";
793         if (!num) 
794                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
795
796         if (options && (!strncasecmp(options, "f", 1)))
797                 mf = -1;
798
799         while (!res && num) {
800                 /* The grammar for German numbers is the same as for English except
801                 * for the following:
802                 * - numbers 20 through 99 are said in reverse order, i.e. 21 is
803                 *   "one-and twenty" and 68 is "eight-and sixty".
804                 * - "one" varies according to gender
805                 * - 100 is 'hundert', however all other instances are 'ein hundert'
806                 * - 1000 is 'tausend', however all other instances are 'ein tausend'
807                 * - 1000000 is always 'eine million'
808                 * - "million" is different in singular and plural form
809                 */
810                 if (num < 0) {
811                         ast_copy_string(fn, "digits/minus", sizeof(fn));
812                         if ( num > INT_MIN ) {
813                                 num = -num;
814                         } else {
815                                 num = 0;
816                         }       
817                 } else if (num < 100 && t) {
818                         ast_copy_string(fn, "digits/and", sizeof(fn));
819                         t = 0;
820                 } else if (num == 1 && mf == -1) {
821                         snprintf(fn, sizeof(fn), "digits/%dF", num);
822                         num = 0;
823                 } else if (num < 20) {
824                         snprintf(fn, sizeof(fn), "digits/%d", num);
825                         num = 0;
826                 } else if (num < 100) {
827                         int ones = num % 10;
828                         if (ones) {
829                                 snprintf(fn, sizeof(fn), "digits/%d-and", ones);
830                                 num -= ones;
831                         } else {
832                                 snprintf(fn, sizeof(fn), "digits/%d", num);
833                                 num = 0;
834                         }
835                 } else if (num == 100 && t == 0) {
836                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
837                         num = 0;
838                 } else if (num < 1000) {
839                         int hundreds = num / 100;
840                         num = num % 100;
841                         if (hundreds == 1) {
842                                 ast_copy_string(fn, "digits/1N", sizeof(fn));
843                         } else {
844                                 snprintf(fn, sizeof(fn), "digits/%d", hundreds);
845                         }
846                         ast_copy_string(fna, "digits/hundred", sizeof(fna));
847                         t = 1;
848                 } else if (num == 1000 && t == 0) {
849                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
850                         num = 0;
851                 } else  if (num < 1000000) {
852                         int thousands = num / 1000;
853                         num = num % 1000;
854                         t = 1;
855                         if (thousands == 1) {
856                                 ast_copy_string(fn, "digits/1N", sizeof(fn));
857                                 ast_copy_string(fna, "digits/thousand", sizeof(fna));
858                         } else {
859                                 res = ast_say_number_full_de(chan, thousands, ints, language, options, audiofd, ctrlfd);
860                                 if (res)
861                                         return res;
862                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
863                         }
864                 } else if (num < 1000000000) {
865                         int millions = num / 1000000;
866                         num = num % 1000000;
867                         t = 1;
868                         if (millions == 1) {
869                                 ast_copy_string(fn, "digits/1F", sizeof(fn));
870                                 ast_copy_string(fna, "digits/million", sizeof(fna));
871                         } else {
872                                 res = ast_say_number_full_de(chan, millions, ints, language, options, audiofd, ctrlfd);
873                                 if (res)
874                                         return res;
875                                 ast_copy_string(fn, "digits/millions", sizeof(fn));
876                         }
877                 } else if (num <= INT_MAX) {
878                         int billions = num / 1000000000;
879                         num = num % 1000000000;
880                         t = 1;
881                         if (billions == 1) {
882                                 ast_copy_string(fn, "digits/1F", sizeof(fn));
883                                 ast_copy_string(fna, "digits/milliard", sizeof(fna));
884                         } else {
885                                 res = ast_say_number_full_de(chan, billions, ints, language, options, audiofd, ctrlfd);
886                                 if (res) {
887                                         return res;
888                                 }
889                                 ast_copy_string(fn, "digits/milliards", sizeof(fn));
890                         }
891                 } else {
892                         ast_debug(1, "Number '%d' is too big for me\n", num);
893                         res = -1;
894                 }
895                 if (!res) {
896                         if (!ast_streamfile(chan, fn, language)) {
897                                 if ((audiofd > -1) && (ctrlfd > -1)) 
898                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
899                                 else  
900                                         res = ast_waitstream(chan, ints);
901                         }
902                         ast_stopstream(chan);
903                         if (!res) {
904                                 if (strlen(fna) != 0 && !ast_streamfile(chan, fna, language)) {
905                                         if ((audiofd > -1) && (ctrlfd > -1))
906                                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
907                                         else
908                                                 res = ast_waitstream(chan, ints);
909                                 }
910                                 ast_stopstream(chan);
911                                 strcpy(fna, "");
912                         }
913                 }
914         }
915         return res;
916 }
917
918 /*! \brief  ast_say_number_full_en_GB: British and Norwegian syntax */
919 /* New files:
920  In addition to American English, the following sounds are required:  "and"
921  */
922 static int ast_say_number_full_en_GB(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
923 {
924         int res = 0;
925         int playh = 0;
926         int playa = 0;
927         char fn[256] = "";
928         if (!num) 
929                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
930
931         while (!res && (num || playh || playa )) {
932                 if (num < 0) {
933                         ast_copy_string(fn, "digits/minus", sizeof(fn));
934                         if ( num > INT_MIN ) {
935                                 num = -num;
936                         } else {
937                                 num = 0;
938                         }       
939                 } else if (playh) {
940                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
941                         playh = 0;
942                 } else if (playa) {
943                         ast_copy_string(fn, "digits/and", sizeof(fn));
944                         playa = 0;
945                 } else if (num < 20) {
946                         snprintf(fn, sizeof(fn), "digits/%d", num);
947                         num = 0;
948                 } else if (num < 100) {
949                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
950                         num %= 10;
951                 } else if (num < 1000) {
952                         int hundreds = num / 100;
953                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
954
955                         playh++;
956                         num -= 100 * hundreds;
957                         if (num)
958                                 playa++;
959                 } else  if (num < 1000000) {
960                         res = ast_say_number_full_en_GB(chan, num / 1000, ints, language, audiofd, ctrlfd);
961                         if (res)
962                                 return res;
963                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
964                         num %= 1000;
965                         if (num && num < 100)
966                                 playa++;
967                 } else  if (num < 1000000000) {
968                                 int millions = num / 1000000;
969                                 res = ast_say_number_full_en_GB(chan, millions, ints, language, audiofd, ctrlfd);
970                                 if (res)
971                                         return res;
972                                 ast_copy_string(fn, "digits/million", sizeof(fn));
973                                 num %= 1000000;
974                                 if (num && num < 100)
975                                         playa++;
976                 } else {
977                                 ast_debug(1, "Number '%d' is too big for me\n", num);
978                                 res = -1;
979                 }
980                 
981                 if (!res) {
982                         if (!ast_streamfile(chan, fn, language)) {
983                                 if ((audiofd > -1) && (ctrlfd > -1)) 
984                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
985                                 else  
986                                         res = ast_waitstream(chan, ints);
987                         }
988                         ast_stopstream(chan);
989                 }
990         }
991         return res;
992 }
993
994 /*! \brief  ast_say_number_full_es: Spanish syntax */
995 /* New files:
996  Requires a few new audios:
997    1F.gsm: feminine 'una'
998    21.gsm thru 29.gsm, cien.gsm, mil.gsm, millon.gsm, millones.gsm, 100.gsm, 200.gsm, 300.gsm, 400.gsm, 500.gsm, 600.gsm, 700.gsm, 800.gsm, 900.gsm, y.gsm 
999  */
1000 static int ast_say_number_full_es(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
1001 {
1002         int res = 0;
1003         int playa = 0;
1004         int mf = 0;                            /* +1 = male; -1 = female */
1005         char fn[256] = "";
1006         if (!num) 
1007                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1008
1009         if (options) {
1010                 if (!strncasecmp(options, "f", 1))
1011                         mf = -1;
1012                 else if (!strncasecmp(options, "m", 1))
1013                         mf = 1;
1014         }
1015
1016         while (!res && num) {
1017                 if (num < 0) {
1018                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1019                         if ( num > INT_MIN ) {
1020                                 num = -num;
1021                         } else {
1022                                 num = 0;
1023                         }       
1024                 } else if (playa) {
1025                         ast_copy_string(fn, "digits/and", sizeof(fn));
1026                         playa = 0;
1027                 } else if (num == 1) {
1028                         if (mf < 0)
1029                                 snprintf(fn, sizeof(fn), "digits/%dF", num);
1030                         else if (mf > 0)
1031                                 snprintf(fn, sizeof(fn), "digits/%dM", num);
1032                         else 
1033                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1034                         num = 0;
1035                 } else if (num < 31) {
1036                         snprintf(fn, sizeof(fn), "digits/%d", num);
1037                         num = 0;
1038                 } else if (num < 100) {
1039                         snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10);
1040                         num %= 10;
1041                         if (num)
1042                                 playa++;
1043                 } else if (num == 100) {
1044                         ast_copy_string(fn, "digits/100", sizeof(fn));
1045                         num = 0;
1046                 } else if (num < 200) {
1047                         ast_copy_string(fn, "digits/100-and", sizeof(fn));
1048                         num -= 100;
1049                 } else {
1050                         if (num < 1000) {
1051                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100)*100);
1052                                 num %= 100;
1053                         } else if (num < 2000) {
1054                                 num %= 1000;
1055                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
1056                         } else {
1057                                 if (num < 1000000) {
1058                                         res = ast_say_number_full_es(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
1059                                         if (res)
1060                                                 return res;
1061                                         num %= 1000;
1062                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1063                                 } else {
1064                                         if (num < 2147483640) {
1065                                                 if ((num/1000000) == 1) {
1066                                                         res = ast_say_number_full_es(chan, num / 1000000, ints, language, "M", audiofd, ctrlfd);
1067                                                         if (res)
1068                                                                 return res;
1069                                                         ast_copy_string(fn, "digits/million", sizeof(fn));
1070                                                 } else {
1071                                                         res = ast_say_number_full_es(chan, num / 1000000, ints, language, options, audiofd, ctrlfd);
1072                                                         if (res)
1073                                                                 return res;
1074                                                         ast_copy_string(fn, "digits/millions", sizeof(fn));
1075                                                 }
1076                                                 num %= 1000000;
1077                                         } else {
1078                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1079                                                 res = -1;
1080                                         }
1081                                 }
1082                         }
1083                 }
1084
1085                 if (!res) {
1086                         if (!ast_streamfile(chan, fn, language)) {
1087                                 if ((audiofd > -1) && (ctrlfd > -1))
1088                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1089                                 else
1090                                         res = ast_waitstream(chan, ints);
1091                         }
1092                         ast_stopstream(chan);
1093
1094                 }
1095                         
1096         }
1097         return res;
1098 }
1099
1100 /*! \brief  ast_say_number_full_fr: French syntax */
1101 /*      Extra sounds needed:
1102         1F: feminin 'une'
1103         et: 'and' */
1104 static int ast_say_number_full_fr(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
1105 {
1106         int res = 0;
1107         int playh = 0;
1108         int playa = 0;
1109         int mf = 1;                            /* +1 = male; -1 = female */
1110         char fn[256] = "";
1111         if (!num) 
1112                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1113         
1114         if (options && !strncasecmp(options, "f", 1))
1115                 mf = -1;
1116
1117         while (!res && (num || playh || playa)) {
1118                 if (num < 0) {
1119                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1120                         if ( num > INT_MIN ) {
1121                                 num = -num;
1122                         } else {
1123                                 num = 0;
1124                         }       
1125                 } else if (playh) {
1126                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1127                         playh = 0;
1128                 } else if (playa) {
1129                         ast_copy_string(fn, "digits/et", sizeof(fn));
1130                         playa = 0;
1131                 } else if (num == 1) {
1132                         if (mf < 0)
1133                                 snprintf(fn, sizeof(fn), "digits/%dF", num);
1134                         else
1135                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1136                         num = 0;
1137                 } else if (num < 21) {
1138                         snprintf(fn, sizeof(fn), "digits/%d", num);
1139                         num = 0;
1140                 } else if (num < 70) {
1141                         snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10);
1142                         if ((num % 10) == 1) playa++;
1143                         num = num % 10;
1144                 } else if (num < 80) {
1145                         ast_copy_string(fn, "digits/60", sizeof(fn));
1146                         if ((num % 10) == 1) playa++;
1147                         num -= 60;
1148                 } else if (num < 100) {
1149                         ast_copy_string(fn, "digits/80", sizeof(fn));
1150                         num = num - 80;
1151                 } else if (num < 200) {
1152                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1153                         num = num - 100;
1154                 } else if (num < 1000) {
1155                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
1156                         playh++;
1157                         num = num % 100;
1158                 } else if (num < 2000) {
1159                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1160                         num = num - 1000;
1161                 } else if (num < 1000000) {
1162                         res = ast_say_number_full_fr(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
1163                         if (res)
1164                                 return res;
1165                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1166                         num = num % 1000;
1167                 } else  if (num < 1000000000) {
1168                         res = ast_say_number_full_fr(chan, num / 1000000, ints, language, options, audiofd, ctrlfd);
1169                         if (res)
1170                                 return res;
1171                         ast_copy_string(fn, "digits/million", sizeof(fn));
1172                         num = num % 1000000;
1173                 } else {
1174                         ast_debug(1, "Number '%d' is too big for me\n", num);
1175                         res = -1;
1176                 }
1177                 if (!res) {
1178                         if (!ast_streamfile(chan, fn, language)) {
1179                                 if ((audiofd > -1) && (ctrlfd > -1))
1180                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1181                                 else
1182                                         res = ast_waitstream(chan, ints);
1183                         }
1184                         ast_stopstream(chan);
1185                 }
1186         }
1187         return res;
1188 }
1189
1190
1191
1192 /* Hebrew syntax */
1193 /* Check doc/lang/hebrew-digits.txt for information about the various
1194  * recordings required to make this translation work properly */
1195 #define SAY_NUM_BUF_SIZE 256
1196 static int ast_say_number_full_he(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
1197 {
1198         int res = 0;
1199         int state = 0;                          /* no need to save anything */
1200         int mf = -1;                            /* +1 = Masculin; -1 = Feminin */
1201         int tmpnum = 0;
1202
1203         char fn[SAY_NUM_BUF_SIZE] = "";
1204
1205         ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: started. num: %d, options=\"%s\"\n", num, options);
1206
1207         if (!num) {
1208                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1209         }
1210         if (options && !strncasecmp(options, "m", 1)) {
1211                 mf = 1;
1212         }
1213         ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, state=%d, options=\"%s\", mf=%d\n", num, state, options, mf);
1214
1215         /* Do we have work to do? */
1216         while (!res && (num || (state > 0))) {
1217                 /* first type of work: play a second sound. In this loop
1218                  * we can only play one sound file at a time. Thus playing
1219                  * a second one requires repeating the loop just for the
1220                  * second file. The variable 'state' remembers where we were.
1221                  * state==0 is the normal mode and it means that we continue
1222                  * to check if the number num has yet anything left.
1223                  */
1224                 ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, state=%d, options=\"%s\", mf=%d, tmpnum=%d\n", num, state, options, mf, tmpnum);
1225
1226                 if (state == 1) {
1227                         state = 0;
1228                 } else if (state == 2) {
1229                         if ((num >= 11) && (num < 21)) {
1230                                 if (mf < 0) {
1231                                         snprintf(fn, sizeof(fn), "digits/ve");
1232                                 } else {
1233                                         snprintf(fn, sizeof(fn), "digits/uu");
1234                                 }
1235                         } else {
1236                                 switch (num) {
1237                                 case 1:
1238                                         snprintf(fn, sizeof(fn), "digits/ve");
1239                                         break;
1240                                 case 2:
1241                                         snprintf(fn, sizeof(fn), "digits/uu");
1242                                         break;
1243                                 case 3:
1244                                         if (mf < 0) {
1245                                                 snprintf(fn, sizeof(fn), "digits/ve");
1246                                         } else {
1247                                                 snprintf(fn, sizeof(fn), "digits/uu");
1248                                         }
1249                                         break;
1250                                 case 4:
1251                                         snprintf(fn, sizeof(fn), "digits/ve");
1252                                         break;
1253                                 case 5:
1254                                         snprintf(fn, sizeof(fn), "digits/ve");
1255                                         break;
1256                                 case 6:
1257                                         snprintf(fn, sizeof(fn), "digits/ve");
1258                                         break;
1259                                 case 7:
1260                                         snprintf(fn, sizeof(fn), "digits/ve");
1261                                         break;
1262                                 case 8:
1263                                         snprintf(fn, sizeof(fn), "digits/uu");
1264                                         break;
1265                                 case 9:
1266                                         snprintf(fn, sizeof(fn), "digits/ve");
1267                                         break;
1268                                 case 10:
1269                                         snprintf(fn, sizeof(fn), "digits/ve");
1270                                         break;
1271                                 }
1272                         }
1273                         state = 0;
1274                 } else if (state == 3) {
1275                         snprintf(fn, sizeof(fn), "digits/1k");
1276                         state = 0;
1277                 } else if (num < 0) {
1278                         snprintf(fn, sizeof(fn), "digits/minus");
1279                         num = (-1) * num;
1280                 } else if (num < 20) {
1281                         if (mf < 0) {
1282                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1283                         } else {
1284                                 snprintf(fn, sizeof(fn), "digits/%dm", num);
1285                         }
1286                         num = 0;
1287                 } else if ((num < 100) && (num >= 20)) {
1288                         snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
1289                         num = num % 10;
1290                         if (num > 0) {
1291                                 state = 2;
1292                         }
1293                 } else if ((num >= 100) && (num < 1000)) {
1294                         tmpnum = num / 100;
1295                         snprintf(fn, sizeof(fn), "digits/%d00", tmpnum);
1296                         num = num - (tmpnum * 100);
1297                         if ((num > 0) && (num < 11)) {
1298                                 state = 2;
1299                         }
1300                 } else if ((num >= 1000) && (num < 10000)) {
1301                         tmpnum = num / 1000;
1302                         snprintf(fn, sizeof(fn), "digits/%dk", tmpnum);
1303                         num = num - (tmpnum * 1000);
1304                         if ((num > 0) && (num < 11)) {
1305                                 state = 2;
1306                         }
1307                 } else if (num < 20000) {
1308                         snprintf(fn, sizeof(fn), "digits/%dm", (num / 1000));
1309                         num = num % 1000;
1310                         state = 3;
1311                 } else if (num < 1000000) {
1312                         res = ast_say_number_full_he(chan, num / 1000, ints, language, "m", audiofd, ctrlfd);
1313                         if (res) {
1314                                 return res;
1315                         }
1316                         snprintf(fn, sizeof(fn), "digits/1k");
1317                         num = num % 1000;
1318                         if ((num > 0) && (num < 11)) {
1319                                 state = 2;
1320                         }
1321                 } else if (num < 2000000) {
1322                         snprintf(fn, sizeof(fn), "digits/million");
1323                         num = num % 1000000;
1324                         if ((num > 0) && (num < 11)) {
1325                                 state = 2;
1326                         }
1327                 } else if (num < 3000000) {
1328                         snprintf(fn, sizeof(fn), "digits/twomillion");
1329                         num = num - 2000000;
1330                         if ((num > 0) && (num < 11)) {
1331                                 state = 2;
1332                         }
1333                 } else if (num < 1000000000) {
1334                         res = ast_say_number_full_he(chan, num / 1000000, ints, language, "m", audiofd, ctrlfd);
1335                         if (res) {
1336                                 return res;
1337                         }
1338                         snprintf(fn, sizeof(fn), "digits/million");
1339                         num = num % 1000000;
1340                         if ((num > 0) && (num < 11)) {
1341                                 state = 2;
1342                         }
1343                 } else {
1344                         ast_debug(1, "Number '%d' is too big for me\n", num);
1345                         res = -1;
1346                 }
1347                 tmpnum = 0;
1348                 if (!res) {
1349                         if (!ast_streamfile(chan, fn, language)) {
1350                                 if ((audiofd > -1) && (ctrlfd > -1)) {
1351                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1352                                 } else {
1353                                         res = ast_waitstream(chan, ints);
1354                                 }
1355                         }
1356                         ast_stopstream(chan);
1357                 }
1358         }
1359         return res;
1360 }
1361
1362 /*! \brief  ast_say_number_full_hu: Hungarian syntax */
1363 /* Extra sounds need:
1364         10en: "tizen"
1365         20on: "huszon"
1366 */
1367 static int ast_say_number_full_hu(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
1368 {
1369         int res = 0;
1370         int playh = 0;
1371         char fn[256] = "";
1372         if (!num) 
1373                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1374
1375         /*
1376         Hungarian support
1377         like english, except numbers up to 29 are from 2 words.
1378         10 and first word of 1[1-9] and 20 and first word of 2[1-9] are different.
1379         */
1380
1381         while(!res && (num || playh)) {
1382                 if (num < 0) {
1383                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1384                         if ( num > INT_MIN ) {
1385                                 num = -num;
1386                         } else {
1387                                 num = 0;
1388                         }       
1389                 } else if (playh) {
1390                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1391                         playh = 0;
1392                 } else if (num < 11 || num == 20) {
1393                         snprintf(fn, sizeof(fn), "digits/%d", num);
1394                         num = 0;
1395                 } else if (num < 20) {
1396                         ast_copy_string(fn, "digits/10en", sizeof(fn));
1397                         num -= 10;
1398                 } else if (num < 30) {
1399                         ast_copy_string(fn, "digits/20on", sizeof(fn));
1400                         num -= 20;
1401                 } else  if (num < 100) {
1402                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
1403                         num %= 10;
1404                 } else {
1405                         if (num < 1000){
1406                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100));
1407                                 playh++;
1408                                 num %= 100;
1409                         } else {
1410                                 if (num < 1000000) { /* 1,000,000 */
1411                                         res = ast_say_number_full_hu(chan, num / 1000, ints, language, audiofd, ctrlfd);
1412                                         if (res)
1413                                                 return res;
1414                                         num %= 1000;
1415                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1416                                 } else {
1417                                         if (num < 1000000000) { /* 1,000,000,000 */
1418                                                 res = ast_say_number_full_hu(chan, num / 1000000, ints, language, audiofd, ctrlfd);
1419                                                 if (res)
1420                                                         return res;
1421                                                 num %= 1000000;
1422                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1423                                         } else {
1424                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1425                                                 res = -1;
1426                                         }
1427                                 }
1428                         }
1429                 }
1430                 if (!res) {
1431                         if(!ast_streamfile(chan, fn, language)) {
1432                                 if ((audiofd  > -1) && (ctrlfd > -1))
1433                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1434                                 else
1435                                         res = ast_waitstream(chan, ints);
1436                         }
1437                         ast_stopstream(chan);
1438                 }
1439         }
1440         return res;
1441 }
1442
1443 /*! \brief  ast_say_number_full_it:  Italian */
1444 static int ast_say_number_full_it(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
1445 {
1446         int res = 0;
1447         int playh = 0;
1448         int tempnum = 0;
1449         char fn[256] = "";
1450
1451         if (!num)
1452                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1453
1454                 /*
1455                 Italian support
1456
1457                 Like english, numbers up to 20 are a single 'word', and others
1458                 compound, but with exceptions.
1459                 For example 21 is not twenty-one, but there is a single word in 'it'.
1460                 Idem for 28 (ie when a the 2nd part of a compund number
1461                 starts with a vowel)
1462
1463                 There are exceptions also for hundred, thousand and million.
1464                 In english 100 = one hundred, 200 is two hundred.
1465                 In italian 100 = cento , like to say hundred (without one),
1466                 200 and more are like english.
1467                 
1468                 Same applies for thousand:
1469                 1000 is one thousand in en, 2000 is two thousand.
1470                 In it we have 1000 = mille , 2000 = 2 mila 
1471
1472                 For million(s) we use the plural, if more than one
1473                 Also, one million is abbreviated in it, like on-million,
1474                 or 'un milione', not 'uno milione'.
1475                 So the right file is provided.
1476                 */
1477
1478         while (!res && (num || playh)) {
1479                         if (num < 0) {
1480                                 ast_copy_string(fn, "digits/minus", sizeof(fn));
1481                                 if ( num > INT_MIN ) {
1482                                         num = -num;
1483                                 } else {
1484                                         num = 0;
1485                                 }       
1486                         } else if (playh) {
1487                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
1488                                 playh = 0;
1489                         } else if (num < 20) {
1490                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1491                                 num = 0;
1492                         } else if (num == 21) {
1493                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1494                                 num = 0;
1495                         } else if (num == 28) {
1496                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1497                                 num = 0;
1498                         } else if (num == 31) {
1499                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1500                                 num = 0;
1501                         } else if (num == 38) {
1502                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1503                                 num = 0;
1504                         } else if (num == 41) {
1505                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1506                                 num = 0;
1507                         } else if (num == 48) {
1508                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1509                                 num = 0;
1510                         } else if (num == 51) {
1511                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1512                                 num = 0;
1513                         } else if (num == 58) {
1514                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1515                                 num = 0;
1516                         } else if (num == 61) {
1517                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1518                                 num = 0;
1519                         } else if (num == 68) {
1520                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1521                                 num = 0;
1522                         } else if (num == 71) {
1523                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1524                                 num = 0;
1525                         } else if (num == 78) {
1526                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1527                                 num = 0;
1528                         } else if (num == 81) {
1529                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1530                                 num = 0;
1531                         } else if (num == 88) {
1532                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1533                                 num = 0;
1534                         } else if (num == 91) {
1535                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1536                                 num = 0;
1537                         } else if (num == 98) {
1538                                 snprintf(fn, sizeof(fn), "digits/%d", num);
1539                                 num = 0;
1540                         } else if (num < 100) {
1541                                 snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
1542                                 num %= 10;
1543                         } else {
1544                                 if (num < 1000) {
1545                                         if ((num / 100) > 1) {
1546                                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100));
1547                                                 playh++;
1548                                         } else {
1549                                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
1550                                         }
1551                                         num %= 100;
1552                                 } else {
1553                                         if (num < 1000000) { /* 1,000,000 */
1554                                                 if ((num/1000) > 1)
1555                                                         res = ast_say_number_full_it(chan, num / 1000, ints, language, audiofd, ctrlfd);
1556                                                 if (res)
1557                                                         return res;
1558                                                 tempnum = num;
1559                                                 num %= 1000;
1560                                                 if ((tempnum / 1000) < 2)
1561                                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1562                                                 else /* for 1000 it says mille, for >1000 (eg 2000) says mila */
1563                                                         ast_copy_string(fn, "digits/thousands", sizeof(fn));
1564                                         } else {
1565                                                 if (num < 1000000000) { /* 1,000,000,000 */
1566                                                         if ((num / 1000000) > 1)
1567                                                                 res = ast_say_number_full_it(chan, num / 1000000, ints, language, audiofd, ctrlfd);
1568                                                         if (res)
1569                                                                 return res;
1570                                                         tempnum = num;
1571                                                         num %= 1000000;
1572                                                         if ((tempnum / 1000000) < 2)
1573                                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1574                                                         else
1575                                                                 ast_copy_string(fn, "digits/millions", sizeof(fn));
1576                                                 } else {
1577                                                         ast_debug(1, "Number '%d' is too big for me\n", num);
1578                                                         res = -1;
1579                                                 }
1580                                         }
1581                                 }
1582                         }
1583                         if (!res) {
1584                                 if (!ast_streamfile(chan, fn, language)) {
1585                                         if ((audiofd > -1) && (ctrlfd > -1))
1586                                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1587                                         else
1588                                                 res = ast_waitstream(chan, ints);
1589                                 }
1590                                 ast_stopstream(chan);
1591                         }
1592                 }
1593         return res;
1594 }
1595
1596 /*! \brief  ast_say_number_full_nl: dutch syntax */
1597 /* New files: digits/nl-en
1598  */
1599 static int ast_say_number_full_nl(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
1600 {
1601         int res = 0;
1602         int playh = 0;
1603         int units = 0;
1604         char fn[256] = "";
1605         if (!num) 
1606                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1607         while (!res && (num || playh )) {
1608                 if (num < 0) {
1609                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1610                         if ( num > INT_MIN ) {
1611                                 num = -num;
1612                         } else {
1613                                 num = 0;
1614                         }       
1615                 } else if (playh) {
1616                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1617                         playh = 0;
1618                 } else if (num < 20) {
1619                         snprintf(fn, sizeof(fn), "digits/%d", num);
1620                         num = 0;
1621                 } else if (num < 100) {
1622                         units = num % 10;
1623                         if (units > 0) {
1624                                 res = ast_say_number_full_nl(chan, units, ints, language, audiofd, ctrlfd);
1625                                 if (res)
1626                                         return res;
1627                                 num = num - units;
1628                                 ast_copy_string(fn, "digits/nl-en", sizeof(fn));
1629                         } else {
1630                                 snprintf(fn, sizeof(fn), "digits/%d", num - units);
1631                                 num = 0;
1632                         }
1633                 } else if (num < 200) {
1634                         /* hundred, not one-hundred */
1635                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1636                         num %= 100;
1637                 } else if (num < 1000) {
1638                         snprintf(fn, sizeof(fn), "digits/%d", num / 100);
1639                         playh++;
1640                         num %= 100;
1641                 } else {
1642                         if (num < 1100) {
1643                                 /* thousand, not one-thousand */
1644                                 num %= 1000;
1645                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
1646                         } else if (num < 10000) { /* 1,100 to 9,9999 */
1647                                 res = ast_say_number_full_nl(chan, num / 100, ints, language, audiofd, ctrlfd);
1648                                 if (res)
1649                                         return res;
1650                                 num %= 100;
1651                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
1652                         } else {
1653                                 if (num < 1000000) { /* 1,000,000 */
1654                                         res = ast_say_number_full_nl(chan, num / 1000, ints, language, audiofd, ctrlfd);
1655                                         if (res)
1656                                                 return res;
1657                                         num %= 1000;
1658                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1659                                 } else {
1660                                         if (num < 1000000000) { /* 1,000,000,000 */
1661                                                 res = ast_say_number_full_nl(chan, num / 1000000, ints, language, audiofd, ctrlfd);
1662                                                 if (res)
1663                                                         return res;
1664                                                 num %= 1000000;
1665                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1666                                         } else {
1667                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1668                                                 res = -1;
1669                                         }
1670                                 }
1671                         }
1672                 }
1673
1674                 if (!res) {
1675                         if (!ast_streamfile(chan, fn, language)) {
1676                                 if ((audiofd > -1) && (ctrlfd > -1))
1677                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1678                                 else
1679                                         res = ast_waitstream(chan, ints);
1680                         }
1681                         ast_stopstream(chan);
1682                 }
1683         }
1684         return res;
1685 }
1686
1687 /*! \brief  ast_say_number_full_no: Norwegian syntax */
1688 /* New files:
1689  In addition to American English, the following sounds are required:  "and", "1N"
1690  */
1691 static int ast_say_number_full_no(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
1692 {
1693         int res = 0;
1694         int playh = 0;
1695         int playa = 0;
1696         int cn = 1;             /* +1 = commune; -1 = neuter */
1697         char fn[256] = "";
1698         
1699         if (!num) 
1700                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
1701         
1702         if (options && !strncasecmp(options, "n", 1)) cn = -1;
1703
1704         while (!res && (num || playh || playa )) {
1705                 /* The grammar for Norwegian numbers is the same as for English except
1706                 * for the following:
1707                 * - 1 exists in both commune ("en", file "1") and neuter ("ett", file "1N")
1708                 *   "and" before the last two digits, i.e. 2034 is "two thousand and
1709                 *   thirty-four" and 1000012 is "one million and twelve".
1710                 */
1711                 if (num < 0) {
1712                         ast_copy_string(fn, "digits/minus", sizeof(fn));
1713                         if ( num > INT_MIN ) {
1714                                 num = -num;
1715                         } else {
1716                                 num = 0;
1717                         }       
1718                 } else if (playh) {
1719                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
1720                         playh = 0;
1721                 } else if (playa) {
1722                         ast_copy_string(fn, "digits/and", sizeof(fn));
1723                         playa = 0;
1724                 } else if (num == 1 && cn == -1) {
1725                         ast_copy_string(fn, "digits/1N", sizeof(fn));
1726                         num = 0;
1727                 } else if (num < 20) {
1728                         snprintf(fn, sizeof(fn), "digits/%d", num);
1729                         num = 0;
1730                 } else if (num < 100) {
1731                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
1732                         num %= 10;
1733                 } else if (num < 1000) {
1734                         int hundreds = num / 100;
1735                         if (hundreds == 1)
1736                                 ast_copy_string(fn, "digits/1N", sizeof(fn));
1737                         else
1738                                 snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
1739
1740                         playh++;
1741                         num -= 100 * hundreds;
1742                         if (num)
1743                                 playa++;
1744                 } else  if (num < 1000000) {
1745                         res = ast_say_number_full_no(chan, num / 1000, ints, language, "n", audiofd, ctrlfd);
1746                         if (res)
1747                                 return res;
1748                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
1749                         num %= 1000;
1750                         if (num && num < 100)
1751                                 playa++;
1752                 } else  if (num < 1000000000) {
1753                                 int millions = num / 1000000;
1754                                 res = ast_say_number_full_no(chan, millions, ints, language, "c", audiofd, ctrlfd);
1755                                 if (res)
1756                                         return res;
1757                                 ast_copy_string(fn, "digits/million", sizeof(fn));
1758                                 num %= 1000000;
1759                                 if (num && num < 100)
1760                                         playa++;
1761                 } else {
1762                                 ast_debug(1, "Number '%d' is too big for me\n", num);
1763                                 res = -1;
1764                 }
1765                 
1766                 if (!res) {
1767                         if (!ast_streamfile(chan, fn, language)) {
1768                                 if ((audiofd > -1) && (ctrlfd > -1)) 
1769                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1770                                 else  
1771                                         res = ast_waitstream(chan, ints);
1772                         }
1773                         ast_stopstream(chan);
1774                 }
1775         }
1776         return res;
1777 }
1778
1779 typedef struct {  
1780         char *separator_dziesiatek;
1781         char *cyfry[10];
1782         char *cyfry2[10];
1783         char *setki[10];
1784         char *dziesiatki[10];
1785         char *nastki[10];  
1786         char *rzedy[3][3];
1787 } odmiana;
1788
1789 static char *pl_rzad_na_tekst(odmiana *odm, int i, int rzad)
1790 {
1791         if (rzad==0)
1792                 return "";
1793  
1794         if (i==1)
1795                 return odm->rzedy[rzad - 1][0];
1796         if ((i > 21 || i < 11) &&  i%10 > 1 && i%10 < 5)
1797                 return odm->rzedy[rzad - 1][1];
1798         else
1799                 return odm->rzedy[rzad - 1][2];
1800 }
1801
1802 static char* pl_append(char* buffer, char* str)
1803 {
1804         strcpy(buffer, str);
1805         buffer += strlen(str); 
1806         return buffer;
1807 }
1808
1809 static void pl_odtworz_plik(struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, char *fn)
1810 {    
1811         char file_name[255] = "digits/";
1812         strcat(file_name, fn);
1813         ast_debug(1, "Trying to play: %s\n", file_name);
1814         if (!ast_streamfile(chan, file_name, language)) {
1815                 if ((audiofd > -1) && (ctrlfd > -1))
1816                         ast_waitstream_full(chan, ints, audiofd, ctrlfd);
1817                 else
1818                         ast_waitstream(chan, ints);
1819         }
1820         ast_stopstream(chan);
1821 }
1822
1823 static void powiedz(struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, odmiana *odm, int rzad, int i)
1824 {
1825         /* Initialise variables to allow compilation on Debian-stable, etc */
1826         int m1000E6 = 0;
1827         int i1000E6 = 0;
1828         int m1000E3 = 0;
1829         int i1000E3 = 0;
1830         int m1000 = 0;
1831         int i1000 = 0;
1832         int m100 = 0;
1833         int i100 = 0;
1834         
1835         if (i == 0 && rzad > 0) { 
1836                 return;
1837         }
1838         if (i == 0) {
1839                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry[0]);
1840                 return;
1841         }
1842
1843         m1000E6 = i % 1000000000;
1844         i1000E6 = i / 1000000000;
1845
1846         powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+3, i1000E6);
1847
1848         m1000E3 = m1000E6 % 1000000;
1849         i1000E3 = m1000E6 / 1000000;
1850
1851         powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+2, i1000E3);
1852
1853         m1000 = m1000E3 % 1000;
1854         i1000 = m1000E3 / 1000;
1855
1856         powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+1, i1000);
1857
1858         m100 = m1000 % 100;
1859         i100 = m1000 / 100;
1860         
1861         if (i100>0)
1862                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->setki[i100]);
1863
1864         if ( m100 > 0 && m100 <=9 ) {
1865                 if (m1000>0)
1866                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100]);
1867                 else
1868                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry[m100]);
1869         } else if (m100 % 10 == 0) {
1870                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
1871         } else if (m100 <= 19 ) {
1872                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->nastki[m100 % 10]);
1873         } else if (m100 != 0) {
1874                 if (odm->separator_dziesiatek[0]==' ') {
1875                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
1876                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100 % 10]);
1877                 } else {
1878                         char buf[10];
1879                         char *b = buf;
1880                         b = pl_append(b, odm->dziesiatki[m100 / 10]);  
1881                         b = pl_append(b, odm->separator_dziesiatek);  
1882                         b = pl_append(b, odm->cyfry2[m100 % 10]); 
1883                         pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, buf);
1884                 }
1885         } 
1886
1887         if (rzad > 0) {
1888                 pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, pl_rzad_na_tekst(odm, i, rzad));
1889         }
1890 }
1891
1892 /* ast_say_number_full_pl: Polish syntax */
1893 static int ast_say_number_full_pl(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
1894 /*
1895 Sounds needed:
1896 0               zero
1897 1               jeden
1898 10              dziesiec
1899 100             sto
1900 1000            tysiac
1901 1000000         milion
1902 1000000000      miliard
1903 1000000000.2    miliardy
1904 1000000000.5    miliardow
1905 1000000.2       miliony
1906 1000000.5       milionow
1907 1000.2          tysiace
1908 1000.5          tysiecy
1909 100m            stu
1910 10m             dziesieciu
1911 11              jedenascie
1912 11m             jedenastu
1913 12              dwanascie
1914 12m             dwunastu
1915 13              trzynascie
1916 13m             trzynastu
1917 14              czternascie
1918 14m             czternastu
1919 15              pietnascie
1920 15m             pietnastu
1921 16              szesnascie
1922 16m             szesnastu
1923 17              siedemnascie
1924 17m             siedemnastu
1925 18              osiemnascie
1926 18m             osiemnastu
1927 19              dziewietnascie
1928 19m             dziewietnastu
1929 1z              jedna
1930 2               dwa
1931 20              dwadziescia
1932 200             dwiescie
1933 200m            dwustu
1934 20m             dwudziestu
1935 2-1m            dwaj
1936 2-2m            dwoch
1937 2z              dwie
1938 3               trzy
1939 30              trzydziesci
1940 300             trzysta
1941 300m            trzystu
1942 30m             trzydziestu
1943 3-1m            trzej
1944 3-2m            trzech
1945 4               cztery
1946 40              czterdziesci
1947 400             czterysta
1948 400m            czterystu
1949 40m             czterdziestu
1950 4-1m            czterej
1951 4-2m            czterech
1952 5               piec
1953 50              piecdziesiat
1954 500             piecset
1955 500m            pieciuset
1956 50m             piedziesieciu
1957 5m              pieciu
1958 6               szesc
1959 60              szescdziesiat
1960 600             szescset
1961 600m            szesciuset
1962 60m             szescdziesieciu
1963 6m              szesciu
1964 7               siedem
1965 70              siedemdziesiat
1966 700             siedemset
1967 700m            siedmiuset
1968 70m             siedemdziesieciu
1969 7m              siedmiu
1970 8               osiem
1971 80              osiemdziesiat
1972 800             osiemset
1973 800m            osmiuset
1974 80m             osiemdziesieciu
1975 8m              osmiu
1976 9               dziewiec
1977 90              dziewiecdziesiat
1978 900             dziewiecset
1979 900m            dziewieciuset
1980 90m             dziewiedziesieciu
1981 9m              dziewieciu
1982 and combinations of eg.: 20_1, 30m_3m, etc...
1983
1984 */
1985 {
1986         char *zenski_cyfry[] = {"0", "1z", "2z", "3", "4", "5", "6", "7", "8", "9"};
1987
1988         char *zenski_cyfry2[] = {"0", "1", "2z", "3", "4", "5", "6", "7", "8", "9"};
1989
1990         char *meski_cyfry[] = {"0", "1", "2-1m", "3-1m", "4-1m", "5m",  /*"2-1mdwaj"*/ "6m", "7m", "8m", "9m"};
1991
1992         char *meski_cyfry2[] = {"0", "1", "2-2m", "3-2m", "4-2m", "5m", "6m", "7m", "8m", "9m"};
1993
1994         char *meski_setki[] = {"", "100m", "200m", "300m", "400m", "500m", "600m", "700m", "800m", "900m"};
1995
1996         char *meski_dziesiatki[] = {"", "10m", "20m", "30m", "40m", "50m", "60m", "70m", "80m", "90m"};
1997
1998         char *meski_nastki[] = {"", "11m", "12m", "13m", "14m", "15m", "16m", "17m", "18m", "19m"};
1999
2000         char *nijaki_cyfry[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
2001
2002         char *nijaki_cyfry2[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
2003
2004         char *nijaki_setki[] = {"", "100", "200", "300", "400", "500", "600", "700", "800", "900"};
2005
2006         char *nijaki_dziesiatki[] = {"", "10", "20", "30", "40", "50", "60", "70", "80", "90"};
2007
2008         char *nijaki_nastki[] = {"", "11", "12", "13", "14", "15", "16", "17", "18", "19"};
2009
2010         char *rzedy[][3] = { {"1000", "1000.2", "1000.5"}, {"1000000", "1000000.2", "1000000.5"}, {"1000000000", "1000000000.2", "1000000000.5"}}; 
2011
2012         /* Initialise variables to allow compilation on Debian-stable, etc */
2013         odmiana *o;
2014
2015         static odmiana *odmiana_nieosobowa = NULL; 
2016         static odmiana *odmiana_meska = NULL; 
2017         static odmiana *odmiana_zenska = NULL; 
2018
2019         if (odmiana_nieosobowa == NULL) {
2020                 odmiana_nieosobowa = ast_malloc(sizeof(*odmiana_nieosobowa));
2021
2022                 odmiana_nieosobowa->separator_dziesiatek = " ";
2023
2024                 memcpy(odmiana_nieosobowa->cyfry, nijaki_cyfry, sizeof(odmiana_nieosobowa->cyfry));
2025                 memcpy(odmiana_nieosobowa->cyfry2, nijaki_cyfry2, sizeof(odmiana_nieosobowa->cyfry));
2026                 memcpy(odmiana_nieosobowa->setki, nijaki_setki, sizeof(odmiana_nieosobowa->setki));
2027                 memcpy(odmiana_nieosobowa->dziesiatki, nijaki_dziesiatki, sizeof(odmiana_nieosobowa->dziesiatki));
2028                 memcpy(odmiana_nieosobowa->nastki, nijaki_nastki, sizeof(odmiana_nieosobowa->nastki));
2029                 memcpy(odmiana_nieosobowa->rzedy, rzedy, sizeof(odmiana_nieosobowa->rzedy));
2030         }
2031
2032         if (odmiana_zenska == NULL) {
2033                 odmiana_zenska = ast_malloc(sizeof(*odmiana_zenska));
2034
2035                 odmiana_zenska->separator_dziesiatek = " ";
2036
2037                 memcpy(odmiana_zenska->cyfry, zenski_cyfry, sizeof(odmiana_zenska->cyfry));
2038                 memcpy(odmiana_zenska->cyfry2, zenski_cyfry2, sizeof(odmiana_zenska->cyfry));
2039                 memcpy(odmiana_zenska->setki, nijaki_setki, sizeof(odmiana_zenska->setki));
2040                 memcpy(odmiana_zenska->dziesiatki, nijaki_dziesiatki, sizeof(odmiana_zenska->dziesiatki));
2041                 memcpy(odmiana_zenska->nastki, nijaki_nastki, sizeof(odmiana_zenska->nastki));
2042                 memcpy(odmiana_zenska->rzedy, rzedy, sizeof(odmiana_zenska->rzedy));
2043         }
2044
2045         if (odmiana_meska == NULL) {
2046                 odmiana_meska = ast_malloc(sizeof(*odmiana_meska));
2047
2048                 odmiana_meska->separator_dziesiatek = " ";
2049
2050                 memcpy(odmiana_meska->cyfry, meski_cyfry, sizeof(odmiana_meska->cyfry));
2051                 memcpy(odmiana_meska->cyfry2, meski_cyfry2, sizeof(odmiana_meska->cyfry));
2052                 memcpy(odmiana_meska->setki, meski_setki, sizeof(odmiana_meska->setki));
2053                 memcpy(odmiana_meska->dziesiatki, meski_dziesiatki, sizeof(odmiana_meska->dziesiatki));
2054                 memcpy(odmiana_meska->nastki, meski_nastki, sizeof(odmiana_meska->nastki));
2055                 memcpy(odmiana_meska->rzedy, rzedy, sizeof(odmiana_meska->rzedy));
2056         }
2057
2058         if (options) {
2059                 if (strncasecmp(options, "f", 1) == 0)
2060                         o = odmiana_zenska;
2061                 else if (strncasecmp(options, "m", 1) == 0)
2062                         o = odmiana_meska;
2063                 else
2064                         o = odmiana_nieosobowa;
2065         } else
2066                 o = odmiana_nieosobowa;
2067
2068         powiedz(chan, language, audiofd, ctrlfd, ints, o, 0, num);
2069         return 0;
2070 }
2071
2072 /* ast_say_number_full_pt: Portuguese syntax */
2073 /*      Extra sounds needed: */
2074 /*      For feminin all sound files end with F */
2075 /*      100E for 100+ something */
2076 /*      1000000S for plural */
2077 /*      pt-e for 'and' */
2078 static int ast_say_number_full_pt(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2079 {
2080         int res = 0;
2081         int playh = 0;
2082         int mf = 1;                            /* +1 = male; -1 = female */
2083         char fn[256] = "";
2084
2085         if (!num) 
2086                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2087
2088         if (options && !strncasecmp(options, "f", 1))
2089                 mf = -1;
2090
2091         while (!res && num ) {
2092                 if (num < 0) {
2093                         ast_copy_string(fn, "digits/minus", sizeof(fn));
2094                         if ( num > INT_MIN ) {
2095                                 num = -num;
2096                         } else {
2097                                 num = 0;
2098                         }       
2099                 } else if (num < 20) {
2100                         if ((num == 1 || num == 2) && (mf < 0))
2101                                 snprintf(fn, sizeof(fn), "digits/%dF", num);
2102                         else
2103                                 snprintf(fn, sizeof(fn), "digits/%d", num);
2104                         num = 0;
2105                 } else if (num < 100) {
2106                         snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
2107                         if (num % 10)
2108                                 playh = 1;
2109                         num = num % 10;
2110                 } else if (num < 1000) {
2111                         if (num == 100)
2112                                 ast_copy_string(fn, "digits/100", sizeof(fn));
2113                         else if (num < 200)
2114                                 ast_copy_string(fn, "digits/100E", sizeof(fn));
2115                         else {
2116                                 if (mf < 0 && num > 199)
2117                                         snprintf(fn, sizeof(fn), "digits/%dF", (num / 100) * 100);
2118                                 else
2119                                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100) * 100);
2120                                 if (num % 100)
2121                                         playh = 1;
2122                         }
2123                         num = num % 100;
2124                 } else if (num < 1000000) {
2125                         if (num > 1999) {
2126                                 res = ast_say_number_full_pt(chan, (num / 1000) * mf, ints, language, options, audiofd, ctrlfd);
2127                                 if (res)
2128                                         return res;
2129                         }
2130                         ast_copy_string(fn, "digits/1000", sizeof(fn));
2131                         if ((num % 1000) && ((num % 1000) < 100  || !(num % 100)))
2132                                 playh = 1;
2133                         num = num % 1000;
2134                 } else if (num < 1000000000) {
2135                         res = ast_say_number_full_pt(chan, (num / 1000000), ints, language, options, audiofd, ctrlfd );
2136                         if (res)
2137                                 return res;
2138                         if (num < 2000000)
2139                                 ast_copy_string(fn, "digits/1000000", sizeof(fn));
2140                         else
2141                                 ast_copy_string(fn, "digits/1000000S", sizeof(fn));
2142  
2143                         if ((num % 1000000) &&
2144                                 /* no thousands */
2145                                 ((!((num / 1000) % 1000) && ((num % 1000) < 100 || !(num % 100))) ||
2146                                 /* no hundreds and below */
2147                                 (!(num % 1000) && (((num / 1000) % 1000) < 100 || !((num / 1000) % 100))) ) )
2148                                 playh = 1;
2149                         num = num % 1000000;
2150                 } else {
2151                         /* number is too big */
2152                         ast_log(LOG_WARNING, "Number '%d' is too big to say.", num);
2153                         res = -1;
2154                 }
2155                 if (!res) {
2156                         if (!ast_streamfile(chan, fn, language)) {
2157                                 if ((audiofd > -1) && (ctrlfd > -1))
2158                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); 
2159                                 else
2160                                         res = ast_waitstream(chan, ints);
2161                         }
2162                         ast_stopstream(chan);
2163                 }
2164                 if (!res && playh) {
2165                         res = wait_file(chan, ints, "digits/pt-e", language);
2166                         ast_stopstream(chan);
2167                         playh = 0;
2168                 }
2169         }
2170         return res;
2171 }
2172
2173 /*! \brief  ast_say_number_full_se: Swedish syntax */
2174 static int ast_say_number_full_se(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2175 {
2176         int res = 0;
2177         int playh = 0;
2178         char fn[256] = "";
2179         int cn = 1;             /* +1 = commune; -1 = neuter */
2180         if (!num) 
2181                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2182         if (options && !strncasecmp(options, "n", 1)) cn = -1;
2183
2184         while (!res && (num || playh)) {
2185                 if (num < 0) {
2186                         ast_copy_string(fn, "digits/minus", sizeof(fn));
2187                         if ( num > INT_MIN ) {
2188                                 num = -num;
2189                         } else {
2190                                 num = 0;
2191                         }       
2192                 } else if (playh) {
2193                         ast_copy_string(fn, "digits/hundred", sizeof(fn));
2194                         playh = 0;
2195                 } else if (num < 20) {
2196                         snprintf(fn, sizeof(fn), "digits/%d", num);
2197                         num = 0;
2198                 } else if (num < 100) {
2199                         snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
2200                         num %= 10;
2201                 } else if (num == 1 && cn == -1) {      /* En eller ett? */
2202                         ast_copy_string(fn, "digits/1N", sizeof(fn));
2203                         num = 0;
2204                 } else {
2205                         if (num < 1000){
2206                                 snprintf(fn, sizeof(fn), "digits/%d", (num/100));
2207                                 playh++;
2208                                 num %= 100;
2209                         } else {
2210                                 if (num < 1000000) { /* 1,000,000 */
2211                                         res = ast_say_number_full_se(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
2212                                         if (res) {
2213                                                 return res;
2214                                         }
2215                                         num %= 1000;
2216                                         ast_copy_string(fn, "digits/thousand", sizeof(fn));
2217                                 } else {
2218                                         if (num < 1000000000) { /* 1,000,000,000 */
2219                                                 res = ast_say_number_full_se(chan, num / 1000000, ints, language, options, audiofd, ctrlfd);
2220                                                 if (res) {
2221                                                         return res;
2222                                                 }
2223                                                 num %= 1000000;
2224                                                 ast_copy_string(fn, "digits/million", sizeof(fn));
2225                                         } else {
2226                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
2227                                                 res = -1;
2228                                         }
2229                                 }
2230                         }
2231                 }
2232                 if (!res) {
2233                         if (!ast_streamfile(chan, fn, language)) {
2234                                 if ((audiofd > -1) && (ctrlfd > -1))
2235                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2236                                 else
2237                                         res = ast_waitstream(chan, ints);
2238                                 ast_stopstream(chan);
2239                         }
2240                 }
2241         }
2242         return res;
2243 }
2244
2245 /*! \brief  ast_say_number_full_zh: Taiwanese / Chinese syntax */
2246 static int ast_say_number_full_zh(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2247 {
2248         int res = 0;
2249         int playh = 0;
2250         int playt = 0;
2251         int playz = 0;
2252         int last_length = 0;
2253         char buf[20] = "";
2254         char fn[256] = "";
2255         if (!num)
2256                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2257
2258         while (!res && (num || playh || playt || playz)) {
2259                         if (num < 0) {
2260                                 ast_copy_string(fn, "digits/minus", sizeof(fn));
2261                                 if ( num > INT_MIN ) {
2262                                         num = -num;
2263                                 } else {
2264                                         num = 0;
2265                                 }       
2266                         } else if (playz) {
2267                                 snprintf(fn, sizeof(fn), "digits/0");
2268                                 last_length = 0;
2269                                 playz = 0;
2270                         } else if (playh) {
2271                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
2272                                 playh = 0;
2273                         } else if (playt) {
2274                                 snprintf(fn, sizeof(fn), "digits/thousand");
2275                                 playt = 0;
2276                         } else  if (num < 10) {
2277                                 snprintf(buf, 10, "%d", num);
2278                                 if (last_length - strlen(buf) > 1 && last_length != 0) {
2279                                         last_length = strlen(buf);
2280                                         playz++;
2281                                         continue;
2282                                 }
2283                                 if (strcasecmp(language,"twz") == 0)
2284                                         snprintf(fn, sizeof(fn), "digits/%d", num);
2285                                 else
2286                                         snprintf(fn, sizeof(fn), "digits/%d", num);
2287                                 num = 0;
2288                         } else  if (num < 100) {
2289                                 snprintf(buf, 10, "%d", num);
2290                                 if (last_length - strlen(buf) > 1 && last_length != 0) {
2291                                         last_length = strlen(buf);
2292                                         playz++;
2293                                         continue;
2294                                 }
2295                                 last_length = strlen(buf);
2296                                 snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
2297                                 num %= 10;
2298                         } else {
2299                                 if (num < 1000){
2300                                         snprintf(buf, 10, "%d", num);
2301                                         if (last_length - strlen(buf) > 1 && last_length != 0) {
2302                                                 last_length = strlen(buf);
2303                                                 playz++;
2304                                                 continue;
2305                                         }
2306                                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
2307                                         playh++;
2308                                         snprintf(buf, 10, "%d", num);
2309                                         ast_log(LOG_DEBUG, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2310                                         last_length = strlen(buf);
2311                                         num -= ((num / 100) * 100);
2312                                 } else if (num < 10000){
2313                                         snprintf(buf, 10, "%d", num);
2314                                         snprintf(fn, sizeof(fn), "digits/%d", (num / 1000));
2315                                         playt++;
2316                                         snprintf(buf, 10, "%d", num);
2317                                         ast_log(LOG_DEBUG, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2318                                         last_length = strlen(buf);
2319                                         num -= ((num / 1000) * 1000);
2320                                 } else if (num < 100000000) { /* 100,000,000 */
2321                                                 res = ast_say_number_full_zh(chan, num / 10000, ints, language, audiofd, ctrlfd);
2322                                                 if (res)
2323                                                         return res;
2324                                                 snprintf(buf, 10, "%d", num);
2325                                                 ast_log(LOG_DEBUG, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2326                                                 num -= ((num / 10000) * 10000);
2327                                                 last_length = strlen(buf);
2328                                                 snprintf(fn, sizeof(fn), "digits/wan");
2329                                 } else {
2330                                         if (num < 1000000000) { /* 1,000,000,000 */
2331                                                 res = ast_say_number_full_zh(chan, num / 100000000, ints, language, audiofd, ctrlfd);
2332                                                 if (res)
2333                                                         return res;
2334                                                 snprintf(buf, 10, "%d", num);
2335                                                 ast_log(LOG_DEBUG, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
2336                                                 last_length = strlen(buf);
2337                                                 num -= ((num / 100000000) * 100000000);
2338                                                 snprintf(fn, sizeof(fn), "digits/yi");
2339                                         } else {
2340                                                 ast_debug(1, "Number '%d' is too big for me\n", num);
2341                                                 res = -1;
2342                                         }
2343                                 }
2344                         }
2345                         if (!res) {
2346                                 if (!ast_streamfile(chan, fn, language)) {
2347                                         if ((audiofd > -1) && (ctrlfd > -1))
2348                                                 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2349                                         else
2350                                                 res = ast_waitstream(chan, ints);
2351                                 }
2352                                 ast_stopstream(chan);
2353                         }
2354         }
2355         return res;
2356 }
2357
2358 /*!\internal
2359  * \brief Counting in Urdu, the national language of Pakistan
2360  * \since 1.6.3
2361  */
2362 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)
2363 {
2364         int res = 0;
2365         int playh = 0;
2366         char fn[256] = "";
2367
2368         if (!num) {
2369                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2370         }
2371
2372         while (!res && (num || playh)) {
2373                 if (playh) {
2374                         snprintf(fn, sizeof(fn), "digits/hundred");
2375                         playh = 0;
2376                 } else if (num < 100) {
2377                         snprintf(fn, sizeof(fn), "digits/%d", num);
2378                         num = 0;
2379                 } else if (num < 1000) {
2380                         snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
2381                         playh++;
2382                         num -= ((num / 100) * 100);
2383                 } else if (num < 100000) { /* 1,00,000 */
2384                         if ((res = ast_say_number_full_ur(chan, num / 1000, ints, language, options, audiofd, ctrlfd))) {
2385                                 return res;
2386                         }
2387                         num = num % 1000;
2388                         snprintf(fn, sizeof(fn), "digits/thousand");
2389                 } else if (num < 10000000) { /* 1,00,00,000 */
2390                         if ((res = ast_say_number_full_ur(chan, num / 100000, ints, language, options, audiofd, ctrlfd))) {
2391                                 return res;
2392                         }
2393                         num = num % 100000;
2394                         snprintf(fn, sizeof(fn), "digits/lac");
2395                 } else if (num < 1000000000) { /* 1,00,00,00,000 */
2396                         if ((res = ast_say_number_full_ur(chan, num / 10000000, ints, language, options, audiofd, ctrlfd))) {
2397                                 return res;
2398                         }
2399                         num = num % 10000000;
2400                         snprintf(fn, sizeof(fn), "digits/crore");
2401                 } else {
2402                         ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
2403                         res = -1;
2404                 }
2405
2406                 if (!res) {
2407                         if (!ast_streamfile(chan, fn, language)) {
2408                                 if ((audiofd > -1) && (ctrlfd > -1)) {
2409                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2410                                 } else {
2411                                         res = ast_waitstream(chan, ints);
2412                                 }
2413                         }
2414                         ast_stopstream(chan);
2415                 }
2416         }
2417         return res;
2418 }
2419
2420 /*! \brief  determine last digits for thousands/millions (ru) */
2421 static int get_lastdigits_ru(int num) {
2422         if (num < 20) {
2423                 return num;
2424         } else if (num < 100) {
2425                 return get_lastdigits_ru(num % 10);
2426         } else if (num < 1000) {
2427                 return get_lastdigits_ru(num % 100);
2428         }
2429         return 0;       /* number too big */
2430 }
2431
2432
2433 /*! \brief  ast_say_number_full_ru: Russian syntax */
2434 /*! \brief  additional files:
2435         n00.gsm                 (one hundred, two hundred, ...)
2436         thousand.gsm
2437         million.gsm
2438         thousands-i.gsm         (tisyachi)
2439         million-a.gsm           (milliona)
2440         thousands.gsm
2441         millions.gsm
2442         1f.gsm                  (odna)
2443         2f.gsm                  (dve)
2444
2445         where 'n' from 1 to 9
2446 */
2447 static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2448 {
2449         int res = 0;
2450         int lastdigits = 0;
2451         char fn[256] = "";
2452         if (!num) 
2453                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2454
2455         while (!res && (num)) {
2456                 if (num < 0) {
2457                         ast_copy_string(fn, "digits/minus", sizeof(fn));
2458                         if ( num > INT_MIN ) {
2459                                 num = -num;
2460                         } else {
2461                                 num = 0;
2462                         }       
2463                 } else  if (num < 20) {
2464                         if (options && strlen(options) == 1 && num < 3) {
2465                             snprintf(fn, sizeof(fn), "digits/%d%s", num, options);
2466                         } else {
2467                                 snprintf(fn, sizeof(fn), "digits/%d", num);
2468                         }
2469                         num = 0;
2470                 } else if (num < 100) {
2471                         snprintf(fn, sizeof(fn), "digits/%d", num - (num % 10));
2472                         num %= 10;
2473                 } else if (num < 1000){
2474                         snprintf(fn, sizeof(fn), "digits/%d", num - (num % 100));
2475                         num %= 100;
2476                 } else if (num < 1000000) { /* 1,000,000 */
2477                         lastdigits = get_lastdigits_ru(num / 1000);
2478                         /* say thousands */
2479                         if (lastdigits < 3) {
2480                                 res = ast_say_number_full_ru(chan, num / 1000, ints, language, "f", audiofd, ctrlfd);
2481                         } else {
2482                                 res = ast_say_number_full_ru(chan, num / 1000, ints, language, NULL, audiofd, ctrlfd);
2483                         }
2484                         if (res)
2485                                 return res;
2486                         if (lastdigits == 1) {
2487                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
2488                         } else if (lastdigits > 1 && lastdigits < 5) {
2489                                 ast_copy_string(fn, "digits/thousands-i", sizeof(fn));
2490                         } else {
2491                                 ast_copy_string(fn, "digits/thousands", sizeof(fn));
2492                         }
2493                         num %= 1000;
2494                 } else  if (num < 1000000000) { /* 1,000,000,000 */
2495                         lastdigits = get_lastdigits_ru(num / 1000000);
2496                         /* say millions */
2497                         res = ast_say_number_full_ru(chan, num / 1000000, ints, language, NULL, audiofd, ctrlfd);
2498                         if (res)
2499                                 return res;
2500                         if (lastdigits == 1) {
2501                                 ast_copy_string(fn, "digits/million", sizeof(fn));
2502                         } else if (lastdigits > 1 && lastdigits < 5) {
2503                                 ast_copy_string(fn, "digits/million-a", sizeof(fn));
2504                         } else {
2505                                 ast_copy_string(fn, "digits/millions", sizeof(fn));
2506                         }
2507                         num %= 1000000;
2508                 } else {
2509                         ast_debug(1, "Number '%d' is too big for me\n", num);
2510                         res = -1;
2511                 }
2512                 if (!res) {
2513                         if (!ast_streamfile(chan, fn, language)) {
2514                                 if ((audiofd  > -1) && (ctrlfd > -1))
2515                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2516                                 else
2517                                         res = ast_waitstream(chan, ints);
2518                         }
2519                         ast_stopstream(chan);
2520                 }
2521         }
2522         return res;
2523 }
2524
2525 static int ast_say_number_full_th(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2526 {
2527         int res = 0;
2528         int playh = 0;
2529         char fn[256] = "";
2530         if (!num) 
2531                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2532
2533         while(!res && (num || playh)) {
2534                 if (num < 0) {
2535                         ast_copy_string(fn, "digits/lop", sizeof(fn));
2536                         if ( num > INT_MIN ) {
2537                                 num = -num;
2538                         } else {
2539                                 num = 0;
2540                         }       
2541                 } else if (playh) {
2542                         ast_copy_string(fn, "digits/roi", sizeof(fn));
2543                         playh = 0;
2544                 } else if (num < 100) {
2545                         if ((num <= 20) || ((num % 10) == 1)) {
2546                                 snprintf(fn, sizeof(fn), "digits/%d", num);
2547                                 num = 0;
2548                         } else {
2549                                 snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
2550                                 num %= 10;
2551                         }
2552                 } else if (num < 1000) {
2553                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
2554                         playh++;
2555                         num %= 100;
2556                 } else if (num < 10000) { /* 10,000 */
2557                         res = ast_say_number_full_th(chan, num / 1000, ints, language, audiofd, ctrlfd);
2558                         if (res)
2559                                 return res;
2560                         num %= 1000;
2561                         ast_copy_string(fn, "digits/pan", sizeof(fn));
2562                 } else if (num < 100000) { /* 100,000 */
2563                         res = ast_say_number_full_th(chan, num / 10000, ints, language, audiofd, ctrlfd);
2564                         if (res)
2565                                 return res;
2566                         num %= 10000;
2567                         ast_copy_string(fn, "digits/muan", sizeof(fn));
2568                 } else if (num < 1000000) { /* 1,000,000 */
2569                         res = ast_say_number_full_th(chan, num / 100000, ints, language, audiofd, ctrlfd);
2570                         if (res)
2571                                 return res;
2572                         num %= 100000;
2573                         ast_copy_string(fn, "digits/san", sizeof(fn));
2574                 } else {
2575                         res = ast_say_number_full_th(chan, num / 1000000, ints, language, audiofd, ctrlfd);
2576                         if (res)
2577                                 return res;
2578                         num %= 1000000;
2579                         ast_copy_string(fn, "digits/larn", sizeof(fn));
2580                 }
2581                 if (!res) {
2582                         if(!ast_streamfile(chan, fn, language)) {
2583                                 if ((audiofd  > -1) && (ctrlfd > -1))
2584                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2585                                 else
2586                                         res = ast_waitstream(chan, ints);
2587                         }
2588                         ast_stopstream(chan);
2589                 }
2590         }
2591         return res;
2592 }
2593
2594 /*! \brief  ast_say_enumeration_full: call language-specific functions */
2595 /* Called from AGI */
2596 static int say_enumeration_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
2597 {
2598         if (!strcasecmp(language, "en") ) {     /* English syntax */
2599            return(ast_say_enumeration_full_en(chan, num, ints, language, audiofd, ctrlfd));
2600         } else if (!strcasecmp(language, "da") ) {      /* Danish syntax */
2601            return(ast_say_enumeration_full_da(chan, num, ints, language, options, audiofd, ctrlfd));
2602         } else if (!strcasecmp(language, "de") ) {      /* German syntax */
2603            return(ast_say_enumeration_full_de(chan, num, ints, language, options, audiofd, ctrlfd));
2604         } else if (!strcasecmp(language, "he")) {       /* Hebrew syntax */
2605                 return (ast_say_enumeration_full_he(chan, num, ints, language, options, audiofd, ctrlfd));
2606         } 
2607         
2608         /* Default to english */
2609         return(ast_say_enumeration_full_en(chan, num, ints, language, audiofd, ctrlfd));
2610 }
2611
2612 /*! \brief  ast_say_enumeration_full_en: English syntax */
2613 /* This is the default syntax, if no other syntax defined in this file is used */
2614 static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
2615 {
2616         int res = 0, t = 0;
2617         char fn[256] = "";
2618         
2619         while (!res && num) {
2620                 if (num < 0) {
2621                         ast_copy_string(fn, "digits/minus", sizeof(fn)); /* kind of senseless for enumerations, but our best effort for error checking */
2622                         if ( num > INT_MIN ) {
2623                                 num = -num;
2624                         } else {
2625                                 num = 0;
2626                         }       
2627                 } else if (num < 20) {
2628                         snprintf(fn, sizeof(fn), "digits/h-%d", num);
2629                         num = 0;
2630                 } else if (num < 100) { 
2631                         int tens = num / 10;
2632                         num = num % 10;
2633                         if (num == 0) {
2634                                 snprintf(fn, sizeof(fn), "digits/h-%d", (tens * 10));
2635                         } else {
2636                                 snprintf(fn, sizeof(fn), "digits/%d", (tens * 10));
2637                         }
2638                 } else if (num < 1000) {
2639                         int hundreds = num / 100;
2640                         num = num % 100;
2641                         if (hundreds > 1 || t == 1) {
2642                                 res = ast_say_number_full_en(chan, hundreds, ints, language, audiofd, ctrlfd);
2643                         }                       
2644                         if (res)
2645                                 return res;
2646                         if (num) {
2647                                 ast_copy_string(fn, "digits/hundred", sizeof(fn));
2648                         } else {
2649                                 ast_copy_string(fn, "digits/h-hundred", sizeof(fn));
2650                         }
2651                 } else if (num < 1000000) {
2652                         int thousands = num / 1000;
2653                         num = num % 1000;
2654                         if (thousands > 1 || t == 1) {
2655                                 res = ast_say_number_full_en(chan, thousands, ints, language, audiofd, ctrlfd);
2656                         }
2657                         if (res)
2658                                 return res;
2659                         if (num) {                                      
2660                                 ast_copy_string(fn, "digits/thousand", sizeof(fn));
2661                         } else {
2662                                 ast_copy_string(fn, "digits/h-thousand", sizeof(fn));
2663                         }
2664                         t = 1;
2665                 } else if (num < 1000000000) {
2666                         int millions = num / 1000000;
2667                         num = num % 1000000;
2668                         t = 1;
2669                         res = ast_say_number_full_en(chan, millions, ints, language, audiofd, ctrlfd);
2670                         if (res)
2671                                 return res;
2672                         if (num) {                                      
2673                                 ast_copy_string(fn, "digits/million", sizeof(fn));
2674                         } else {
2675                                 ast_copy_string(fn, "digits/h-million", sizeof(fn));
2676                         }
2677                 } else if (num < INT_MAX) {
2678                         int billions = num / 1000000000;
2679                         num = num % 1000000000;
2680                         t = 1;
2681                         res = ast_say_number_full_en(chan, billions, ints, language, audiofd, ctrlfd);
2682                         if (res)
2683                                 return res;
2684                         if (num) {                                      
2685                                 ast_copy_string(fn, "digits/billion", sizeof(fn));
2686                         } else {
2687                                 ast_copy_string(fn, "digits/h-billion", sizeof(fn));
2688                         }
2689                 } else if (num == INT_MAX) {
2690                         ast_copy_string(fn, "digits/h-last", sizeof(fn));
2691                         num = 0;
2692                 } else {
2693                         ast_debug(1, "Number '%d' is too big for me\n", num);
2694                         res = -1;
2695                 }
2696
2697                 if (!res) {
2698                         if (!ast_streamfile(chan, fn, language)) {
2699                                 if ((audiofd > -1) && (ctrlfd > -1)) {
2700                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
2701                                 } else {
2702                                         res = ast_waitstream(chan, ints);
2703                                 }
2704                         }
2705                         ast_stopstream(chan);
2706                 }
2707         }
2708         return res;
2709 }
2710
2711 /*! \brief  ast_say_enumeration_full_da: Danish syntax */
2712 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)
2713 {
2714         /* options can be: '' or 'm' male gender; 'f' female gender; 'n' neuter gender; 'p' plural */
2715         int res = 0, t = 0;
2716         char fn[256] = "", fna[256] = "";
2717         char *gender;
2718
2719         if (options && !strncasecmp(options, "f", 1)) {
2720                 gender = "F";
2721         } else if (options && !strncasecmp(options, "n", 1)) {
2722                 gender = "N";
2723         } else {
2724                 gender = "";
2725         }
2726
2727         if (!num) 
2728                 return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
2729
2730         while (!res && num) {
2731                 if (num < 0) {
2732                         ast_copy_string(fn, "digits/minus", sizeof(fn)); /* kind of senseless for enumerations, but our best effort for error checking */
2733                         if ( num > INT_MIN ) {
2734                                 num = -num;
2735                         } else {
2736                                 num = 0;
2737                         }       
2738                 } else if (num < 100 && t) {
2739                         ast_copy_string(fn, "digits/and", sizeof(fn));
2740                         t = 0;
2741                 } else if (num < 20) {
2742                         snprintf(fn, sizeof(fn), "digits/h-%d%s", num, gender);
2743                         num = 0;
2744                 } else if (num < 100) {
2745                         int ones = num % 10;
2746                         if (ones) {
2747                                 snprintf(fn, sizeof(fn), "digits/%d-and", ones);
2748                                 num -= ones;
2749                         } else {
2750                                 snprintf(fn, sizeof(fn), "digits/h-%d%s", num, gender);
2751                                 num = 0;
2752                         }
2753                 } else if (num == 100 && t == 0) {
2754                         snprintf(fn, sizeof(fn), "digits/h-hundred%s", gender);
2755