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