clean db
[platform/upstream/ibus-libpinyin.git] / src / PYDynamicSpecialPhrase.cc
1 /* vim:set et ts=4 sts=4:
2  *
3  * ibus-pinyin - The Chinese PinYin engine for IBus
4  *
5  * Copyright (c) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 #include "PYDynamicSpecialPhrase.h"
22
23 namespace PY {
24
25 DynamicSpecialPhrase::~DynamicSpecialPhrase (void)
26 {
27 }
28
29 std::string
30 DynamicSpecialPhrase::text (void)
31 {
32     /* get the current time */
33     std::time_t rawtime;
34     std::time (&rawtime);
35     m_time = *std::localtime (&rawtime);
36
37     std::string result;
38
39     size_t pos = 0;
40     size_t pnext;
41     gint s = 0;
42     while (s != 2) {
43         switch (s) {
44         case 0: // expect "${"
45             pnext = m_text.find ("${", pos);
46             if (pnext == m_text.npos) {
47                 result += m_text.substr (pos);
48                 s = 2;
49             }
50             else {
51                 result += m_text.substr (pos, pnext - pos);
52                 pos = pnext + 2;
53                 s = 1;
54             }
55             break;
56         case 1: // expect "}"
57             pnext = m_text.find ("}", pos);
58             if (pnext == m_text.npos) {
59                 result += "${";
60                 result += m_text.substr (pos);
61                 s = 2;
62             }
63             else {
64                 result += variable (m_text.substr(pos, pnext - pos));
65                 pos = pnext + 1;
66                 s = 0;
67             }
68             break;
69         default: /* should not be reached */
70             g_assert_not_reached ();
71         }
72     }
73     return result;
74 }
75
76 inline const std::string
77 DynamicSpecialPhrase::dec (gint d, const gchar *fmt)
78 {
79     gchar string [32];
80     g_snprintf (string, sizeof (string), fmt, d);
81     return string;
82 }
83
84 inline const std::string
85 DynamicSpecialPhrase::year_cn (gboolean yy)
86 {
87     static const gchar * const digits[] = {
88         "〇", "一", "二", "三", "四",
89         "五", "六", "七", "八", "九"
90     };
91
92     gint year = m_time.tm_year + 1900;
93     gint bit = 0;
94     if (yy) {
95         year %= 100;
96         bit = 2;
97     }
98
99     std::string result;
100     while (year != 0 || bit > 0) {
101         result.insert(0, digits[year % 10]);
102         year /= 10;
103         bit -= 1;
104     }
105     return result;
106 }
107
108 inline const std::string
109 DynamicSpecialPhrase::month_cn (void)
110 {
111     static const gchar * const month_num[] = {
112         "一", "二", "三", "四", "五", "六", "七", "八",
113         "九", "十", "十一", "十二"
114     };
115     return month_num[m_time.tm_mon];
116 }
117
118 inline const std::string
119 DynamicSpecialPhrase::weekday_cn (void)
120 {
121     static const gchar * const week_num[] = {
122         "日", "一", "二", "三", "四", "五", "六"
123     };
124     return week_num[m_time.tm_wday];
125 }
126
127 inline const std::string
128 DynamicSpecialPhrase::hour_cn (guint i)
129 {
130     static const gchar * const hour_num[] = {
131         "零", "一", "二", "三", "四",
132         "五", "六", "七", "八", "九",
133         "十", "十一", "十二", "十三", "十四",
134         "十五", "十六", "十七", "十八", "十九",
135         "二十", "二十一", "二十二", "二十三",
136     };
137     return hour_num[i];
138 }
139
140 inline const std::string
141 DynamicSpecialPhrase::fullhour_cn (void)
142 {
143     return hour_cn (m_time.tm_hour);
144 }
145
146 inline const std::string
147 DynamicSpecialPhrase::halfhour_cn (void)
148 {
149     return hour_cn (m_time.tm_hour % 12);
150 }
151
152 inline const std::string
153 DynamicSpecialPhrase::day_cn (void)
154 {
155     static const gchar * const day_num[] = {
156         "", "一", "二", "三", "四",
157         "五", "六", "七", "八", "九",
158         "", "十","二十", "三十"
159     };
160     guint day = m_time.tm_mday;
161     return std::string (day_num[day / 10 + 10]) + day_num[day % 10];
162 }
163
164 inline const std::string
165 DynamicSpecialPhrase::minsec_cn (guint i)
166 {
167     static const gchar * const num[] = {
168         "", "一", "二", "三", "四",
169         "五", "六", "七", "八", "九",
170         "零", "十","二十", "三十", "四十"
171         "五十", "六十"
172     };
173     return std::string (num[i / 10 + 10]) + num[i % 10];
174 }
175
176 static const char * numbers [2][10] = {
177     {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖",},
178     {"〇", "一", "二", "三", "四", "五", "六", "七", "八", "九",},
179 };
180
181 struct unit_t{
182     const char * unit_zh_name;  // Chinese Character
183     const int digits;           // Position in string.
184     const bool persist;         // Whether to force eating zero and force inserting into result string.
185 };
186
187 static unit_t units_simplified[] ={
188     {"兆", 12, true},
189     {"亿", 8, true},
190     {"万", 4, true},
191     {"千", 3, false},
192     {"百", 2, false},
193     {"十", 1, false},
194     {"",   0, true},
195 };
196
197 static unit_t units_traditional[] ={
198     {"兆", 12, true},
199     {"亿", 8, true},
200     {"万", 4, true},
201     {"仟", 3, false},
202     {"佰", 2, false},
203     {"拾", 1, false},
204     {"",   0, true},
205 };
206
207
208 const std::string
209 DynamicSpecialPhrase::simplest_cn_number(gint64 num)
210 {
211     std::string result = "";
212     if ( num == 0 )
213         result = numbers[1][0];
214     while (num > 0) {
215         int remains = num % 10;
216         num = num / 10;
217         result = std::string ( numbers[1][remains] ) + result;
218     }
219
220     return result;
221 }
222
223 static inline const std::string
224 translate_to_longform(gint64 num, const char * number[10], unit_t units[])
225 {
226     std::string result = "";
227     int cur_pos = -1;
228     bool eat_zero = false;
229
230     while (num > 0) {
231         int remains = num % 10;
232         num = num / 10;
233         cur_pos ++;
234         std::string unit = "";
235         int pos = cur_pos;
236         size_t i = 6;
237         while ( pos > 0 ) {
238             for ( i = 0; i < 7; ++i) {
239                 pos = pos % units[i].digits;
240                 if ( pos == 0 )
241                     break;
242             }
243         }
244
245         if ( units[i].persist ) {
246             result = std::string (units[i].unit_zh_name) + result;
247             eat_zero = true;
248         }
249
250         if ( remains == 0){
251             if ( eat_zero ) continue;
252
253             result = std::string (number[0]) + result;
254             eat_zero = true;
255             continue;
256         }else{
257             eat_zero = false;
258         }
259
260         if (num == 0 && remains == 1 && i == 5)
261             result = std::string (units[i].unit_zh_name) + result;
262         else if (units[i].persist)
263             result = std::string (number[remains]) + result;
264         else
265             result = std::string (number[remains]) + std::string (units[i].unit_zh_name) + result;
266     }
267
268     return result;
269 }
270
271 const std::string
272 DynamicSpecialPhrase::simplified_number(gint64 num)
273 {
274     return translate_to_longform(num, numbers[1], units_simplified);
275 }
276
277 const std::string
278 DynamicSpecialPhrase::traditional_number(gint64 num)
279 {
280     if ( 0 == num )
281         return numbers[0][0];
282     return translate_to_longform(num, numbers[0], units_traditional);
283 }
284
285 inline const std::string
286 DynamicSpecialPhrase::variable (const std::string &name)
287 {
288     if (name == "year")     return dec (m_time.tm_year + 1900);
289     if (name == "year_yy")  return dec ((m_time.tm_year + 1900) % 100, "%02d");
290     if (name == "month")    return dec (m_time.tm_mon + 1);
291     if (name == "month_mm") return dec (m_time.tm_mon + 1, "%02d");
292     if (name == "day")      return dec (m_time.tm_mday);
293     if (name == "day_dd")   return dec (m_time.tm_mday, "%02d");
294     if (name == "weekday")  return dec (m_time.tm_wday + 1);
295     if (name == "fullhour") return dec (m_time.tm_hour, "%02d");
296     if (name == "falfhour") return dec (m_time.tm_hour % 12, "%02d");
297     if (name == "ampm")     return m_time.tm_hour < 12 ? "AM" : "PM";
298     if (name == "minute")   return dec (m_time.tm_min, "%02d");
299     if (name == "second")   return dec (m_time.tm_sec, "%02d");
300     if (name == "year_cn")      return year_cn ();
301     if (name == "year_yy_cn")   return year_cn (TRUE);
302     if (name == "month_cn")     return month_cn ();
303     if (name == "day_cn")       return day_cn ();
304     if (name == "weekday_cn")   return weekday_cn ();
305     if (name == "fullhour_cn")  return fullhour_cn ();
306     if (name == "halfhour_cn")  return halfhour_cn ();
307     if (name == "ampm_cn")      return m_time.tm_hour < 12 ? "上午" : "下午";
308     if (name == "minute_cn")    return minsec_cn (m_time.tm_min);
309     if (name == "second_cn")    return minsec_cn (m_time.tm_sec);
310
311     return "${" + name + "}";
312 }
313
314 };