Merged revisions 168828 via svnmerge from
[asterisk/asterisk.git] / main / say.c
index 07fd1cc..943ccaf 100644 (file)
@@ -50,6 +50,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/lock.h"
 #include "asterisk/localtime.h"
 #include "asterisk/utils.h"
+#include "asterisk/app.h"
 
 /* Forward declaration */
 static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang);
@@ -7754,6 +7755,114 @@ static int ast_say_datetime_from_now_ge(struct ast_channel *chan, time_t t, cons
        return res;
 }
 
+/* In English, we use the plural for everything but one. For example:
+ *  1 degree
+ *  2 degrees
+ *  5 degrees
+ * The filename for the plural form is generated by appending "s". Note that
+ * purpose is to generate a unique filename, not to implement irregular 
+ * declensions. Thus:
+ *  1 man
+ *  2 mans (the "mans" soundfile will of course say "men")
+ */
+static const char *counted_noun_ending_en(int num)
+{
+       if (num == 1 || num == -1) {
+               return "";
+       } else {
+               return "s";
+       }
+}
+
+/* Counting of objects in slavic languages such as Russian and Ukrainian the
+ * rules are more complicated. There are two plural forms used in counting.
+ * They are the genative singular which we represent with the suffix "x1" and 
+ * the genative plural which we represent with the suffix "x2". The base names
+ * of the soundfiles remain in English. For example:
+ *  1 degree (soudfile says "gradus")
+ *  2 degreex1 (soundfile says "gradusa")
+ *  5 degreex2 (soundfile says "gradusov")
+ */
+static const char *counted_noun_ending_slavic(int num)
+{
+       if (num < 0) {
+           num *= -1;
+       }
+       num %= 100;                     /* never pay attention to more than two digits */
+       if (num >= 20) {                /* for numbers 20 and above, pay attention to only last digit */
+           num %= 10;
+       }
+       if (num == 1) {                 /* singular */
+           return "";
+       }
+       if (num > 0 && num < 5) {       /* 2--5 get genative singular */
+           return "x1";
+       } else {                        /* 5--19 get genative plural */
+           return "x2";
+       }
+}
+
+int ast_say_counted_noun(struct ast_channel *chan, int num, const char noun[])
+{
+       char *temp;
+       int temp_len;
+       const char *ending;
+       if (!strcasecmp(chan->language, "ru")) {                /* Russian */
+               ending = counted_noun_ending_slavic(num);
+       } else if(!strcasecmp(chan->language, "ua")) {          /* Ukrainian */
+               ending = counted_noun_ending_slavic(num);
+       } else if(!strcasecmp(chan->language, "ua")) {          /* Polish */
+               ending = counted_noun_ending_slavic(num);
+       } else {                                                /* English and default */
+               ending = counted_noun_ending_en(num);
+       }
+       temp = alloca((temp_len = (strlen(noun) + strlen(ending) + 1)));
+       snprintf(temp, temp_len, "%s%s", noun, ending);
+       return ast_play_and_wait(chan, temp);
+}
+
+/*
+ * In slavic languages such as Russian and Ukrainian the rules for declining
+ * adjectives are simpler than those for nouns.  When counting we use only
+ * the singular (to which we give no suffix) and the genative plural (which
+ * we represent by adding an "x").  Oh, an in the singular gender matters
+ * so we append the supplied gender suffix ("m", "f", "n").
+ */
+static const char *counted_adjective_ending_ru(int num, const char gender[])
+{
+       if (num < 0) {
+           num *= -1;
+       }
+       num %= 100;             /* never pay attention to more than two digits */
+       if (num >= 20) {        /* at 20 and beyond only the last digit matters */
+           num %= 10;
+       }
+       if (num == 1) {
+           return gender ? gender : "";
+       } else {                /* all other numbers get the genative plural */
+           return "x";
+       }
+}
+
+int ast_say_counted_adjective(struct ast_channel *chan, int num, const char adjective[], const char gender[])
+{
+       char *temp;
+       int temp_len;
+       const char *ending;
+       if (!strcasecmp(chan->language, "ru")) {                        /* Russian */
+               ending = counted_adjective_ending_ru(num, gender);
+       } else if (!strcasecmp(chan->language, "ua")) {                 /* Ukrainian */
+               ending = counted_adjective_ending_ru(num, gender);
+       } else if (!strcasecmp(chan->language, "pl")) {                 /* Polish */
+               ending = counted_adjective_ending_ru(num, gender);
+       } else {                                                        /* English and default */
+               ending = "";
+       }
+       temp = alloca((temp_len = (strlen(adjective) + strlen(ending) + 1)));
+       snprintf(temp, temp_len, "%s%s", adjective, ending);
+       return ast_play_and_wait(chan, temp);
+}
+
 
 
 /*