Delete some debug symbols
[mverbiste] / gui / conjugation.cpp
1 /*  $Id: conjugation.cpp,v 1.12 2011/01/25 02:29:44 sarrazip Exp $
2     conjugation.cpp - Generic conjugation interface
3
4     verbiste - French conjugation system
5     Copyright (C) 2003-2006 Pierre Sarrazin <http://sarrazip.com/>
6
7     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License
9     as published by the Free Software Foundation; either version 2
10     of the License, or (at your option) 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., 59 Temple Place - Suite 330, Boston, MA
20     02111-1307, USA.
21 */
22
23 #include "conjugation.h"
24
25 #include <libintl.h>
26 #define _(x) gettext(x)
27 #define N_(x) (x)
28
29 #include <iostream>
30 #include <string.h>
31
32 using namespace std;
33 using namespace verbiste;
34
35
36 void
37 getConjugation(const FrenchVerbDictionary &fvd,
38                const string &infinitive,
39                const string &tname,
40                VVVS &dest,
41                bool includePronouns)
42 {
43     const TemplateSpec *templ = fvd.getTemplate(tname);
44     if (templ == NULL)
45         return;
46
47     try
48     {
49         static const struct { Mode m; Tense t; } table[] =
50         {
51             { INFINITIVE_MODE, PRESENT_TENSE },
52             { INDICATIVE_MODE, PRESENT_TENSE },
53             { INDICATIVE_MODE, IMPERFECT_TENSE },
54             { INDICATIVE_MODE, FUTURE_TENSE },
55             { INDICATIVE_MODE, PAST_TENSE },
56             { CONDITIONAL_MODE, PRESENT_TENSE },
57             { SUBJUNCTIVE_MODE, PRESENT_TENSE },
58             { SUBJUNCTIVE_MODE, IMPERFECT_TENSE },
59             { IMPERATIVE_MODE, PRESENT_TENSE },
60             { PARTICIPLE_MODE, PRESENT_TENSE },
61             { PARTICIPLE_MODE, PAST_TENSE },
62             { GERUND_MODE, PRESENT_TENSE },  // italian only
63             { INVALID_MODE, INVALID_TENSE }  // marks the end
64         };
65
66
67         string radical = FrenchVerbDictionary::getRadical(infinitive, tname);
68
69         bool isItalian = (fvd.getLanguage() == FrenchVerbDictionary::ITALIAN);
70
71         for (int j = 0; table[j].m != INVALID_MODE; j++)
72         {
73             if (table[j].m == GERUND_MODE && !isItalian)
74                 continue;
75
76             dest.push_back(VVS());
77             VVS &tenseDest = dest.back();
78
79             VVS conjug;
80             fvd.generateTense(radical, *templ, table[j].m, table[j].t, conjug,
81                                 includePronouns,
82                                 fvd.isVerbStartingWithAspirateH(infinitive),
83                                 isItalian);
84
85             for (VVS::const_iterator p = conjug.begin(); p != conjug.end(); p++)
86             {
87                 tenseDest.push_back(VS());
88                 for (VS::const_iterator i = p->begin(); i != p->end(); i++)
89                 {
90                     string s = *i;
91                     tenseDest.back().push_back(s);
92                 }
93             }
94         }
95     }
96     catch (logic_error &e)
97     {
98         dest.clear();
99         return;
100     }
101 }
102
103
104 static const char *tn[16] =
105 {
106     N_("inf. pres."),
107     "",
108     "",
109     "",
110     N_("ind. pres."),
111     N_("ind. imperf."),
112     N_("ind. fut."),
113     N_("ind. past"),
114     N_("cond. pres."),
115     N_("subj. pres."),
116     N_("subj. imperf."),
117     "",
118     N_("imp. pres."),
119     N_("part. pres."),
120     N_("part. past"),
121     N_("gerund pres."),  // italian only
122 };
123
124
125 string getTenseNameForTableCell(int row, int col, bool isItalian)
126 {
127     if (row < 0 || row > 3 || col < 0 || col > 3)
128     {
129         assert(false);
130         return "";
131     }
132
133     if (row == 3 && col == 3 && !isItalian)
134         return string();
135
136     return _(tn[row * 4 + col]);
137 }
138
139
140 static
141 string
142 removePronoun(const string &s)
143 {
144     string::size_type start = 0;
145     if (s.find("que ") == 0)
146         start = 4;
147     else if (s.find("qu'") == 0)
148         start = 3;
149     else if (s.find("che ") == 0)  // Italian
150         start = 4;
151
152     static const char *pronouns[] =
153     {
154         "je ", "j'", "tu ", "il ", "nous ", "vous ", "ils ",
155         "io ", "tu ", "egli ", "noi ", "voi ", "essi ",  // Italian
156         NULL
157     };
158
159     for (size_t i = 0; pronouns[i] != NULL; i++)
160     {
161         size_t len = strlen(pronouns[i]);
162         if (s.find(pronouns[i], start) == start)
163         {
164             start += len;
165             break;
166         }
167     }
168
169     return string(s, start, string::npos);
170 }
171
172
173 string
174 createTableCellText(verbiste::FrenchVerbDictionary &fvd,
175                     const VVS &tense,
176                     const string &lowerCaseUTF8UserText,
177                     const string &openMark,
178                     const string &closeMark)
179 {
180     string userTextWOAccents = fvd.removeUTF8Accents(lowerCaseUTF8UserText);
181
182     string persons;
183     for (VVS::const_iterator it = tense.begin(); it != tense.end(); it++)
184     {
185         const VS &person = *it;
186
187         if (it != tense.begin())
188             persons += "\n";
189
190         for (VS::const_iterator i = person.begin(); i != person.end(); i++)
191         {
192             if (i != person.begin())
193                 persons += ", ";
194
195             string inflection = fvd.removeUTF8Accents(removePronoun(*i));
196             if (inflection == userTextWOAccents)
197                 persons += openMark + *i + closeMark;
198             else
199                 persons += *i;
200         }
201     }
202     return persons;
203 }
204
205
206 /**
207  * Qt version of createTableCellText() above.
208  * Return a vertor of QStrings, which are conjugations.
209  **/
210 QVector<QString> qgetConjugates(verbiste::FrenchVerbDictionary &fvd,
211                                 const VVS &tense,
212                                 const string &lowerCaseUTF8UserText,
213                                 const string &openMark,
214                                 const string &closeMark)
215 {
216     string userTextWOAccents = fvd.removeUTF8Accents(lowerCaseUTF8UserText);
217     QVector<QString> persons(0);
218     for (VVS::const_iterator it = tense.begin(); it != tense.end(); it++)
219     {
220         const VS &person = *it;
221         QString ver;
222
223 //        if (it != tense.begin())
224 //            persons += "\n";
225
226         for (VS::const_iterator i = person.begin(); i != person.end(); i++)
227         {
228             if (i != person.begin())
229                 ver.append(", ");
230
231             string inflection = fvd.removeUTF8Accents(removePronoun(*i));
232             if (inflection == userTextWOAccents) {
233                 const std::string wrapped = openMark + *i + closeMark;
234                 ver.append(QString::fromUtf8(wrapped.c_str()));
235             }
236             else {
237                 const char *str = (*i).c_str();
238                 ver.append(QString::fromUtf8(str));
239             }
240         }
241         persons.append(ver);
242     }
243     return persons;
244 }