aboutsummaryrefslogtreecommitdiffstats
path: root/main/say.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/say.c')
-rw-r--r--main/say.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/main/say.c b/main/say.c
index 67b791ba4..32cef2954 100644
--- a/main/say.c
+++ b/main/say.c
@@ -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);
+}
+
/*