1 /*
2  *      utils.cpp
3  *
4  *      Copyright 2008 David Vachulka <arch_dvx@users.sourceforge.net>
5  *
6  *      This program is free software; you can redistribute it and/or modify
7  *      it under the terms of the GNU General Public License as published by
8  *      the Free Software Foundation; either version 2 of the License, or
9  *      (at your option) any later version.
10  *
11  *      This program is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *      GNU General Public License for more details.
15  *
16  *      You should have received a copy of the GNU General Public License
17  *      along with this program; if not, write to the Free Software
18  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *      MA 02110-1301, USA.
20  */
21 
22 #ifdef WIN32
23  #define WIN32_LEAN_AND_MEAN
24  #include <windows.h>
25  #include <mmsystem.h>
26  #include <ctime>
27  #include <shellapi.h>
28 #endif
29 #include <random>
30 #include "config.h"
31 #include "i18n.h"
32 #include "dxutils.h"
33 #ifdef HAVE_ENCHANT
34 #include <enchant++.h>
35 #include <FXString.h>
36 #endif
37 #include "dxirc.h"
38 
39 #define preferences dxirc::instance()->getPreferences()
40 
41 #ifdef HAVE_ENCHANT
42 static enchant::Broker *ebroker;
43 typedef std::pair<Checkers*,dxStringArray*> CheckerPair;
enumerateDicts(const char * const lang_tag,const char * const,const char * const,const char * const,void * user_data)44 void enumerateDicts (const char * const lang_tag,
45          const char * const /*provider_name*/,
46          const char * const /*provider_desc*/,
47          const char * const /*provider_file*/,
48          void * user_data)
49 {
50     CheckerPair *chpair = (CheckerPair*)user_data;
51     const Checkers &checkers = *chpair->first;
52     dxStringArray &spellLang = *(chpair->second);
53     if(checkers.find(lang_tag) == checkers.end())
54         spellLang.append(lang_tag);
55 }
56 #endif
57 
58 //This's from Xfe, thanks
streq(const FXchar * a,const FXchar * b)59 int streq(const FXchar *a, const FXchar *b)
60 {
61     if (a == NULL || b == NULL)
62         return 0;
63     return (strcmp(a, b) == 0);
64 }
65 
dxutils()66 dxutils::dxutils()
67 {
68     m_lcodec = NULL;
69     m_iniFile = FXString::null;
70     m_locale = FXString::null;
71     m_haveNotify = false;
72 #ifndef WIN32
73     if(!FXPath::search(FXSystem::getExecPath(), "notify-send").empty())
74         m_haveNotify = true;
75 #endif // WIN32
76 #ifdef HAVE_ENCHANT
77 #ifdef HAVE_ENCHANT2
78     ebroker = new enchant::Broker();
79 #else
80     ebroker = enchant::Broker::instance();
81 #endif //HAVE_ENCHANT2
82 #endif //HAVE_ENCHANT
83 }
84 
~dxutils()85 dxutils::~dxutils()
86 {
87 #ifdef HAVE_ENCHANT
88     Checkers::const_iterator it = m_checkers.begin();
89     for(; it != m_checkers.end(); it++)
90     {
91         delete (*it).second;
92     }
93 #endif
94 #ifdef HAVE_ENCHANT2
95     delete ebroker;
96 #endif
97 }
98 
instance()99 dxutils &dxutils::instance()
100 {
101     static dxutils p;
102     return p;
103 }
104 
fillCommands()105 void dxutils::fillCommands()
106 {
107     m_commands.clear();
108     m_dcccommands.clear();
109     m_commands.append("ADMIN");
110     m_commands.append("AWAY");
111     m_commands.append("BANLIST");
112     m_commands.append("BOATS");
113     m_commands.append("CONNECT");
114     m_commands.append("COMMANDS");
115     m_dcccommands.append("COMMANDS");
116     m_commands.append("CTCP");
117     m_commands.append("CYCLE");
118     m_commands.append("DCC");
119     m_commands.append("DEOP");
120     m_commands.append("DEVOICE");
121     m_commands.append("DISCONNECT");
122 #ifndef WIN32
123     m_commands.append("EXEC");
124     m_dcccommands.append("EXEC");
125 #endif
126     m_commands.append("HELP");
127     m_dcccommands.append("HELP");
128     m_commands.append("IGNORE");
129     m_commands.append("INVITE");
130     m_commands.append("JOIN");
131     m_commands.append("KICK");
132     m_commands.append("KILL");
133     m_commands.append("LIST");
134     m_commands.append("LOG");
135     m_dcccommands.append("LOG");
136 #ifdef HAVE_LUA
137     m_commands.append("LUA");
138     m_dcccommands.append("LUA");
139 #endif
140     m_commands.append("ME");
141     m_dcccommands.append("ME");
142     m_commands.append("MODE");
143     m_commands.append("MSG");
144     m_commands.append("NAMES");
145     m_commands.append("NICK");
146     m_commands.append("NOTICE");
147     m_commands.append("OP");
148     m_commands.append("OPER");
149     m_commands.append("PART");
150     m_commands.append("QUERY");
151     m_commands.append("QUIT");
152     m_commands.append("QUOTE");
153     m_commands.append("SAY");
154     m_dcccommands.append("SAY");
155     m_commands.append("STATS");
156     m_commands.append("TIME");
157     m_commands.append("TOPIC");
158     m_commands.append("VOICE");
159     m_commands.append("WALLOPS");
160     m_commands.append("WHO");
161     m_commands.append("WHOAMI");
162     m_commands.append("WHOIS");
163     m_commands.append("WHOWAS");
164     StringIt it;
165     for(it=m_aliases.begin(); it!=m_aliases.end(); it++)
166     {
167         m_commands.append((*it).first.after('/'));
168     }
169     for(FXint i=0; i<m_scriptCommands.no(); i++)
170     {
171         m_commands.append(m_scriptCommands[i].name);
172         m_dcccommands.append(m_scriptCommands[i].name);
173     }
174     FXString v;
175     FXint i,j,h;
176     for(h=1; h<=m_commands.no()/9; h=3*h+1);
177     for(; h > 0; h /= 3)
178     {
179         for(i = h + 1; i <= m_commands.no(); i++)
180         {
181             v = m_commands[i - 1];
182             j = i;
183             while (j > h && comparecase(m_commands[j - h - 1], v) > 0)
184             {
185                 m_commands[j - 1] = m_commands[j - h - 1];
186                 j -= h;
187             }
188             m_commands[j - 1] = v;
189         }
190     }
191     for(h=1; h<=m_dcccommands.no()/9; h=3*h+1);
192     for(; h > 0; h /= 3)
193     {
194         for(i = h + 1; i <= m_dcccommands.no(); i++)
195         {
196             v = m_dcccommands[i - 1];
197             j = i;
198             while (j > h && comparecase(m_dcccommands[j - h - 1], v) > 0)
199             {
200                 m_dcccommands[j - 1] = m_dcccommands[j - h - 1];
201                 j -= h;
202             }
203             m_dcccommands[j - 1] = v;
204         }
205     }
206 }
207 
getCodec()208 FXTextCodec* dxutils::getCodec()
209 {
210     if(m_lcodec != NULL)
211         return m_lcodec;
212     else
213     {
214 #ifdef WIN32
215         UINT codepage = ::GetACP();
216         switch(codepage)
217         {
218             case 1250:
219             {
220                 m_lcodec = new FXCP1250Codec();
221                 return m_lcodec;
222             }
223             case 1251:
224             {
225                 m_lcodec = new FXCP1251Codec();
226                 return m_lcodec;
227             }
228             case 1252:
229             {
230                 m_lcodec = new FXCP1252Codec();
231                 return m_lcodec;
232             }
233             case 1253:
234             {
235                 m_lcodec = new FXCP1253Codec();
236                 return m_lcodec;
237             }
238             case 1254:
239             {
240                 m_lcodec = new FXCP1254Codec();
241                 return m_lcodec;
242             }
243             case 1255:
244             {
245                 m_lcodec = new FXCP1255Codec();
246                 return m_lcodec;
247             }
248             case 1256:
249             {
250                 m_lcodec = new FXCP1256Codec();
251                 return m_lcodec;
252             }
253             case 1257:
254             {
255                 m_lcodec = new FXCP1257Codec();
256                 return m_lcodec;
257             }
258             case 1258:
259             {
260                 m_lcodec = new FXCP1258Codec();
261                 return m_lcodec;
262             }
263             case 437:
264             {
265                 m_lcodec = new FXCP437Codec();
266                 return m_lcodec;
267             }
268             case 850:
269             {
270                 m_lcodec = new FXCP850Codec();
271                 return m_lcodec;
272             }
273             case 852:
274             {
275                 m_lcodec = new FXCP852Codec();
276                 return m_lcodec;
277             }
278             case 855:
279             {
280                 m_lcodec = new FXCP855Codec();
281                 return m_lcodec;
282             }
283             case 856:
284             {
285                 m_lcodec = new FXCP856Codec();
286                 return m_lcodec;
287             }
288             case 857:
289             {
290                 m_lcodec = new FXCP857Codec();
291                 return m_lcodec;
292             }
293             case 860:
294             {
295                 m_lcodec = new FXCP860Codec();
296                 return m_lcodec;
297             }
298             case 861:
299             {
300                 m_lcodec = new FXCP861Codec();
301                 return m_lcodec;
302             }
303             case 862:
304             {
305                 m_lcodec = new FXCP862Codec();
306                 return m_lcodec;
307             }
308             case 863:
309             {
310                 m_lcodec = new FXCP863Codec();
311                 return m_lcodec;
312             }
313             case 864:
314             {
315                 m_lcodec = new FXCP864Codec();
316                 return m_lcodec;
317             }
318             case 865:
319             {
320                 m_lcodec = new FXCP865Codec();
321                 return m_lcodec;
322             }
323             case 866:
324             {
325                 m_lcodec = new FXCP866Codec();
326                 return m_lcodec;
327             }
328             case 869:
329             {
330                 m_lcodec = new FXCP869Codec();
331                 return m_lcodec;
332             }
333             case 874:
334             {
335                 m_lcodec = new FXCP874Codec();
336                 return m_lcodec;
337             }
338             case 20866:
339             {
340                 m_lcodec = new FXKOI8RCodec();
341                 return m_lcodec;
342             }
343             default:
344             {
345                 m_lcodec = new FXCP1252Codec();
346                 return m_lcodec;
347             }
348         }
349 #else
350         FXString locale, language, territory, codeset, modifier;
351         if(!(FXSystem::getEnvironment("LANG")).empty()) locale = FXSystem::getEnvironment("LANG");
352         else if(!(FXSystem::getEnvironment("LC_ALL")).empty()) locale = FXSystem::getEnvironment("LC_ALL");
353         else if(!(FXSystem::getEnvironment("LC_MESSAGES")).empty()) locale = FXSystem::getEnvironment("LC_MESSAGES");
354         else locale = "en_US";
355         if(locale == "C" || locale == "POSIX")
356         {
357             locale = "en_US";
358         }
359         locale.lower();
360         if(locale.contains("utf")) locale = locale.before('.');
361         language = locale.before('_');
362         territory = locale.after('_').before('.').before('@');
363         codeset = locale.after('.');
364         modifier = locale.after('@');
365 
366         if(language == "af")
367         {
368             m_lcodec = new FX88591Codec();
369             return m_lcodec;
370         }
371         if(language == "ar")
372         {
373             m_lcodec = new FX88596Codec();
374             return m_lcodec;
375         }
376         if(language == "az")
377         {
378             m_lcodec = new FX88599Codec();
379             return m_lcodec;
380         }
381         if(language == "be")
382         {
383             m_lcodec = new FXCP1251Codec();
384             return m_lcodec;
385         }
386         if(language == "bg")
387         {
388             if(codeset=="iso88595") m_lcodec = new FX88595Codec();
389             else if(codeset=="koi8r") m_lcodec = new FXKOI8RCodec();
390             else m_lcodec = new FXCP1251Codec();
391             return m_lcodec;
392         }
393         if(language == "br")
394         {
395             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
396             else if(codeset=="iso885914") m_lcodec = new FX885914Codec();
397             else m_lcodec = new FX88591Codec();
398             return m_lcodec;
399         }
400         if(language == "ca")
401         {
402             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
403             else m_lcodec = new FX88591Codec();
404             return m_lcodec;
405         }
406         if(language == "cs")
407         {
408             m_lcodec = new FX88592Codec();
409             return m_lcodec;
410         }
411         if(language == "cy")
412         {
413             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
414             else if(codeset=="iso885914") m_lcodec = new FX885914Codec();
415             else m_lcodec = new FX88591Codec();
416             return m_lcodec;
417         }
418         if(language == "da")
419         {
420             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
421             else m_lcodec = new FX88591Codec();
422             return m_lcodec;
423         }
424         if(language == "de")
425         {
426             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
427             else m_lcodec = new FX88591Codec();
428             return m_lcodec;
429         }
430         if(language == "ee")
431         {
432             m_lcodec = new FX88594Codec();
433             return m_lcodec;
434         }
435         if(language == "el")
436         {
437             if(modifier=="euro") m_lcodec = new FX885915Codec();
438             else m_lcodec = new FX88597Codec();
439             return m_lcodec;
440         }
441         if(language == "en")
442         {
443             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
444             else m_lcodec = new FX88591Codec();
445             return m_lcodec;
446         }
447         if(language == "eo")
448         {
449             m_lcodec = new FX88593Codec();
450             return m_lcodec;
451         }
452         if(language == "es")
453         {
454             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
455             else m_lcodec = new FX88591Codec();
456             return m_lcodec;
457         }
458         if(language == "et")
459         {
460             if(codeset=="iso88591") m_lcodec = new FX88591Codec();
461             else if(codeset=="iso885913") m_lcodec = new FX885913Codec();
462             else if(codeset=="iso88594") m_lcodec = new FX88594Codec();
463             else m_lcodec = new FX885915Codec();
464             return m_lcodec;
465         }
466         if(language == "eu")
467         {
468             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
469             else m_lcodec = new FX88591Codec();
470             return m_lcodec;
471         }
472         if(language == "fi")
473         {
474             if(codeset=="88591" || codeset=="iso88591") m_lcodec = new FX88591Codec();
475             else m_lcodec = new FX885915Codec();
476             return m_lcodec;
477         }
478         if(language == "fo")
479         {
480             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
481             else m_lcodec = new FX88591Codec();
482             return m_lcodec;
483         }
484         if(language == "fr")
485         {
486             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
487             else m_lcodec = new FX88591Codec();
488             return m_lcodec;
489         }
490         if(language == "fre")
491         {
492             m_lcodec = new FX88591Codec();
493             return m_lcodec;
494         }
495         if(language == "ga")
496         {
497             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
498             else if(codeset=="iso885914") m_lcodec = new FX885914Codec();
499             else m_lcodec = new FX88591Codec();
500             return m_lcodec;
501         }
502         if(language == "gd")
503         {
504             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
505             else if(codeset=="iso885914") m_lcodec = new FX885914Codec();
506             else m_lcodec = new FX88591Codec();
507             return m_lcodec;
508         }
509         if(language == "ger")
510         {
511             m_lcodec = new FX88591Codec();
512             return m_lcodec;
513         }
514         if(language == "gl")
515         {
516             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
517             else m_lcodec = new FX88591Codec();
518             return m_lcodec;
519         }
520         if(language == "gv")
521         {
522             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
523             else if(codeset=="iso885914") m_lcodec = new FX885914Codec();
524             else m_lcodec = new FX88591Codec();
525             return m_lcodec;
526         }
527         if(language == "he")
528         {
529             if(codeset=="cp1255" || codeset=="microsoftcp1255") m_lcodec = new FXCP1255Codec();
530             else m_lcodec = new FX88598Codec();
531             return m_lcodec;
532         }
533         if(language == "hr")
534         {
535             m_lcodec = new FX88592Codec();
536             return m_lcodec;
537         }
538         if(language == "hu")
539         {
540             m_lcodec = new FX88592Codec();
541             return m_lcodec;
542         }
543         if(language == "id")
544         {
545             m_lcodec = new FX88591Codec();
546             return m_lcodec;
547         }
548         if(language == "in")
549         {
550             m_lcodec = new FX88591Codec();
551             return m_lcodec;
552         }
553         if(language == "is")
554         {
555             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
556             else m_lcodec = new FX88591Codec();
557             return m_lcodec;
558         }
559         if(language == "it")
560         {
561             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
562             else m_lcodec = new FX88591Codec();
563             return m_lcodec;
564         }
565         if(language == "iw")
566         {
567             m_lcodec = new FX88598Codec();
568             return m_lcodec;
569         }
570         if(language == "kl")
571         {
572             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
573             else m_lcodec = new FX88591Codec();
574             return m_lcodec;
575         }
576         if(language == "kw")
577         {
578             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
579             else if(codeset=="iso885914") m_lcodec = new FX885914Codec();
580             else m_lcodec = new FX88591Codec();
581             return m_lcodec;
582         }
583         if(language == "lt")
584         {
585             if(codeset=="iso88594") m_lcodec = new FX88594Codec();
586             else m_lcodec = new FX885913Codec();
587             return m_lcodec;
588         }
589         if(language == "lv")
590         {
591             if(codeset=="iso88594") m_lcodec = new FX88594Codec();
592             else m_lcodec = new FX885913Codec();
593             return m_lcodec;
594         }
595         if(language == "mi")
596         {
597             m_lcodec = new FX88591Codec();
598             return m_lcodec;
599         }
600         if(language == "mk")
601         {
602             if(codeset=="cp1251" || codeset=="microsoftc1251") m_lcodec = new FXCP1251Codec();
603             else m_lcodec = new FX88595Codec();
604             return m_lcodec;
605         }
606         if(language == "ms")
607         {
608             m_lcodec = new FX88591Codec();
609             return m_lcodec;
610         }
611         if(language == "mt")
612         {
613             m_lcodec = new FX88593Codec();
614             return m_lcodec;
615         }
616         if(language == "nb")
617         {
618             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
619             else m_lcodec = new FX88591Codec();
620             return m_lcodec;
621         }
622         if(language == "nl")
623         {
624             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
625             else m_lcodec = new FX88591Codec();
626             return m_lcodec;
627         }
628         if(language == "nn")
629         {
630             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
631             else m_lcodec = new FX88591Codec();
632             return m_lcodec;
633         }
634         if(language == "no")
635         {
636             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
637             else m_lcodec = new FX88591Codec();
638             return m_lcodec;
639         }
640         if(language == "ny")
641         {
642             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
643             else m_lcodec = new FX88591Codec();
644             return m_lcodec;
645         }
646         if(language == "oc")
647         {
648             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
649             else m_lcodec = new FX88591Codec();
650             return m_lcodec;
651         }
652         if(language == "pd")
653         {
654             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
655             else m_lcodec = new FX88591Codec();
656             return m_lcodec;
657         }
658         if(language == "ph")
659         {
660             m_lcodec = new FX88591Codec();
661             return m_lcodec;
662         }
663         if(language == "pl")
664         {
665             m_lcodec = new FX88592Codec();
666             return m_lcodec;
667         }
668         if(language == "pp")
669         {
670             m_lcodec = new FX88591Codec;
671             return m_lcodec;
672         }
673         if(language == "pt")
674         {
675             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
676             else m_lcodec = new FX88591Codec();
677             return m_lcodec;
678         }
679         if(language == "ro")
680         {
681             m_lcodec = new FX88592Codec();
682             return m_lcodec;
683         }
684         if(language == "ru")
685         {
686             if(codeset=="koi8r" || territory=="ua") m_lcodec = new FXKOI8RCodec();
687             else if(codeset=="cp1251" || codeset=="microsoftcp1251") m_lcodec = new FXCP1251Codec();
688             else m_lcodec = new FX88595Codec();
689             return m_lcodec;
690         }
691         if(language == "sh")
692         {
693             m_lcodec = new FX88592Codec();
694             return m_lcodec;
695         }
696         if(language == "sk")
697         {
698             m_lcodec = new FX88592Codec();
699             return m_lcodec;
700         }
701         if(language == "sl")
702         {
703             m_lcodec = new FX88592Codec();
704             return m_lcodec;
705         }
706         if(language == "sp")
707         {
708             m_lcodec = new FX88595Codec();
709             return m_lcodec;
710         }
711         if(language == "sq")
712         {
713             m_lcodec = new FX88592Codec();
714             return m_lcodec;
715         }
716         if(language == "sr")
717         {
718             if(codeset=="iso88592" || territory=="sp") m_lcodec = new FX88592Codec();
719             else if(codeset=="cp1251" || codeset=="microsoftcp1251") m_lcodec = new FXCP1251Codec();
720             else m_lcodec = new FX88595Codec();
721             return m_lcodec;
722         }
723         if(language == "sv")
724         {
725             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
726             else m_lcodec = new FX88591Codec();
727             return m_lcodec;
728         }
729         if(language == "th")
730         {
731             m_lcodec = new FX885911Codec();
732             return m_lcodec;
733         }
734         if(language == "tl")
735         {
736             m_lcodec = new FX88591Codec();
737             return m_lcodec;
738         }
739         if(language == "tr")
740         {
741             m_lcodec = new FX88599Codec();
742             return m_lcodec;
743         }
744         if(language == "tt")
745         {
746             m_lcodec = new FXKOI8RCodec();
747             return m_lcodec;
748         }
749         if(language == "uk")
750         {
751             if(codeset=="cp1251" || codeset=="microsoftcp1251") m_lcodec = new FXCP1251Codec();
752             else if(codeset=="koi8u") m_lcodec = new FX885915Codec(); // FXKOI8UCodec doesn't exist
753             else m_lcodec = new FXKOI8RCodec();
754             return m_lcodec;
755         }
756         if(language == "ur")
757         {
758             m_lcodec = new FXCP1256Codec();
759             return m_lcodec;
760         }
761         if(language == "wa")
762         {
763             if(modifier=="euro" || codeset=="iso885915") m_lcodec = new FX885915Codec();
764             else m_lcodec = new FX88591Codec();
765             return m_lcodec;
766         }
767         if(language == "yi")
768         {
769             m_lcodec = new FXCP1255Codec();
770             return m_lcodec;
771         }
772         m_lcodec = new FX885915Codec();
773         return m_lcodec;
774 #endif
775     }
776 }
777 
localeToUtf8(const FXchar * buffer)778 FXString dxutils::localeToUtf8(const FXchar *buffer)
779 {
780     return getCodec()->mb2utf(buffer);
781 }
782 
localeToUtf8(const FXString & text)783 FXString dxutils::localeToUtf8(const FXString& text)
784 {
785     return getCodec()->mb2utf(text);
786 }
787 
setIniFile(const FXString & file)788 void dxutils::setIniFile(const FXString &file)
789 {
790     m_iniFile = file;
791 }
792 
getIniFile()793 FXString dxutils::getIniFile()
794 {
795     FXString pathname;
796     if(!m_iniFile.empty() && !FXStat::isExecutable(m_iniFile))
797     {
798         pathname = FXPath::directory(m_iniFile);
799         if(pathname.empty()) pathname = FXSystem::getCurrentDirectory();
800         if(!FXStat::exists(pathname))
801         {
802             if(!FXDir::create(pathname))
803             {
804                 fxwarning("%s: unable to create directory.\n",pathname.text());
805             }
806         }
807         else
808         {
809             if(!FXStat::isDirectory(pathname))
810             {
811                 fxwarning("%s: is not a directory.\n",pathname.text());
812             }
813         }
814         return m_iniFile;
815     }
816     else
817     {
818 #ifdef WIN32
819         pathname = localeToUtf8(FXSystem::getEnvironment("AppData")+PATHSEPSTRING+"dxirc");
820         if(!FXStat::exists(pathname))
821         {
822             if(!FXDir::create(pathname))
823             {
824                 fxwarning("%s: unable to create directory.\n",pathname.text());
825             }
826         }
827         else
828         {
829             if(!FXStat::isDirectory(pathname))
830             {
831                 fxwarning("%s: is not a directory.\n",pathname.text());
832             }
833         }
834         m_iniFile = pathname.append(PATHSEPSTRING "dxirc.ini");
835         return m_iniFile;
836 #else
837         pathname = FXSystem::getHomeDirectory()+PATHSEPSTRING+".config"+PATHSEPSTRING+"dxirc";
838         if(!FXStat::exists(pathname))
839         {
840             if(!FXDir::create(pathname))
841             {
842                 fxwarning("%s: unable to create directory.\n",pathname.text());
843             }
844         }
845         else
846         {
847             if(!FXStat::isDirectory(pathname))
848             {
849                 fxwarning("%s: is not a directory.\n",pathname.text());
850             }
851         }
852         m_iniFile = pathname.append(PATHSEPSTRING "dxirc");
853         return m_iniFile;
854 #endif
855     }
856     return FXString::null;
857 }
858 
getParam(FXString toParse,FXint n,FXbool toEnd)859 FXString dxutils::getParam(FXString toParse, FXint n, FXbool toEnd)
860 {
861     return getParam(toParse, n, toEnd, ' ');
862 }
863 
getParam(FXString toParse,FXint n,FXbool toEnd,const FXchar & separator)864 FXString dxutils::getParam(FXString toParse, FXint n, FXbool toEnd, const FXchar &separator)
865 {
866     if (toEnd)
867     {
868         return toParse.after(separator, n-1);
869     }
870     else
871     {
872         return toParse.before(separator, n).rafter(separator);
873     }
874 }
875 
removeSpaces(const FXString & text)876 FXString dxutils::removeSpaces(const FXString &text)
877 {
878     FXint num = text.contains(' ');
879     FXString removed;
880     if(num)
881     {
882         for(FXint i=0; i<=num; i++)
883         {
884             removed.append(text.section(' ',i));
885         }
886         return removed;
887     }
888     else
889         return text;
890 }
891 
removeNonalphanumeric(const FXString & text)892 FXString dxutils::removeNonalphanumeric(const FXString &text)
893 {
894     if(FXRex("^[a-zA-Z0-9]+$").match(text))
895         return text;
896     else
897     {
898         FXString rettxt;
899         for(FXint i=0; i<text.length(); i++)
900         {
901             if((47<(FXint)text[i]&&(FXint)text[i]<58) ||
902                     (64<(FXint)text[i]&&(FXint)text[i]<91) ||
903                     (96<(FXint)text[i]&&text[i]<123))
904                 rettxt += text[i];
905             else
906                 rettxt += '0';
907         }
908         return rettxt;
909     }
910 }
911 
createModes(FXchar sign,FXchar mode,FXString nicks)912 FXString dxutils::createModes(FXchar sign, FXchar mode, FXString nicks)
913 {
914     FXString modes;
915     modes += sign;
916     FXString tomode;
917     if(!nicks.contains(' ')) return modes+mode+" "+nicks;
918     if(nicks.right(1) != " ") nicks.append(" ");
919     while(nicks.contains(' '))
920     {
921         modes += mode;
922         tomode += nicks.before(' ')+" ";
923         nicks = nicks.after(' ');
924     }
925     return modes+" "+tomode;
926 }
927 
loadAlias()928 void dxutils::loadAlias()
929 {
930     FXSettings set;
931     set.parseFile(getIniFile(), TRUE);
932     FXint no = set.readIntEntry("ALIASES", "number", 0);
933     for(FXint i=0; i<no; i++)
934     {
935         FXString key, value;
936         key = set.readStringEntry("ALIASES", FXStringFormat("key%d", i).text());
937         value = set.readStringEntry("ALIASES", FXStringFormat("value%d", i).text());
938         if(!key.empty() && !value.empty() && key[0]=='/' && !key.contains(' '))
939             m_aliases.insert(StringPair(key, value));
940     }
941     fillCommands();
942 
943 }
944 
setAliases(dxStringMap a)945 void dxutils::setAliases(dxStringMap a)
946 {
947     m_aliases = a;
948     fillCommands();
949 }
950 
getAlias(FXString key)951 FXString dxutils::getAlias(FXString key)
952 {
953     if(m_aliases.count(key.lower())>0)
954         return m_aliases.find(key)->second;
955     return FXString::null;
956 }
957 
getAliases()958 dxStringMap dxutils::getAliases()
959 {
960     return m_aliases;
961 }
962 
commandsNo()963 FXint dxutils::commandsNo()
964 {
965     return m_commands.no();
966 }
967 
commandsAt(FXint i)968 FXString dxutils::commandsAt(FXint i)
969 {
970     return m_commands.at(i);
971 }
972 
isCommand(const FXString & command)973 FXbool dxutils::isCommand(const FXString &command)
974 {
975     if(!m_commands.no()) return FALSE;
976     for(FXint i=0; i<m_commands.no(); i++)
977     {
978         if(comparecase(command, m_commands.at(i)) == 0) return TRUE;
979     }
980     return FALSE;
981 }
982 
dcccommandsNo()983 FXint dxutils::dcccommandsNo()
984 {
985     return m_dcccommands.no();
986 }
987 
dcccommandsAt(FXint i)988 FXString dxutils::dcccommandsAt(FXint i)
989 {
990     return m_dcccommands.at(i);
991 }
992 
isDccCommand(const FXString & command)993 FXbool dxutils::isDccCommand(const FXString &command)
994 {
995     if(!m_dcccommands.no()) return FALSE;
996     for(FXint i=0; i<m_dcccommands.no(); i++)
997     {
998         if(comparecase(command, m_dcccommands.at(i)) == 0) return TRUE;
999     }
1000     return FALSE;
1001 }
1002 
1003 // This's from Xfe, thanks
1004 // Test if a string is encoded in UTF-8
1005 // "length" is the number of bytes of the string to consider
1006 // Taken from the weechat project. Original author FlashCode <flashcode@flashtux.org>
isUtf8(const FXchar * string,FXuint length)1007 FXbool dxutils::isUtf8(const FXchar* string, FXuint length)
1008 {
1009     FXuint n=0;
1010     while(n<length)
1011     {
1012         // UTF-8, 2 bytes, should be: 110vvvvv 10vvvvvv
1013         if(((FXuchar)(string[0]) & 0xE0) == 0xC0)
1014         {
1015             if(!string[1] || (((FXuchar)(string[1]) & 0xC0) != 0x80))
1016                 return false;
1017             string += 2;
1018             n += 2;
1019         }
1020         // UTF-8, 3 bytes, should be: 1110vvvv 10vvvvvv 10vvvvvv
1021         else if(((FXuchar)(string[0]) & 0xF0) == 0xE0)
1022         {
1023             if (!string[1] || !string[2]
1024                 || (((FXuchar)(string[1]) & 0xC0) != 0x80)
1025                 || (((FXuchar)(string[2]) & 0xC0) != 0x80))
1026                 return false;
1027             string += 3;
1028             n += 3;
1029        }
1030         // UTF-8, 4 bytes, should be: 11110vvv 10vvvvvv 10vvvvvv 10vvvvvv
1031         else if(((FXuchar)(string[0]) & 0xF8) == 0xF0)
1032         {
1033             if (!string[1] || !string[2] || !string[3]
1034                 || (((FXuchar)(string[1]) & 0xC0) != 0x80)
1035                 || (((FXuchar)(string[2]) & 0xC0) != 0x80)
1036                 || (((FXuchar)(string[3]) & 0xC0) != 0x80))
1037                 return false;
1038             string += 4;
1039             n += 4;
1040         }
1041         // UTF-8, 1 byte, should be: 0vvvvvvv
1042         else if((FXuchar)(string[0]) >= 0x80)
1043         {
1044             return false;
1045         }
1046         // Next byte
1047         else
1048         {
1049             string++;
1050             n++;
1051         }
1052     }
1053     return true;
1054 }
1055 
addScriptCommand(LuaScriptCommand command)1056 void dxutils::addScriptCommand(LuaScriptCommand command)
1057 {
1058     m_scriptCommands.append(command);
1059     fillCommands();
1060 }
1061 
1062 //Remove one command for lua script
removeScriptCommand(const FXString & command)1063 FXbool dxutils::removeScriptCommand(const FXString &command)
1064 {
1065     for(FXint i=m_scriptCommands.no()-1; i>-1; i--)
1066     {
1067         if(comparecase(command, m_scriptCommands[i].name) == 0)
1068         {
1069             m_scriptCommands.erase(i);
1070             fillCommands();
1071             return TRUE;
1072         }
1073     }
1074     return FALSE;
1075 }
1076 
1077 //Remove all commands for lua script
removeScriptCommands(const FXString & script)1078 FXbool dxutils::removeScriptCommands(const FXString& script)
1079 {
1080     FXbool result = FALSE;
1081     for(FXint i=m_scriptCommands.no()-1; i>-1; i--)
1082     {
1083         if(comparecase(script, m_scriptCommands[i].script) == 0)
1084         {
1085             m_scriptCommands.erase(i);
1086             result = TRUE;
1087         }
1088     }
1089     fillCommands();
1090     return result;
1091 }
1092 
isScriptCommand(const FXString & command)1093 FXbool dxutils::isScriptCommand(const FXString &command)
1094 {
1095     for(FXint i=0; i<m_scriptCommands.no(); i++)
1096     {
1097         if(comparecase(command, m_scriptCommands[i].name) == 0) return TRUE;
1098     }
1099     return FALSE;
1100 }
1101 
availableCommands()1102 FXString dxutils::availableCommands()
1103 {
1104     FXString commandstr = _("Available commands: ");
1105     for(FXint i=0; i < m_commands.no(); i++)
1106     {
1107         if(m_commands[i] != "commands") commandstr += m_commands[i].upper()+(i != m_commands.no() - 1? ", " : "");
1108     }
1109     return commandstr;
1110 }
1111 
availableDccCommands()1112 FXString dxutils::availableDccCommands()
1113 {
1114     FXString commandstr = _("Available commands: ");
1115     for(FXint i=0; i < m_dcccommands.no(); i++)
1116     {
1117         if(m_dcccommands[i] != "commands") commandstr += m_dcccommands[i].upper()+(i != m_dcccommands.no() - 1? ", " : "");
1118     }
1119     return commandstr;
1120 }
1121 
availableScriptsCommands()1122 FXString dxutils::availableScriptsCommands()
1123 {
1124     FXString commandstr = _("Available commands: ");
1125     for(FXint i=0; i < m_scriptCommands.no(); i++)
1126     {
1127         commandstr += m_scriptCommands[i].name.upper()+(i != m_scriptCommands.no() - 1? ", " : "");
1128     }
1129     return commandstr;
1130 }
1131 
availableScriptCommands(const FXString & script)1132 FXString dxutils::availableScriptCommands(const FXString& script)
1133 {
1134     FXbool result = FALSE;
1135     FXString commandstr = _("Script commands: ");
1136     for(FXint i=m_scriptCommands.no()-1; i>-1; i--)
1137     {
1138         if(comparecase(script, m_scriptCommands[i].script) == 0)
1139         {
1140             if(result) commandstr += ", ";
1141             commandstr += m_scriptCommands[i].name.upper();
1142             result = TRUE;
1143         }
1144     }
1145     if(result) return commandstr;
1146     else return _("Script hasn't commands");
1147 }
1148 
getHelpText(const FXString & command)1149 FXString dxutils::getHelpText(const FXString &command)
1150 {
1151     for(FXint i=0; i<m_scriptCommands.no(); i++)
1152     {
1153         if(comparecase(command, m_scriptCommands[i].name) == 0) return m_scriptCommands[i].helptext;
1154     }
1155     return FXStringFormat(_("Command %s doesn't exists"), command.text());
1156 }
1157 
getFuncname(const FXString & command)1158 FXString dxutils::getFuncname(const FXString &command)
1159 {
1160     for(FXint i=0; i<m_scriptCommands.no(); i++)
1161     {
1162         if(comparecase(command, m_scriptCommands[i].name) == 0) return m_scriptCommands[i].funcname;
1163     }
1164     return FXStringFormat(_("Command %s doesn't exists"), command.text());
1165 }
1166 
getScriptName(const FXString & command)1167 FXString dxutils::getScriptName(const FXString &command)
1168 {
1169     for(FXint i=0; i<m_scriptCommands.no(); i++)
1170     {
1171         if(comparecase(command, m_scriptCommands[i].name) == 0) return m_scriptCommands[i].script;
1172     }
1173     return FXStringFormat(_("Command %s doesn't exists"), command.text());
1174 }
1175 
checkThemePath(const FXString & path)1176 FXString dxutils::checkThemePath(const FXString &path)
1177 {
1178     if(path == "internal") return path;
1179     else
1180     {
1181         if(!FXPath::search(path, "irc_normal.png").empty()) return path;
1182         return "internal";
1183     }
1184 }
1185 
checkThemesList(const FXString & list)1186 FXString dxutils::checkThemesList(const FXString &list)
1187 {
1188     FXString themes;
1189     for(FXint i=0; i<list.contains(';'); i++)
1190     {
1191         if(list.before(';', i+1).rafter(';') == "internal") themes.append("internal;");
1192         if(!FXPath::search(list.before(';', i+1).rafter(';'), "irc_normal.png").empty()) themes.append(list.before(';', i+1).rafter(';')+";");
1193     }
1194     if(!themes.empty()) return themes;
1195     return FXString("internal;");
1196 }
1197 
encrypt(const FXString & text)1198 FXString dxutils::encrypt(const FXString &text)
1199 {
1200     FXString result = "";
1201     const std::string CHARACTERS = "0123456789!@#$%^&*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1202     std::random_device random_device;
1203     std::mt19937 generator(random_device());
1204     std::uniform_int_distribution<> distribution(0, CHARACTERS.size() - 1);
1205     for(FXint i=0; i<text.count(); i++)
1206     {
1207         result += text[i];
1208         result += CHARACTERS[distribution(generator)];
1209     }
1210     return result;
1211 }
1212 
decrypt(const FXString & text)1213 FXString dxutils::decrypt(const FXString &text)
1214 {
1215     FXString result = "";
1216     for(FXint i=0; i<text.count(); i++)
1217     {
1218         if((i+1)%2) result += text[i];
1219     }
1220     return result;
1221 }
1222 
getStringIniEntry(const FXchar * section,const FXchar * key,const FXchar * def)1223 FXString dxutils::getStringIniEntry(const FXchar *section,const FXchar *key,const FXchar *def)
1224 {
1225     FXSettings set;
1226     set.parseFile(m_iniFile.empty()?getIniFile():m_iniFile, TRUE);
1227     return set.readStringEntry(section, key, def);
1228 }
1229 
getIntIniEntry(const FXchar * section,const FXchar * key,FXint def)1230 FXint dxutils::getIntIniEntry(const FXchar* section, const FXchar* key, FXint def)
1231 {
1232     FXSettings set;
1233     set.parseFile(m_iniFile.empty()?getIniFile():m_iniFile, TRUE);
1234     return set.readIntEntry(section, key, def);
1235 }
1236 
1237 //return bool entry in inifile
getBoolIniEntry(const FXchar * section,const FXchar * key,FXbool def)1238 FXbool dxutils::getBoolIniEntry(const FXchar* section, const FXchar* key, FXbool def)
1239 {
1240     FXSettings set;
1241     set.parseFile(m_iniFile.empty()?getIniFile():m_iniFile, TRUE);
1242     return set.readBoolEntry(section, key, def);
1243 }
1244 
1245 // return color entry in inifile
getColorIniEntry(const FXchar * section,const FXchar * key,FXColor def)1246 FXColor dxutils::getColorIniEntry(const FXchar* section, const FXchar* key, FXColor def)
1247 {
1248     FXSettings set;
1249     set.parseFile(m_iniFile.empty()?getIniFile():m_iniFile, TRUE);
1250     return set.readColorEntry(section, key, def);
1251 }
1252 
1253 //Return file size in human readable form
getFileSize(FXlong size)1254 FXString dxutils::getFileSize(FXlong size)
1255 {
1256     FXfloat fsize = 0.0;
1257     if(size > 1000000000)
1258     {
1259         fsize = size/1073741824.0;
1260         return FXStringFormat("%.2f %s", fsize, _("GB"));
1261     }
1262     if(size > 100000)
1263     {
1264         fsize = size/1048576.0;
1265         return FXStringFormat("%.2f %s", fsize, _("MB"));
1266     }
1267     if(size > 1000)
1268     {
1269         fsize = size/1024.0;
1270         return FXStringFormat("%.2f %s", fsize, _("KB"));
1271     }
1272     return FXStringFormat("%s %s", FXStringVal(size).text(), _("bytes"));
1273 }
1274 
1275 //Return file size in human readable form
getFileSize(const FXString & ssize)1276 FXString dxutils::getFileSize(const FXString &ssize)
1277 {
1278     return getFileSize(FXLongVal(ssize));
1279 }
1280 
1281 /*Return download/send speed in human readable form
1282  * speed = difference between two position during 1 second
1283  */
getSpeed(FXlong speed)1284 FXString dxutils::getSpeed(FXlong speed)
1285 {
1286     FXfloat fspeed = 0.0;
1287     if(speed > 100000)
1288     {
1289         fspeed = speed/(1048576.0);
1290         return FXStringFormat("%.2f %s", fspeed, _("MB/s"));
1291     }
1292     fspeed = speed/(1024.0);
1293     return FXStringFormat("%.2f %s", fspeed, _("KB/s"));
1294 }
1295 
1296 //Return remaining time of download/send
getRemaining(FXlong size,FXlong speed)1297 FXString dxutils::getRemaining(FXlong size, FXlong speed)
1298 {
1299     if(!speed) return "?";
1300     FXlong remainingTime = size/speed;
1301     if(remainingTime <= 0 || remainingTime > 54000) return "?";
1302     else
1303     {
1304         int secs = remainingTime;
1305         int hours = remainingTime/3600;
1306         secs -= hours*3600;
1307         int mins = secs/60;
1308         secs -= mins*60;
1309         return FXStringFormat("%d:%02d:%02d", hours, mins, secs);
1310     }
1311 }
1312 
1313 //Return position in file in percent string
getPercentPosition(FXlong size,FXlong position)1314 FXString dxutils::getPercentPosition(FXlong size, FXlong position)
1315 {
1316     if(!size) return "0%";
1317     return FXStringFormat("%ld%%", (100*position)/size);
1318 }
1319 
1320 // launch link in browser
launchLink(const FXString & link)1321 FXint dxutils::launchLink(const FXString &link)
1322 {
1323 #ifdef WIN32
1324     return ((FXlong)ShellExecuteA(NULL,"open",link.text(),NULL,NULL,SW_SHOWNORMAL)) > 32;
1325 #else
1326     static const char * browsers[]={"xdg-open","firefox","iceweasel","konqueror","opera","netscape","dillo","open",NULL};
1327     FXString path = FXSystem::getExecPath();
1328     FXString exec;
1329     for(int i=0; browsers[i]!=NULL; i++)
1330     {
1331         exec = FXPath::search(path, browsers[i]);
1332         if(!exec.empty()) break;
1333     }
1334     if(exec.empty()) return 0;
1335     exec += " "+FXPath::enquote(link)+" &";
1336     system(exec.text());
1337     return 1;
1338 #endif
1339 }
1340 
1341 //play event sound
playFile(const FXString & file)1342 void dxutils::playFile(const FXString &file)
1343 {
1344     if(!FXStat::exists(file))
1345         return;
1346 #ifdef WIN32
1347     PlaySoundA((LPCSTR)file.text(), NULL, SND_FILENAME | SND_ASYNC);
1348 #else
1349     static const char * players[]={"aplay","play","esdplay","artsplay","ossplay",NULL};
1350     FXString path = FXSystem::getExecPath();
1351     FXString exec;
1352     for(int i=0; players[i]!=NULL; i++)
1353     {
1354         exec = FXPath::search(path, players[i]);
1355         if(!exec.empty()) break;
1356     }
1357     if(exec.empty()) return;
1358     if(exec.contains("aplay")) exec += " -q";
1359     exec += " "+FXPath::enquote(file)+" &";
1360     system(exec.text());
1361 #endif
1362 }
1363 
1364 //write debugline
debugLine(const FXString & line)1365 void dxutils::debugLine(const FXString &line)
1366 {
1367 #ifdef DEBUG
1368     fxmessage("[%s] %s\n", FXSystem::time("%H:%M:%S", FXSystem::now()).text(), line.text());
1369 #endif
1370 }
1371 
1372 //true if word right
1373 #ifdef HAVE_ENCHANT
checkWord(FXString word,FXString lang)1374 FXbool dxutils::checkWord(FXString word, FXString lang)
1375 {
1376     Checkers::const_iterator it = m_checkers.find(lang);
1377     if(it != m_checkers.end())
1378         return (*it).second->check(word.text());
1379     return TRUE;
1380 }
1381 #else
checkWord(FXString,FXString)1382 FXbool dxutils::checkWord(FXString, FXString)
1383 {
1384     return TRUE;
1385 }
1386 #endif
1387 
1388 //fill available langs
1389 #ifdef HAVE_ENCHANT
loadAvailableSpellLangs()1390 void dxutils::loadAvailableSpellLangs()
1391 {
1392     CheckerPair chpair(&m_checkers, &m_availableSpellLangs);
1393     ebroker->list_dicts(enumerateDicts, &chpair);
1394     if(m_availableSpellLangs.no())
1395     {
1396         FXString v;
1397         FXint i,j,h;
1398         for(h=1; h<=m_availableSpellLangs.no()/9; h=3*h+1);
1399         for(; h > 0; h /= 3)
1400         {
1401             for(i = h + 1; i <= m_availableSpellLangs.no(); i++)
1402             {
1403                 v = m_availableSpellLangs[i - 1];
1404                 j = i;
1405                 while (j > h && comparecase(m_availableSpellLangs[j - h - 1], v) > 0)
1406                 {
1407                     m_availableSpellLangs[j - 1] = m_availableSpellLangs[j - h - 1];
1408                     j -= h;
1409                 }
1410                 m_availableSpellLangs[j - 1] = v;
1411             }
1412         }
1413     }
1414     for(FXint i=0; i<m_availableSpellLangs.no(); i++)
1415     {
1416         if(m_checkers.find(m_availableSpellLangs[i]) != m_checkers.end())
1417             return;
1418         try
1419         {
1420             m_checkers[m_availableSpellLangs[i]] = ebroker->request_dict(m_availableSpellLangs[i].text());
1421         }
1422         catch(enchant::Exception &/*e*/)
1423         {
1424         }
1425     }
1426 }
1427 #else
loadAvailableSpellLangs()1428 void dxutils::loadAvailableSpellLangs()
1429 {
1430     m_availableSpellLangs.no(0);
1431 }
1432 #endif
1433 
1434 //get number of spellchecking language
1435 #ifdef HAVE_ENCHANT
getAvailableSpellLangsNum()1436 FXint dxutils::getAvailableSpellLangsNum()
1437 {
1438     return m_availableSpellLangs.no();
1439 }
1440 #else
getAvailableSpellLangsNum()1441 FXint dxutils::getAvailableSpellLangsNum()
1442 {
1443     return 0;
1444 }
1445 #endif
1446 
1447 //return array of spellchecking language
getAvailableSpellLangs()1448 dxStringArray dxutils::getAvailableSpellLangs()
1449 {
1450     return m_availableSpellLangs;
1451 }
1452 
1453 //get default spellchecking language
1454 #ifdef HAVE_ENCHANT
getDefaultLang()1455 FXString dxutils::getDefaultLang()
1456 {
1457     if(m_locale.empty()) getLocale();
1458     if(m_checkers.find(m_locale) != m_checkers.end())
1459         return m_locale;
1460     Checkers::const_iterator it = m_checkers.begin();
1461     FXString language = m_locale.before('_');
1462     for(; it != m_checkers.end(); it++)
1463     {
1464         if(comparecase((*it).first.before('_'),language)==0) return language;
1465     }
1466     if(m_availableSpellLangs.no()) return m_availableSpellLangs[0];
1467     else return FXString::null;
1468 }
1469 #else
getDefaultLang()1470 FXString dxutils::getDefaultLang()
1471 {
1472     if(m_locale.empty()) getLocale();
1473     return m_locale;
1474 }
1475 #endif
1476 
1477 //return locale, e.g cs_CZ etc.
getLocale()1478 FXString dxutils::getLocale()
1479 {
1480     if(!m_locale.empty())
1481         return m_locale;
1482 #ifdef WIN32
1483     LCID lcid = GetUserDefaultLCID();
1484     if(lcid!=0)
1485     {
1486         FXuint localeid = LANGIDFROMLCID(lcid);
1487         /* locale code from this page
1488          * http://msdn.microsoft.com/en-us/library/dd318693%28v=VS.85%29.aspx
1489          * not fully implemented
1490          */
1491         switch(localeid){
1492             case 0x0436: m_locale = "af_ZA";break; // Afrikaans
1493             case 0x041c: m_locale = "sq_AL";break; // Albanian
1494             case 0x0401: m_locale = "ar_SA";break; // Arabic - Saudi Arabia
1495             case 0x0801: m_locale = "ar_IQ";break; // Arabic - Iraq
1496             case 0x0c01: m_locale = "ar_EG";break; // Arabic - Egypt
1497             case 0x1001: m_locale = "ar_LY";break; // Arabic - Libya
1498             case 0x1401: m_locale = "ar_DZ";break; // Arabic - Algeria
1499             case 0x1801: m_locale = "ar_MA";break; // Arabic - Morocco
1500             case 0x1c01: m_locale = "ar_TN";break; // Arabic - Tunisia
1501             case 0x2001: m_locale = "ar_OM";break; // Arabic - Oman
1502             case 0x2401: m_locale = "ar_YE";break; // Arabic - Yemen
1503             case 0x2801: m_locale = "ar_SY";break; // Arabic - Syria
1504             case 0x2c01: m_locale = "ar_JO";break; // Arabic - Jordan
1505             case 0x3001: m_locale = "ar_LB";break; // Arabic - Lebanon
1506             case 0x3401: m_locale = "ar_KW";break; // Arabic - Kuwait
1507             case 0x3801: m_locale = "ar_AE";break; // Arabic - United Arab Emirates
1508             case 0x3c01: m_locale = "ar_BH";break; // Arabic - Bahrain
1509             case 0x4001: m_locale = "ar_QA";break; // Arabic - Qatar
1510             case 0x042b: m_locale = "hy_AM";break; // Armenian
1511             case 0x042c: m_locale = "az_AZ";break; // Azeri Latin
1512             case 0x082c: m_locale = "az_AZ";break; // Azeri - Cyrillic
1513             case 0x042d: m_locale = "eu_ES";break; // Basque
1514             case 0x0423: m_locale = "be_BY";break; // Belarusian
1515             case 0x0445: m_locale = "bn_IN";break; // Begali
1516             case 0x201a: m_locale = "bs_BA";break; // Bosnian
1517             case 0x141a: m_locale = "bs_BA";break; // Bosnian - Cyrillic
1518             case 0x047e: m_locale = "br_FR";break; // Breton - France
1519             case 0x0402: m_locale = "bg_BG";break; // Bulgarian
1520             case 0x0403: m_locale = "ca_ES";break; // Catalan
1521             case 0x0004: m_locale = "zh_CHS";break; // Chinese - Simplified
1522             case 0x0404: m_locale = "zh_TW";break; // Chinese - Taiwan
1523             case 0x0804: m_locale = "zh_CN";break; // Chinese - PRC
1524             case 0x0c04: m_locale = "zh_HK";break; // Chinese - Hong Kong S.A.R.
1525             case 0x1004: m_locale = "zh_SG";break; // Chinese - Singapore
1526             case 0x1404: m_locale = "zh_MO";break; // Chinese - Macao S.A.R.
1527             case 0x7c04: m_locale = "zh_CHT";break; // Chinese - Traditional
1528             case 0x041a: m_locale = "hr_HR";break; // Croatian
1529             case 0x101a: m_locale = "hr_BA";break; // Croatian - Bosnia
1530             case 0x0405: m_locale = "cs_CZ";break; // Czech
1531             case 0x0406: m_locale = "da_DK";break; // Danish
1532             case 0x048c: m_locale = "gbz_AF";break; // Dari - Afghanistan
1533             case 0x0465: m_locale = "div_MV";break; // Divehi - Maldives
1534             case 0x0413: m_locale = "nl_NL";break; // Dutch - The Netherlands
1535             case 0x0813: m_locale = "nl_BE";break; // Dutch - Belgium
1536             case 0x0409: m_locale = "en_US";break; // English - United States
1537             case 0x0809: m_locale = "en_GB";break; // English - United Kingdom
1538             case 0x0c09: m_locale = "en_AU";break; // English - Australia
1539             case 0x1009: m_locale = "en_CA";break; // English - Canada
1540             case 0x1409: m_locale = "en_NZ";break; // English - New Zealand
1541             case 0x1809: m_locale = "en_IE";break; // English - Ireland
1542             case 0x1c09: m_locale = "en_ZA";break; // English - South Africa
1543             case 0x2009: m_locale = "en_JA";break; // English - Jamaica
1544             case 0x2409: m_locale = "en_CB";break; // English - Carribbean
1545             case 0x2809: m_locale = "en_BZ";break; // English - Belize
1546             case 0x2c09: m_locale = "en_TT";break; // English - Trinidad
1547             case 0x3009: m_locale = "en_ZW";break; // English - Zimbabwe
1548             case 0x3409: m_locale = "en_PH";break; // English - Phillippines
1549             case 0x0425: m_locale = "et_EE";break; // Estonian
1550             case 0x0438: m_locale = "fo_FO";break; // Faroese
1551             case 0x0464: m_locale = "fil_PH";break; // Filipino
1552             case 0x040b: m_locale = "fi_FI";break; // Finnish
1553             case 0x040c: m_locale = "fr_FR";break; // French - France
1554             case 0x080c: m_locale = "fr_BE";break; // French - Belgium
1555             case 0x0c0c: m_locale = "fr_CA";break; // French - Canada
1556             case 0x100c: m_locale = "fr_CH";break; // French - Switzerland
1557             case 0x140c: m_locale = "fr_LU";break; // French - Luxembourg
1558             case 0x180c: m_locale = "fr_MC";break; // French - Monaco
1559             case 0x0462: m_locale = "fy_NL";break; // Frisian - Netherlands
1560             case 0x0456: m_locale = "gl_ES";break; // Galician
1561             case 0x0437: m_locale = "ka_GE";break; // Georgian
1562             case 0x0407: m_locale = "de_DE";break; // German - Germany
1563             case 0x0807: m_locale = "de_CH";break; // German - Switzerland
1564             case 0x0c07: m_locale = "de_AT";break; // German - Austria
1565             case 0x1007: m_locale = "de_LU";break; // German - Luxembourg
1566             case 0x1407: m_locale = "de_LI";break; // German - Liechtenstein
1567             case 0x0408: m_locale = "el_GR";break; // Greek
1568             case 0x0447: m_locale = "gu_IN";break; // Gujarati
1569             case 0x040d: m_locale = "he_IL";break; // Hebrew
1570             case 0x0439: m_locale = "hi_IN";break; // Hindi
1571             case 0x040e: m_locale = "hu_HU";break; // Hungarian
1572             case 0x040f: m_locale = "is_IS";break; // Icelandic
1573             case 0x0421: m_locale = "id_ID";break; // Indonesian
1574             case 0x045d: m_locale = "iu_CA";break; // Inuktitut
1575             case 0x085d: m_locale = "iu_CA";break; // Inuktitut - Latin
1576             case 0x083c: m_locale = "ga_IE";break; // Irish - Ireland
1577             case 0x0434: m_locale = "xh_ZA";break; // Xhosa - South Africa
1578             case 0x0435: m_locale = "zu_ZA";break; // Zulu
1579             case 0x0410: m_locale = "it_IT";break; // Italian - Italy
1580             case 0x0810: m_locale = "it_CH";break; // Italian - Switzerland
1581             case 0x0411: m_locale = "ja_JP";break; // Japanese
1582             case 0x044b: m_locale = "kn_IN";break; // Kannada - India
1583             case 0x043f: m_locale = "kk_KZ";break; // Kazakh
1584             case 0x0457: m_locale = "kok_IN";break; // Konkani
1585             case 0x0412: m_locale = "ko_KR";break; // Korean
1586             case 0x0440: m_locale = "ky_KG";break; // Kyrgyz
1587             case 0x0426: m_locale = "lv_LV";break; // Latvian
1588             case 0x0427: m_locale = "lt_LT";break; // Lithuanian
1589             case 0x046e: m_locale = "lb_LU";break; // Luxembourgish
1590             case 0x042f: m_locale = "mk_MK";break; // FYRO Macedonian
1591             case 0x043e: m_locale = "ms_MY";break; // Malay - Malaysia
1592             case 0x083e: m_locale = "ms_BN";break; // Malay - Brunei
1593             case 0x044c: m_locale = "ml_IN";break; // Malayalam - India
1594             case 0x043a: m_locale = "mt_MT";break; // Maltese
1595             case 0x0481: m_locale = "mi_NZ";break; // Maori
1596             case 0x047a: m_locale = "arn_CL";break; // Mapudungun
1597             case 0x044e: m_locale = "mr_IN";break; // Marathi
1598             case 0x047c: m_locale = "moh_CA";break; // Mohawk - Canada
1599             case 0x0450: m_locale = "mn_MN";break; // Mongolian
1600             case 0x0461: m_locale = "ne_NP";break; // Nepali
1601             case 0x0414: m_locale = "nb_NO";break; // Norwegian - Bokmal
1602             case 0x0814: m_locale = "nn_NO";break; // Norwegian - Nynorsk
1603             case 0x0482: m_locale = "oc_FR";break; // Occitan - France
1604             case 0x0448: m_locale = "or_IN";break; // Oriya - India
1605             case 0x0463: m_locale = "ps_AF";break; // Pashto - Afghanistan
1606             case 0x0429: m_locale = "fa_IR";break; // Persian
1607             case 0x0415: m_locale = "pl_PL";break; // Polish
1608             case 0x0416: m_locale = "pt_BR";break; // Portuguese - Brazil
1609             case 0x0816: m_locale = "pt_PT";break; // Portuguese - Portugal
1610             case 0x0446: m_locale = "pa_IN";break; // Punjabi
1611             case 0x046b: m_locale = "quz_BO";break; // Quechua (Bolivia)
1612             case 0x086b: m_locale = "quz_EC";break; // Quechua (Ecuador)
1613             case 0x0c6b: m_locale = "quz_PE";break; // Quechua (Peru)
1614             case 0x0418: m_locale = "ro_RO";break; // Romanian - Romania
1615             case 0x0417: m_locale = "rm_CH";break; // Raeto-Romanese
1616             case 0x0419: m_locale = "ru_RU";break; // Russian
1617             case 0x243b: m_locale = "smn_FI";break; // Sami Finland
1618             case 0x103b: m_locale = "smj_NO";break; // Sami Norway
1619             case 0x143b: m_locale = "smj_SE";break; // Sami Sweden
1620             case 0x043b: m_locale = "se_NO";break; // Sami Northern Norway
1621             case 0x083b: m_locale = "se_SE";break; // Sami Northern Sweden
1622             case 0x0c3b: m_locale = "se_FI";break; // Sami Northern Finland
1623             case 0x203b: m_locale = "sms_FI";break; // Sami Skolt
1624             case 0x183b: m_locale = "sma_NO";break; // Sami Southern Norway
1625             case 0x1c3b: m_locale = "sma_SE";break; // Sami Southern Sweden
1626             case 0x044f: m_locale = "sa_IN";break; // Sanskrit
1627             case 0x0c1a: m_locale = "sr_SP";break; // Serbian - Cyrillic
1628             case 0x1c1a: m_locale = "sr_BA";break; // Serbian - Bosnia Cyrillic
1629             case 0x081a: m_locale = "sr_SP";break; // Serbian - Latin
1630             case 0x181a: m_locale = "sr_BA";break; // Serbian - Bosnia Latin
1631             case 0x046c: m_locale = "ns_ZA";break; // Northern Sotho
1632             case 0x0432: m_locale = "tn_ZA";break; // Setswana - Southern Africa
1633             case 0x041b: m_locale = "sk_SK";break; // Slovak
1634             case 0x0424: m_locale = "sl_SI";break; // Slovenian
1635             case 0x040a: m_locale = "es_ES";break; // Spanish - Spain
1636             case 0x080a: m_locale = "es_MX";break; // Spanish - Mexico
1637             case 0x0c0a: m_locale = "es_ES";break; // Spanish - Spain (Modern)
1638             case 0x100a: m_locale = "es_GT";break; // Spanish - Guatemala
1639             case 0x140a: m_locale = "es_CR";break; // Spanish - Costa Rica
1640             case 0x180a: m_locale = "es_PA";break; // Spanish - Panama
1641             case 0x1c0a: m_locale = "es_DO";break; // Spanish - Dominican Republic
1642             case 0x200a: m_locale = "es_VE";break; // Spanish - Venezuela
1643             case 0x240a: m_locale = "es_CO";break; // Spanish - Colombia
1644             case 0x280a: m_locale = "es_PE";break; // Spanish - Peru
1645             case 0x2c0a: m_locale = "es_AR";break; // Spanish - Argentina
1646             case 0x300a: m_locale = "es_EC";break; // Spanish - Ecuador
1647             case 0x340a: m_locale = "es_CL";break; // Spanish - Chile
1648             case 0x380a: m_locale = "es_UR";break; // Spanish - Uruguay
1649             case 0x3c0a: m_locale = "es_PY";break; // Spanish - Paraguay
1650             case 0x400a: m_locale = "es_BO";break; // Spanish - Bolivia
1651             case 0x440a: m_locale = "es_SV";break; // Spanish - El Salvador
1652             case 0x480a: m_locale = "es_HN";break; // Spanish - Honduras
1653             case 0x4c0a: m_locale = "es_NI";break; // Spanish - Nicaragua
1654             case 0x500a: m_locale = "es_PR";break; // Spanish - Puerto Rico
1655             case 0x0441: m_locale = "sw_KE";break; // Swahili
1656             case 0x041d: m_locale = "sv_SE";break; // Swedish - Sweden
1657             case 0x081d: m_locale = "sv_FI";break; // Swedish - Finland
1658             case 0x045a: m_locale = "syr_SY";break; // Syriac
1659             case 0x0449: m_locale = "ta_IN";break; // Tamil
1660             case 0x0444: m_locale = "tt_RU";break; // Tatar
1661             case 0x044a: m_locale = "te_IN";break; // Telugu
1662             case 0x041e: m_locale = "th_TH";break; // Thai
1663             case 0x041f: m_locale = "tr_TR";break; // Turkish
1664             case 0x0422: m_locale = "uk_UA";break; // Ukrainian
1665             case 0x0420: m_locale = "ur_PK";break; // Urdu
1666             case 0x0820: m_locale = "ur_IN";break; // Urdu - India
1667             case 0x0443: m_locale = "uz_UZ";break; // Uzbek - Latin
1668             case 0x0843: m_locale = "uz_UZ";break; // Uzbek - Cyrillic
1669             case 0x042a: m_locale = "vi_VN";break; // Vietnamese
1670             case 0x0452: m_locale = "cy_GB";break; // Welsh
1671             default: m_locale = "en_US";
1672         }
1673     }
1674     else m_locale = "en_US";
1675 #else
1676     if(!(FXSystem::getEnvironment("LANG")).empty()) m_locale = FXSystem::getEnvironment("LANG");
1677     else if(!(FXSystem::getEnvironment("LC_ALL")).empty()) m_locale = FXSystem::getEnvironment("LC_ALL");
1678     else if(!(FXSystem::getEnvironment("LC_MESSAGES")).empty()) m_locale = FXSystem::getEnvironment("LC_MESSAGES");
1679     else m_locale = "en_US";
1680     if(m_locale == "C" || m_locale == "POSIX")
1681     {
1682         m_locale = "en_US";
1683     }
1684     m_locale = m_locale.before('.').before('@');
1685 #endif
1686     return m_locale;
1687 }
1688 
1689 //get spellchecking language for channel
1690 #ifdef HAVE_ENCHANT
getChannelLang(FXString channel)1691 FXString dxutils::getChannelLang(FXString channel)
1692 {
1693     if(channel.empty()) return getDefaultLang();
1694     StringIt it = preferences.m_langs.find(channel);
1695     FXString lang = "";
1696     if(it != preferences.m_langs.end())
1697         lang = (*it).second;
1698     if(m_checkers.find(lang) != m_checkers.end())
1699         return lang;
1700     else return getDefaultLang();
1701 }
1702 #else
getChannelLang(FXString)1703 FXString dxutils::getChannelLang(FXString)
1704 {
1705     return FXString::null;
1706 }
1707 #endif
1708 
sortStringArray(dxStringArray & array)1709 void dxutils::sortStringArray(dxStringArray &array)
1710 {
1711     FXString v;
1712     FXint i,j,h;
1713     for(h=1; h<=array.no()/9; h=3*h+1);
1714     for(; h > 0; h /= 3)
1715     {
1716         for(i = h + 1; i <= array.no(); i++)
1717         {
1718             v = array[i - 1];
1719             j = i;
1720             while (j > h && comparecase(array[j - h - 1], v) > 0)
1721             {
1722                 array[j - 1] = array[j - h - 1];
1723                 j -= h;
1724             }
1725             array[j - 1] = v;
1726         }
1727     }
1728 }
1729 
1730 //time stamp to human readable string
stamp2fxstring(FXString datestr,FXString timestr)1731 FXString dxutils::stamp2fxstring(FXString datestr, FXString timestr)
1732 {
1733     FXString year = datestr.section('-',0);
1734     FXString month = datestr.section('-',1);
1735     FXString day = datestr.section('-',2);
1736     struct tm timeinfo;
1737     timeinfo.tm_year = FXIntVal(year) - 1900;
1738     timeinfo.tm_mon = FXIntVal(month) - 1;
1739     timeinfo.tm_mday = FXIntVal(day);
1740     timeinfo.tm_hour = 0;
1741     timeinfo.tm_min = 0;
1742     timeinfo.tm_sec = 0;
1743     timeinfo.tm_isdst = 0;
1744     time_t local = mktime(&timeinfo);
1745     return FXSystem::time("[%x ", local)+timestr+"]";
1746 }
1747 
1748 //is file with name on path right dxirc log file?
isRightLogFile(const FXString & path,const FXString & name)1749 bool dxutils::isRightLogFile(const FXString& path, const FXString& name)
1750 {
1751     if(FXRex("^\\d\\d\\d\\d-\\d\\d-\\d\\d+$").match(name))
1752     {
1753         FXFile textfile(path,FXFile::Reading);
1754         FXint n;
1755         FXchar *txt;
1756         if(!textfile.isOpen()) return false;
1757         if(!FXMALLOC(&txt,FXchar,10)) return false;
1758         n = textfile.readBlock(txt,10);
1759         if(n<0)
1760         {
1761             FXFREE(&txt);
1762             return false;
1763         }
1764         if(FXRex("^\\[\\d\\d:\\d\\d:\\d\\d\\]+$").match(txt,10))
1765         {
1766             FXFREE(&txt);
1767             return true;
1768         }
1769         else
1770         {
1771             FXFREE(&txt);
1772             return false;
1773         }
1774     }
1775     return false;
1776 }
1777 
1778 //normalize log line
normalizeLogLine(FXString datestr,std::string line)1779 FXString dxutils::normalizeLogLine(FXString datestr, std::string line)
1780 {
1781     FXString nline = line.c_str();
1782     FXString date = stamp2fxstring(datestr, nline.before(']').after('['));
1783     nline = date+nline.after(']');
1784     return nline;
1785 }
1786 
1787 //get month string
getMonth(FXint month)1788 FXString dxutils::getMonth(FXint month)
1789 {
1790     switch(month) {
1791         case 1: return _("January");
1792         case 2: return _("February");
1793         case 3: return _("March");
1794         case 4: return _("April");
1795         case 5: return _("May");
1796         case 6: return _("June");
1797         case 7: return _("July");
1798         case 8: return _("August");
1799         case 9: return _("September");
1800         case 10: return _("October");
1801         case 11: return _("November");
1802         case 12: return _("December");
1803         default: return "Rok ma jen 12 mesicu:)";
1804     }
1805 }
1806 
1807 //get month string-number for name
getMonthNumber(const FXString & month)1808 FXString dxutils::getMonthNumber(const FXString& month)
1809 {
1810     if(month==_("January")) return "01";
1811     else if(month==_("February")) return "02";
1812     else if(month==_("March")) return "03";
1813     else if(month==_("April")) return "04";
1814     else if(month==_("May")) return "05";
1815     else if(month==_("June")) return "06";
1816     else if(month==_("July")) return "07";
1817     else if(month==_("August")) return "08";
1818     else if(month==_("September")) return "09";
1819     else if(month==_("October")) return "10";
1820     else if(month==_("November")) return "11";
1821     else if(month==_("December")) return "12";
1822     return "00";
1823 }
1824 
1825 // Get key binding string from user input
1826 // Code adapted from FXAccelTable::unparseAccel() and modified to get strings like 'Ctrl-A' instead of 'ctrl+a'
getKeybinding(FXEvent * event)1827 FXString dxutils::getKeybinding(FXEvent* event)
1828 {
1829     // Get modifiers and key
1830     FXint mods=event->state;
1831     FXint code=event->code;
1832     FXchar buffer[64];
1833     FXString s;
1834     // Handle modifier keys
1835     if(mods&CONTROLMASK)
1836         s+="Ctrl-";
1837     if(mods&ALTMASK)
1838         s+="Alt-";
1839     if(mods&SHIFTMASK)
1840         s+="Shift-";
1841     if(mods&METAMASK)
1842         s+="Meta-";
1843     // Handle some special keys
1844     switch(code)
1845     {
1846         case KEY_Home:
1847             s+="Home";
1848             break;
1849         case KEY_End:
1850             s+="End";
1851             break;
1852         case KEY_Page_Up:
1853             s+="PgUp";
1854             break;
1855         case KEY_Page_Down:
1856             s+="PgDn";
1857             break;
1858         case KEY_Left:
1859             s+="Left";
1860             break;
1861         case KEY_Right:
1862             s+="Right";
1863             break;
1864         case KEY_Up:
1865             s+="Up";
1866             break;
1867         case KEY_Down:
1868             s+="Down";
1869             break;
1870         case KEY_Insert:
1871             s+="Ins";
1872             break;
1873         case KEY_Delete:
1874             s+="Del";
1875             break;
1876         case KEY_Escape:
1877             s+="Esc";
1878             break;
1879         case KEY_Tab:
1880             s+="Tab";
1881             break;
1882         case KEY_Return:
1883             s+="Return";
1884             break;
1885         case KEY_BackSpace:
1886             s+="Back";
1887             break;
1888         case KEY_space:
1889             s+="Space";
1890             break;
1891         case KEY_F1:
1892         case KEY_F2:
1893         case KEY_F3:
1894         case KEY_F4:
1895         case KEY_F5:
1896         case KEY_F6:
1897         case KEY_F7:
1898         case KEY_F8:
1899         case KEY_F9:
1900         case KEY_F10:
1901         case KEY_F11:
1902         case KEY_F12:
1903         case KEY_F13:
1904         case KEY_F14:
1905         case KEY_F15:
1906         case KEY_F16:
1907         case KEY_F17:
1908         case KEY_F18:
1909         case KEY_F19:
1910         case KEY_F20:
1911         case KEY_F21:
1912         case KEY_F22:
1913         case KEY_F23:
1914         case KEY_F24:
1915         case KEY_F25:
1916         case KEY_F26:
1917         case KEY_F27:
1918         case KEY_F28:
1919         case KEY_F29:
1920         case KEY_F30:
1921         case KEY_F31:
1922         case KEY_F32:
1923         case KEY_F33:
1924         case KEY_F34:
1925         case KEY_F35:
1926             sprintf(buffer,"F%d",code-KEY_F1+1);
1927             s+=buffer;
1928             break;
1929         default:
1930         if(Ascii::isPrint(code))
1931             s+=Ascii::toUpper(code);
1932         else
1933             s="";  // Invalid case
1934         break;
1935     }
1936     return s;
1937 }
1938 
1939 // Parse accelerator from string
parseAccel(const FXString & string)1940 FXHotKey dxutils::parseAccel(const FXString& string)
1941 {
1942     FXuint code=0,mods=0;
1943     FXint pos=0;
1944     // Parse leading space
1945     while(pos<string.length() && Ascii::isSpace(string[pos]))
1946         pos++;
1947     // Parse modifiers
1948     while(pos<string.length())
1949     {
1950         // Modifier
1951         if(comparecase(&string[pos],"ctl",3)==0)
1952         {
1953             mods|=CONTROLMASK;
1954             pos+=3;
1955         }
1956         else if(comparecase(&string[pos],"ctrl",4)==0)
1957         {
1958             mods|=CONTROLMASK;
1959             pos+=4;
1960         }
1961         else if(comparecase(&string[pos],"alt",3)==0)
1962         {
1963             mods|=ALTMASK;
1964             pos+=3;
1965         }
1966         else if(comparecase(&string[pos],"meta",4)==0)
1967         {
1968             mods|=METAMASK;
1969             pos+=4;
1970         }
1971         else if(comparecase(&string[pos],"shift",5)==0)
1972         {
1973             mods|=SHIFTMASK;
1974             pos+=5;
1975         }
1976         else
1977             break;
1978         // Separator
1979         if(string[pos]=='+' || string[pos]=='-' || Ascii::isSpace(string[pos]))
1980             pos++;
1981     }
1982     // Test for some special keys
1983     if(comparecase(&string[pos],"home",4)==0)
1984         code=KEY_Home;
1985     else if(comparecase(&string[pos],"end",3)==0)
1986         code=KEY_End;
1987     else if(comparecase(&string[pos],"pgup",4)==0)
1988         code=KEY_Page_Up;
1989     else if(comparecase(&string[pos],"pgdn",4)==0)
1990         code=KEY_Page_Down;
1991     else if(comparecase(&string[pos],"left",4)==0)
1992         code=KEY_Left;
1993     else if(comparecase(&string[pos],"right",5)==0)
1994         code=KEY_Right;
1995     else if(comparecase(&string[pos],"up",2)==0)
1996         code=KEY_Up;
1997     else if(comparecase(&string[pos],"down",4)==0)
1998         code=KEY_Down;
1999     else if(comparecase(&string[pos],"ins",3)==0)
2000         code=KEY_Insert;
2001     else if(comparecase(&string[pos],"del",3)==0)
2002         code=KEY_Delete;
2003     else if(comparecase(&string[pos],"esc",3)==0)
2004         code=KEY_Escape;
2005     else if(comparecase(&string[pos],"tab",3)==0)
2006         code=KEY_Tab;
2007     else if(comparecase(&string[pos],"return",6)==0)
2008         code=KEY_Return;
2009     else if(comparecase(&string[pos],"enter",5)==0)
2010         code=KEY_Return;
2011     else if(comparecase(&string[pos],"back",4)==0)
2012         code=KEY_BackSpace;
2013     else if(comparecase(&string[pos],"spc",3)==0)
2014         code=KEY_space;
2015     else if(comparecase(&string[pos],"space",5)==0)
2016         code=KEY_space;
2017     // Test for function keys
2018     else if(Ascii::toLower(string[pos])=='f' && Ascii::isDigit(string[pos+1]))
2019     {
2020         if(Ascii::isDigit(string[pos+2]))
2021         {
2022             code=KEY_F1+10*(string[pos+1]-'0')+(string[pos+2]-'0')-1;
2023         }
2024         else
2025             code=KEY_F1+string[pos+1]-'1';
2026     }
2027     // Test if hexadecimal code designator
2028     else if(string[pos]=='#')
2029         code=strtoul(&string[pos+1],NULL,16);
2030     // Test if its a single character accelerator
2031     else if(Ascii::isPrint(string[pos]))
2032     {
2033         if(mods&SHIFTMASK)
2034             code=Ascii::toUpper(string[pos])+KEY_space-' ';
2035         else
2036             code=Ascii::toLower(string[pos])+KEY_space-' ';
2037     }
2038     return MKUINT(code,mods);
2039 }
2040 
2041 //Remove ircmark from text
stripColors(const FXString & text,const FXbool stripOther)2042 FXString dxutils::stripColors(const FXString &text, const FXbool stripOther)
2043 {
2044     FXString newstr;
2045     FXbool color = FALSE;
2046     FXint numbers = 0;
2047     FXint i = 0;
2048     while(text[i] != '\0') {
2049         if(text[i] == '\017') //reset
2050         {
2051             color = FALSE;
2052         }
2053         else if(stripOther && text[i] == '\002')
2054         {
2055             //remove bold mark
2056         }
2057         else if(stripOther && text[i] == '\037')
2058         {
2059             //remove underline mark
2060         }
2061         else if(text[i] == '\035')
2062         {
2063             //remove italic mark
2064         }
2065         else if(text[i] == '\021')
2066         {
2067             //remove fixed mark
2068         }
2069         else if(text[i] == '\026')
2070         {
2071             //remove reverse mark
2072         }
2073         else if(text[i] == '\003') //color
2074         {
2075             color = TRUE;
2076         }
2077         else if(text[i] == '\004') //hex color
2078         {
2079             color = TRUE;
2080         }
2081         else if(color && isdigit(text[i]) && numbers < 2)
2082         {
2083             numbers++;
2084         }
2085         else if(color && text[i] == ',' && numbers < 3)
2086         {
2087             numbers = 0;
2088         }
2089         else
2090         {
2091             numbers = 0;
2092             color = FALSE;
2093             newstr += text[i];
2094         }
2095         i++;
2096     }
2097     return newstr;
2098 }
2099 
2100 //Return color for ircolor code
getIrcColor(FXint code,bool foreground)2101 FXColor dxutils::getIrcColor(FXint code, bool foreground)
2102 {
2103     switch(code){
2104         case 0:
2105             return fxcolorfromname("white");
2106         case 1:
2107             return fxcolorfromname("black");
2108         case 2:
2109             return FXRGB(0,0,128); //blue
2110         case 3:
2111             return FXRGB(0,128,0); //green
2112         case 4:
2113             return FXRGB(255,0,0); //lightred
2114         case 5:
2115             return FXRGB(128,0,64); //brown
2116         case 6:
2117             return FXRGB(128,0,128); //purple
2118         case 7:
2119             return FXRGB(255,128,64); //orange
2120         case 8:
2121             return FXRGB(255,255,0); //yellow
2122         case 9:
2123             return FXRGB(128,255,0); //lightgreen
2124         case 10:
2125             return FXRGB(0,128,128); //cyan
2126         case 11:
2127             return FXRGB(0,255,255); //lightcyan
2128         case 12:
2129             return FXRGB(0,0,255); //lightblue
2130         case 13:
2131             return FXRGB(255,0,255); //pink
2132         case 14:
2133             return FXRGB(128,128,128); //grey
2134         case 15:
2135             return FXRGB(192,192,192); //lightgrey
2136         case 16:
2137             return fxcolorfromname("#470000");
2138         case 17:
2139             return fxcolorfromname("#472100");
2140         case 18:
2141             return fxcolorfromname("#474700");
2142         case 19:
2143             return fxcolorfromname("#324700");
2144         case 20:
2145             return fxcolorfromname("#004700");
2146         case 21:
2147             return fxcolorfromname("#00472c");
2148         case 22:
2149             return fxcolorfromname("#004747");
2150         case 23:
2151             return fxcolorfromname("#002747");
2152         case 24:
2153             return fxcolorfromname("#000047");
2154         case 25:
2155             return fxcolorfromname("#2e0047");
2156         case 26:
2157             return fxcolorfromname("#470047");
2158         case 27:
2159             return fxcolorfromname("#47002a");
2160         case 28:
2161             return fxcolorfromname("#740000");
2162         case 29:
2163             return fxcolorfromname("#743a00");
2164         case 30:
2165             return fxcolorfromname("#747400");
2166         case 31:
2167             return fxcolorfromname("#517400");
2168         case 32:
2169             return fxcolorfromname("#007400");
2170         case 33:
2171             return fxcolorfromname("#007449");
2172         case 34:
2173             return fxcolorfromname("#007474");
2174         case 35:
2175             return fxcolorfromname("#004074");
2176         case 36:
2177             return fxcolorfromname("#000074");
2178         case 37:
2179             return fxcolorfromname("#4b0074");
2180         case 38:
2181             return fxcolorfromname("#740074");
2182         case 39:
2183             return fxcolorfromname("#740045");
2184         case 40:
2185             return fxcolorfromname("#b50000");
2186         case 41:
2187             return fxcolorfromname("#b56300");
2188         case 42:
2189             return fxcolorfromname("#b5b500");
2190         case 43:
2191             return fxcolorfromname("#7db500");
2192         case 44:
2193             return fxcolorfromname("#00b500");
2194         case 45:
2195             return fxcolorfromname("#00b571");
2196         case 46:
2197             return fxcolorfromname("#00b5b5");
2198         case 47:
2199             return fxcolorfromname("#0063b5");
2200         case 48:
2201             return fxcolorfromname("#0000b5");
2202         case 49:
2203             return fxcolorfromname("#7500b5");
2204         case 50:
2205             return fxcolorfromname("#b500b5");
2206         case 51:
2207             return fxcolorfromname("#b5006b");
2208         case 52:
2209             return fxcolorfromname("#ff0000");
2210         case 53:
2211             return fxcolorfromname("#ff8c00");
2212         case 54:
2213             return fxcolorfromname("#ffff00");
2214         case 55:
2215             return fxcolorfromname("#b2ff00");
2216         case 56:
2217             return fxcolorfromname("#00ff00");
2218         case 57:
2219             return fxcolorfromname("#00ffa0");
2220         case 58:
2221             return fxcolorfromname("#00ffff");
2222         case 59:
2223             return fxcolorfromname("#008cff");
2224         case 60:
2225             return fxcolorfromname("#0000ff");
2226         case 61:
2227             return fxcolorfromname("#a500ff");
2228         case 62:
2229             return fxcolorfromname("#ff00ff");
2230         case 63:
2231             return fxcolorfromname("#ff0098");
2232         case 64:
2233             return fxcolorfromname("#ff5959");
2234         case 65:
2235             return fxcolorfromname("#ffb459");
2236         case 66:
2237             return fxcolorfromname("#ffff71");
2238         case 67:
2239             return fxcolorfromname("#cfff60");
2240         case 68:
2241             return fxcolorfromname("#6fff6f");
2242         case 69:
2243             return fxcolorfromname("#65ffc9");
2244         case 70:
2245             return fxcolorfromname("#6dffff");
2246         case 71:
2247             return fxcolorfromname("#59b4ff");
2248         case 72:
2249             return fxcolorfromname("#5959ff");
2250         case 73:
2251             return fxcolorfromname("#c459ff");
2252         case 74:
2253             return fxcolorfromname("#ff66ff");
2254         case 75:
2255             return fxcolorfromname("#ff59bc");
2256         case 76:
2257             return fxcolorfromname("#ff9c9c");
2258         case 77:
2259             return fxcolorfromname("#ffd39c");
2260         case 78:
2261             return fxcolorfromname("#ffff9c");
2262         case 79:
2263             return fxcolorfromname("#e2ff9c");
2264         case 80:
2265             return fxcolorfromname("#9cff9c");
2266         case 81:
2267             return fxcolorfromname("#9cffdb");
2268         case 82:
2269             return fxcolorfromname("#9cffff");
2270         case 83:
2271             return fxcolorfromname("#9cd3ff");
2272         case 84:
2273             return fxcolorfromname("#9c9cff");
2274         case 85:
2275             return fxcolorfromname("#dc9cff");
2276         case 86:
2277             return fxcolorfromname("#ff9cff");
2278         case 87:
2279             return fxcolorfromname("#ff94d3");
2280         case 88:
2281             return fxcolorfromname("#000000");
2282         case 89:
2283             return fxcolorfromname("#131313");
2284         case 90:
2285             return fxcolorfromname("#282828");
2286         case 91:
2287             return fxcolorfromname("#363636");
2288         case 92:
2289             return fxcolorfromname("#4d4d4d");
2290         case 93:
2291             return fxcolorfromname("#656565");
2292         case 94:
2293             return fxcolorfromname("#818181");
2294         case 95:
2295             return fxcolorfromname("#9f9f9f");
2296         case 96:
2297             return fxcolorfromname("#bcbcbc");
2298         case 97:
2299             return fxcolorfromname("#e2e2e2");
2300         case 98:
2301             return fxcolorfromname("#ffffff");
2302         default:
2303             return foreground?preferences.m_colors.text:preferences.m_colors.back;
2304     }
2305 }
2306 
2307 //Remove ircmark from text
stripLogMark(const FXString & text)2308 FXString dxutils::stripLogMark(const FXString &text)
2309 {
2310     FXString newstr;
2311     FXbool mark = FALSE;
2312     FXint numbers = 0;
2313     FXint i = 0;
2314     while(text[i] != '\0') {
2315         if(text[i] == '\014') //log mark
2316         {
2317             if(!mark) mark = TRUE; //first mark
2318             else mark = FALSE; //last mark
2319         }
2320         else if(mark && isdigit(text[i]) && numbers < 2)
2321         {
2322             numbers++;
2323         }
2324         else
2325         {
2326             numbers = 0;
2327             mark = FALSE;
2328             newstr += text[i];
2329         }
2330         i++;
2331     }
2332     return newstr;
2333 }
2334 
haveNotify()2335 bool dxutils::haveNotify()
2336 {
2337     return m_haveNotify;
2338 }
2339 
2340