1 /*******************************************************
2  Copyright (C) 2006 Madhan Kanagavel
3  Copyright (C) 2013-2015 Nikolay
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ********************************************************/
19 
20 #include "util.h"
21 #include "validators.h"
22 #include "model/Model_Currency.h"
23 #include "model/Model_Infotable.h"
24 #include "model/Model_Setting.h"
25 #include <wx/sstream.h>
26 //----------------------------------------------------------------------------
27 
CaseInsensitiveCmp(const wxString & s1,const wxString & s2)28 int CaseInsensitiveCmp(const wxString &s1, const wxString &s2)
29 {
30     return s1.CmpNoCase(s2);
31 }
32 
33 //----------------------------------------------------------------------------
correctEmptyFileExt(const wxString & ext,wxString & fileName)34 void correctEmptyFileExt(const wxString& ext, wxString & fileName)
35 {
36     wxFileName tempFileName(fileName);
37     if (tempFileName.GetExt().IsEmpty())
38         fileName += "." + ext;
39 }
40 
inQuotes(const wxString & l,const wxString & delimiter)41 const wxString inQuotes(const wxString& l, const wxString& delimiter)
42 {
43     wxString label = l;
44     if (label.Contains(delimiter) || label.Contains("\""))
45     {
46         label.Replace("\"","\"\"", true);
47         label = wxString() << "\"" << label << "\"";
48     }
49 
50     label.Replace("\t","    ", true);
51     label.Replace("\n"," ", true);
52     return label;
53 }
54 
mmLoadColorsFromDatabase()55 void mmLoadColorsFromDatabase()
56 {
57     mmColors::userDefColor1 = Model_Infotable::instance().GetColourSetting("USER_COLOR1", wxColour(255, 0, 0));
58     mmColors::userDefColor2 = Model_Infotable::instance().GetColourSetting("USER_COLOR2", wxColour(255, 165, 0));
59     mmColors::userDefColor3 = Model_Infotable::instance().GetColourSetting("USER_COLOR3", wxColour(255, 255, 0));
60     mmColors::userDefColor4 = Model_Infotable::instance().GetColourSetting("USER_COLOR4", wxColour(0, 255, 0));
61     mmColors::userDefColor5 = Model_Infotable::instance().GetColourSetting("USER_COLOR5", wxColour(0, 255, 255));
62     mmColors::userDefColor6 = Model_Infotable::instance().GetColourSetting("USER_COLOR6", wxColour(0, 0, 255));
63     mmColors::userDefColor7 = Model_Infotable::instance().GetColourSetting("USER_COLOR7", wxColour(0, 0, 128));
64 }
65 
66 /* Set the default colors */
67 wxColour mmColors::listAlternativeColor0 = wxColour(225, 237, 251);
68 wxColour mmColors::listAlternativeColor1 = wxColour(255, 255, 255);
69 wxColour mmColors::listBackColor = wxColour(255, 255, 255);
70 wxColour mmColors::navTreeBkColor = wxColour(255, 255, 255);
71 wxColour mmColors::listBorderColor = wxColour(0, 0, 0);
72 wxColour mmColors::listDetailsPanelColor = wxColour(244, 247, 251);
73 wxColour mmColors::listFutureDateColor = wxColour(116, 134, 168);
74 
75 wxColour mmColors::userDefColor1;
76 wxColour mmColors::userDefColor2;
77 wxColour mmColors::userDefColor3;
78 wxColour mmColors::userDefColor4;
79 wxColour mmColors::userDefColor5;
80 wxColour mmColors::userDefColor6;
81 wxColour mmColors::userDefColor7;
82 
83 //*-------------------------------------------------------------------------*//
84 
site_content(const wxString & sSite,wxString & sOutput)85 int site_content(const wxString& sSite, wxString& sOutput)
86  {
87     wxString proxyName = Model_Setting::instance().GetStringSetting("PROXYIP", "");
88     if (!proxyName.empty())
89     {
90         int proxyPort = Model_Setting::instance().GetIntSetting("PROXYPORT", 0);
91         const wxString& proxySettings = wxString::Format("%s:%d", proxyName, proxyPort);
92         wxURL::SetDefaultProxy(proxySettings);
93     }
94     else
95         wxURL::SetDefaultProxy(""); // Remove prior proxy
96 
97     wxURL url(sSite);
98     int err_code = url.GetError();
99     if (err_code == wxURL_NOERR)
100     {
101         int networkTimeout = Model_Setting::instance().GetIntSetting("NETWORKTIMEOUT", 10); // default 10 secs
102         url.GetProtocol().SetTimeout(networkTimeout);
103         wxInputStream* in_stream = url.GetInputStream();
104         if (in_stream)
105         {
106             wxStringOutputStream out_stream(&sOutput);
107             in_stream->Read(out_stream);
108         }
109         else
110             err_code = -1; //Cannot get data from WWW!
111         delete in_stream;
112     }
113 
114     if (err_code != wxURL_NOERR)
115     {
116         if      (err_code == wxURL_SNTXERR ) sOutput = _("Syntax error in the URL string");
117         else if (err_code == wxURL_NOPROTO ) sOutput = _("Found no protocol which can get this URL");
118         else if (err_code == wxURL_NOHOST  ) sOutput = _("A host name is required for this protocol");
119         else if (err_code == wxURL_NOPATH  ) sOutput = _("A path is required for this protocol");
120         else if (err_code == wxURL_CONNERR ) sOutput = _("Connection error");
121         else if (err_code == wxURL_PROTOERR) sOutput = _("An error occurred during negotiation");
122         else if (err_code == -1) sOutput = _("Cannot get data from WWW!");
123         else sOutput = _("Unknown error");
124     }
125     return err_code;
126 }
127 
download_file(const wxString & site,const wxString & path)128 bool download_file(const wxString& site, const wxString& path)
129 {
130     wxFileSystem fs;
131     wxFileSystem::AddHandler(new wxInternetFSHandler());
132     wxFSFile *file = fs.OpenFile(site);
133     if (file != NULL)
134     {
135         wxInputStream *in = file->GetStream();
136         if (in != NULL)
137         {
138             wxFileOutputStream output(path);
139             output.Write(*file->GetStream());
140             output.Close();
141             delete in;
142             return true;
143         }
144     }
145 
146     return false;
147 }
148 
149 //* Date Functions----------------------------------------------------------*//
mmGetNiceDateSimpleString(const wxDateTime & dt)150 const wxString mmGetNiceDateSimpleString(const wxDateTime &dt)
151 {
152     wxString dateFmt = mmOptions::instance().dateFormat_;
153     dateFmt.Replace("%Y%m%d", "%Y %m %d");
154     dateFmt.Replace(".", " ");
155     dateFmt.Replace(",", " ");
156     dateFmt.Replace("/", " ");
157     dateFmt.Replace("-", " ");
158     dateFmt.Replace("%d", wxString::Format("%d", dt.GetDay()));
159     dateFmt.Replace("%Y", wxString::Format("%d", dt.GetYear()));
160     dateFmt.Replace("%y", wxString::Format("%d", dt.GetYear()).Mid(2,2));
161     dateFmt.Replace("%m", wxGetTranslation(wxDateTime::GetEnglishMonthName(dt.GetMonth())));
162 
163     return dateFmt;
164 }
165 
mmGetDateForDisplay(const wxDateTime & dt)166 const wxString mmGetDateForDisplay(const wxDateTime &dt)
167 {
168     return dt.Format(mmOptions::instance().dateFormat_);
169 }
170 
mmParseDisplayStringToDate(wxDateTime & date,wxString sDate,const wxString & sDateMask)171 bool mmParseDisplayStringToDate(wxDateTime& date, wxString sDate, const wxString &sDateMask)
172 {
173     if (date_formats_regex().count(sDateMask) == 0)
174         return false;
175 
176     const wxString regex = date_formats_regex().at(sDateMask);
177     wxRegEx pattern(regex);
178 
179     if (pattern.Matches(sDate))
180     {
181         sDate = pattern.GetMatch(sDate);
182         wxString::const_iterator end;
183         return date.ParseFormat(sDate, sDateMask, &end);
184     }
185     return false;
186 }
187 
mmGetStorageStringAsDate(const wxString & str)188 const wxDateTime mmGetStorageStringAsDate(const wxString& str)
189 {
190     wxDateTime dt;
191     if (str.IsEmpty() || !dt.ParseDate(str))
192         dt = wxDateTime::Today();
193     int year = dt.GetYear();
194     if (year < 50)
195         dt.Add(wxDateSpan::Years(2000));
196     else if (year < 100)
197         dt.Add(wxDateSpan::Years(1900));
198     return dt;
199 }
200 
date_formats_regex()201 const std::map<wxString,wxString> date_formats_regex()
202 {
203     const wxString dd = "((([0 ][1-9])|([1-2][0-9])|(3[0-1]))|([1-9]))";
204     const wxString mm = "((([0 ][1-9])|(1[0-2]))|([1-9]))";
205     const wxString yy = "([0-9]{2})";
206     const wxString yyyy = "(((19)|([2]([0]{1})))([0-9]{2}))";
207     std::map<wxString, wxString> date_regex;
208     date_regex["%d/%m/%y"] = wxString::Format("^%s/%s/%s*", dd, mm, yy);
209     date_regex["%d/%m/%Y"] = wxString::Format("^%s/%s/%s*", dd, mm, yyyy);
210     date_regex["%d-%m-%y"] = wxString::Format("^%s-%s-%s*", dd, mm, yy);
211     date_regex["%d-%m-%Y"] = wxString::Format("^%s-%s-%s*", dd, mm, yyyy);
212     date_regex["%d.%m.%y"] = wxString::Format("^%s\x2E%s\x2E%s*", dd, mm, yy);
213     date_regex["%d.%m.%Y"] = wxString::Format("^%s\x2E%s\x2E%s*", dd, mm, yyyy);
214     date_regex["%d,%m,%y"] = wxString::Format("^%s,%s,%s*", dd, mm, yy);
215     date_regex["%d/%m'%Y"] = wxString::Format("^%s/%s'%s*", dd, mm, yyyy);
216     date_regex["%d/%m %Y"] = wxString::Format("^%s/%s %s*", dd, mm, yyyy);
217     date_regex["%m/%d/%y"] = wxString::Format("^%s/%s/%s*", mm, dd, yy);
218     date_regex["%m/%d/%Y"] = wxString::Format("^%s/%s/%s*", mm, dd, yyyy);
219     date_regex["%m-%d-%y"] = wxString::Format("^%s-%s-%s*", mm, dd, yy);
220     date_regex["%m-%d-%Y"] = wxString::Format("^%s-%s-%s*", mm, dd, yyyy);
221     date_regex["%m/%d'%y"] = wxString::Format("^%s/%s'%s*", mm, dd, yy);
222     date_regex["%m/%d'%Y"] = wxString::Format("^%s/%s'%s*", mm, dd, yyyy);
223     date_regex["%y/%m/%d"] = wxString::Format("^%s/%s/%s*", yy, mm, dd);
224     date_regex["%y-%m-%d"] = wxString::Format("^%s-%s-%s*", yy, mm, dd);
225     date_regex["%Y/%m/%d"] = wxString::Format("^%s/%s/%s*", yyyy, mm, dd);
226     date_regex["%Y-%m-%d"] = wxString::Format("^%s-%s-%s*", yyyy, mm, dd);
227     date_regex["%Y.%m.%d"] = wxString::Format("^%s\x2E%s\x2E%s*", yyyy, mm, dd);
228     date_regex["%Y %m %d"] = wxString::Format("^%s %s %s*", yyyy, mm, dd);
229     date_regex["%Y%m%d"] = wxString::Format("^%s%s%s*", yyyy, mm, dd);
230 
231     return date_regex;
232 }
233 
234 const std::map<wxString, wxString> g_date_formats_map = {
235     { "%Y-%m-%d", "YYYY-MM-DD" }
236     , { "%d/%m/%y", "DD/MM/YY" }
237     , { "%d/%m/%Y", "DD/MM/YYYY" }
238     , { "%d-%m-%y", "DD-MM-YY" }
239     , { "%d-%m-%Y", "DD-MM-YYYY" }
240     , { "%d.%m.%y", "DD.MM.YY" }
241     , { "%d.%m.%Y", "DD.MM.YYYY" }
242     , { "%d,%m,%y", "DD,MM,YY" }
243     , { "%d/%m'%Y", "DD/MM'YYYY" }
244     , { "%d/%m %Y", "DD/MM YYYY" }
245     , { "%m/%d/%y", "MM/DD/YY" }
246     , { "%m/%d/%Y", "MM/DD/YYYY" }
247     , { "%m-%d-%y", "MM-DD-YY" }
248     , { "%m-%d-%Y", "MM-DD-YYYY" }
249     , { "%m/%d'%y", "MM/DD'YY" }
250     , { "%m/%d'%Y", "MM/DD'YYYY" }
251     , { "%y/%m/%d", "YY/MM/DD" }
252     , { "%y-%m-%d", "YY-MM-DD" }
253     , { "%Y/%m/%d", "YYYY/MM/DD" }
254     , { "%Y.%m.%d", "YYYY.MM.DD" }
255     , { "%Y %m %d", "YYYY MM DD" }
256     , { "%Y%m%d", "YYYYMMDD" }
257 };
258 
259 static const wxString MONTHS[12] =
260 {
261     wxTRANSLATE("January"), wxTRANSLATE("February"), wxTRANSLATE("March")
262     , wxTRANSLATE("April"), wxTRANSLATE("May"), wxTRANSLATE("June")
263     , wxTRANSLATE("July"), wxTRANSLATE("August"), wxTRANSLATE("September")
264     , wxTRANSLATE("October"), wxTRANSLATE("November"), wxTRANSLATE("December")
265 };
266 
267 static const wxString MONTHS_SHORT[12] =
268 {
269     wxTRANSLATE("Jan"), wxTRANSLATE("Feb"), wxTRANSLATE("Mar")
270     , wxTRANSLATE("Apr"), wxTRANSLATE("May"), wxTRANSLATE("Jun")
271     , wxTRANSLATE("Jul"), wxTRANSLATE("Aug"), wxTRANSLATE("Sep")
272     , wxTRANSLATE("Oct"), wxTRANSLATE("Nov"), wxTRANSLATE("Dec")
273 };
274 
275 static const wxString gDaysInWeek[7] =
276 {
277     wxTRANSLATE("Sunday"), wxTRANSLATE("Monday"), wxTRANSLATE("Tuesday")
278     , wxTRANSLATE("Wednesday"), wxTRANSLATE("Thursday"), wxTRANSLATE("Friday")
279     , wxTRANSLATE("Saturday")
280 };
281 
282 //
mmPlatformType()283 const wxString mmPlatformType()
284 {
285 	return wxPlatformInfo::Get().GetOperatingSystemFamilyName().substr(0, 3);
286 }
287 
getURL(const wxString & file)288 const wxString getURL(const wxString& file)
289 {
290 	wxString index = file;
291 #ifdef __WXGTK__
292     index.Prepend("file://");
293 #endif
294     return index;
295 }
296 
windowsFreezeThaw(wxWindow * w)297 void windowsFreezeThaw(wxWindow* w)
298 {
299 #ifdef __WXGTK__
300     return;
301 #endif
302 
303     if (w->IsFrozen())
304         w->Thaw();
305     else
306         w->Freeze();
307 }
308 
309 #if 1
310 // ----------------------------------------------------------------------------
311 // mmCalcValidator
312 // Same as previous, but substitute dec char according to currency configuration
313 // ----------------------------------------------------------------------------
314 
IMPLEMENT_DYNAMIC_CLASS(mmCalcValidator,wxTextValidator)315 IMPLEMENT_DYNAMIC_CLASS(mmCalcValidator, wxTextValidator)
316 BEGIN_EVENT_TABLE(mmCalcValidator, wxTextValidator)
317 EVT_CHAR(mmCalcValidator::OnChar)
318 END_EVENT_TABLE()
319 
320 mmCalcValidator::mmCalcValidator() : wxTextValidator(wxFILTER_INCLUDE_CHAR_LIST)
321 {
322     wxArrayString list;
323     for (const auto& c : " 1234567890.,(/+-*)")
324     {
325         list.Add(c);
326     }
327     SetIncludes(list);
328     const Model_Currency::Data *base_currency = Model_Currency::instance().GetBaseCurrency();
329     if (base_currency)
330         m_decChar = base_currency->DECIMAL_POINT[0];
331 }
332 
OnChar(wxKeyEvent & event)333 void mmCalcValidator::OnChar(wxKeyEvent& event)
334 {
335     if (!m_validatorWindow)
336     {
337         event.Skip();
338         return;
339     }
340 
341     int keyCode = event.GetKeyCode();
342 
343     // we don't filter special keys and delete
344     if (keyCode < WXK_SPACE || keyCode == WXK_DELETE || keyCode >= WXK_START)
345     {
346         event.Skip();
347         return;
348     }
349 
350     const wxString str((wxUniChar)keyCode, 1);
351     if (!(wxIsdigit(str[0]) || wxString("+-.,*/ ()").Contains(str)))
352     {
353         if ( !wxValidator::IsSilent() )
354             wxBell();
355 
356         // eat message
357         return;
358     }
359     // only if it's a wxTextCtrl
360     if (!m_validatorWindow || !wxDynamicCast(m_validatorWindow, wxTextCtrl))
361     {
362         event.Skip();
363         return;
364     }
365     // if decimal point, check if it's already in the string
366     if (str == '.' || str == ',')
367     {
368         const wxString value = ((wxTextCtrl*)m_validatorWindow)->GetValue();
369         size_t ind = value.rfind(m_decChar);
370         if (ind < value.Length())
371         {
372             // check if after last decimal point there is an operation char (+-/*)
373             if (value.find('+', ind+1) >= value.Length() && value.find('-', ind+1) >= value.Length() &&
374                 value.find('*', ind+1) >= value.Length() && value.find('/', ind+1) >= value.Length())
375                 return;
376         }
377 #ifdef _MSC_VER
378         if (str != m_decChar)
379         {
380             const wxChar vk = m_decChar == '.' ? 0x6e : 0xbc;
381             keybd_event(vk, 0xb3, 0, 0);
382             keybd_event(vk, 0xb3, KEYEVENTF_KEYUP, 0);
383             return;
384         }
385 #endif
386     }
387     event.Skip();
388 }
389 #endif
390