]> git.saurik.com Git - wxWidgets.git/blame - src/common/utilscmn.cpp
Added (untested) support for sub-locales.
[wxWidgets.git] / src / common / utilscmn.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: utilscmn.cpp
3// Purpose: Miscellaneous utility functions and classes
4// Author: Julian Smart
5// Modified by:
6// Created: 29/01/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Julian Smart
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
7007fcfc 13#pragma implementation "utils.h"
c801d85f
KB
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include "wx/defs.h"
25#include "wx/utils.h"
26#include "wx/window.h"
27#include "wx/menu.h"
28#include "wx/frame.h"
dfad0599
JS
29#include "wx/msgdlg.h"
30#include "wx/textdlg.h"
c801d85f
KB
31#endif
32
47d67540 33#if wxUSE_IOSTREAMH
c801d85f 34#include <iostream.h>
fbc535ff 35#include <fstream.h>
c801d85f
KB
36#else
37#include <iostream>
fbc535ff
JS
38#include <fstream>
39# ifdef _MSC_VER
40 using namespace std;
41# endif
c801d85f
KB
42#endif
43
c801d85f
KB
44#include <ctype.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#if !defined(__WATCOMC__)
49#if !(defined(_MSC_VER) && (_MSC_VER > 800))
50#include <errno.h>
51#endif
52#endif
53#include <time.h>
469e1e5c 54#ifndef __MWERKS__
c801d85f
KB
55#include <sys/types.h>
56#include <sys/stat.h>
469e1e5c 57#endif
c801d85f 58
ce3ed50d
JS
59#ifdef __SALFORDC__
60#include <clib.h>
61#endif
62
c801d85f
KB
63// Pattern matching code.
64// Yes, this path is deliberate (for Borland compilation)
65#ifdef wx_mac /* MATTHEW: [5] Mac doesn't like paths with "/" */
66#include "glob.inc"
67#else
68#include "../common/glob.inc"
69#endif
70
2049ba38 71#ifdef __WXMSW__
c801d85f
KB
72#include "windows.h"
73#endif
74
75#define _MAXPATHLEN 500
76
77extern char *wxBuffer;
78
17dff81c
SC
79#ifdef __WXMAC__
80int strcasecmp(const char *str_1, const char *str_2)
81{
82 register char c1, c2;
83 do {
84 c1 = tolower(*str_1++);
85 c2 = tolower(*str_2++);
86 } while ( c1 && (c1 == c2) );
87
88 return c1 - c2;
89}
90
91int strncasecmp(const char *str_1, const char *str_2, size_t maxchar)
92{
93
94 register char c1, c2;
95 while( maxchar--)
96 {
97 c1 = tolower(*str_1++);
98 c2 = tolower(*str_2++);
99
100 if ( !c1 || c1!=c2 )
101 return c1 - c2;
102
103 } ;
104
105 return 0 ;
106
107}
108#endif
c801d85f
KB
109#ifdef __VMS__
110// we have no strI functions under VMS, therefore I have implemented
111// an inefficient but portable version: convert copies of strings to lowercase
112// and then use the normal comparison
113static void myLowerString(char *s)
114{
115 while(*s){
116 if(isalpha(*s)) *s = (char)tolower(*s);
117 s++;
118 }
119}
120
121int strcasecmp(const char *str_1, const char *str_2)
122{
123 char *temp1 = new char[strlen(str_1)+1];
124 char *temp2 = new char[strlen(str_2)+1];
125 strcpy(temp1,str_1);
126 strcpy(temp2,str_2);
127 myLowerString(temp1);
128 myLowerString(temp2);
129
130 int result = strcmp(temp1,temp2);
131 delete[] temp1;
132 delete[] temp2;
133
134 return(result);
135}
136
137int strncasecmp(const char *str_1, const char *str_2, size_t maxchar)
138{
139 char *temp1 = new char[strlen(str_1)+1];
140 char *temp2 = new char[strlen(str_2)+1];
141 strcpy(temp1,str_1);
142 strcpy(temp2,str_2);
143 myLowerString(temp1);
144 myLowerString(temp2);
145
146 int result = strncmp(temp1,temp2,maxchar);
147 delete[] temp1;
148 delete[] temp2;
149
150 return(result);
151}
152#endif
153
34138703 154#ifdef __WINDOWS__
c801d85f
KB
155
156#ifndef __GNUWIN32__
469e1e5c 157#ifndef __MWERKS__
c801d85f
KB
158#define strcasecmp stricmp
159#define strncasecmp strnicmp
469e1e5c
SC
160#else
161#define strcasecmp _stricmp
162#define strncasecmp _strnicmp
163#endif
c801d85f
KB
164#endif
165
166#ifdef _MSC_VER
167#pragma warning (disable : 4245)
168#endif
169
170#ifdef _MSC_VER
171#pragma warning (default : 4245)
172#endif
173
174#else
175// This declaration is missing in SunOS!
176// (Yes, I know it is NOT ANSI-C but its in BSD libc)
177#if defined(__xlC) || defined(__AIX__) || defined(__GNUG__)
178extern "C"
179{
180 int strcasecmp (const char *, const char *);
181 int strncasecmp (const char *, const char *, size_t);
182}
183#endif
2049ba38 184#endif /* __WXMSW__ */
c801d85f
KB
185
186
187char *
188copystring (const char *s)
189{
190 if (s == NULL) s = "";
191 size_t len = strlen (s) + 1;
192
193 char *news = new char[len];
194 memcpy (news, s, len); // Should be the fastest
195
196 return news;
197}
198
199// Id generation
200static long wxCurrentId = 100;
201
202long
203wxNewId (void)
204{
205 return wxCurrentId++;
206}
207
208long
209wxGetCurrentId(void) { return wxCurrentId; }
210
211void
212wxRegisterId (long id)
213{
214 if (id >= wxCurrentId)
215 wxCurrentId = id + 1;
216}
217
218void
219StringToFloat (char *s, float *number)
220{
221 if (s && *s && number)
c67daf87 222 *number = (float) strtod (s, (char **) NULL);
c801d85f
KB
223}
224
225void
226StringToDouble (char *s, double *number)
227{
228 if (s && *s && number)
c67daf87 229 *number = strtod (s, (char **) NULL);
c801d85f
KB
230}
231
232char *
233FloatToString (float number, const char *fmt)
234{
235 static char buf[256];
236
237// sprintf (buf, "%.2f", number);
238 sprintf (buf, fmt, number);
239 return buf;
240}
241
242char *
243DoubleToString (double number, const char *fmt)
244{
245 static char buf[256];
246
247 sprintf (buf, fmt, number);
248 return buf;
249}
250
251void
252StringToInt (char *s, int *number)
253{
254 if (s && *s && number)
c67daf87 255 *number = (int) strtol (s, (char **) NULL, 10);
c801d85f
KB
256}
257
258void
259StringToLong (char *s, long *number)
260{
261 if (s && *s && number)
c67daf87 262 *number = strtol (s, (char **) NULL, 10);
c801d85f
KB
263}
264
265char *
266IntToString (int number)
267{
268 static char buf[20];
269
270 sprintf (buf, "%d", number);
271 return buf;
272}
273
274char *
275LongToString (long number)
276{
277 static char buf[20];
278
279 sprintf (buf, "%ld", number);
280 return buf;
281}
282
283// Array used in DecToHex conversion routine.
284static char hexArray[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
285 'C', 'D', 'E', 'F' };
286
287// Convert 2-digit hex number to decimal
fd71308f 288int wxHexToDec(const wxString& buf)
c801d85f
KB
289{
290 int firstDigit, secondDigit;
291
fd71308f
JS
292 if (buf.GetChar(0) >= 'A')
293 firstDigit = buf.GetChar(0) - 'A' + 10;
c801d85f 294 else
fd71308f 295 firstDigit = buf.GetChar(0) - '0';
c801d85f 296
fd71308f
JS
297 if (buf.GetChar(1) >= 'A')
298 secondDigit = buf.GetChar(1) - 'A' + 10;
c801d85f 299 else
fd71308f 300 secondDigit = buf.GetChar(1) - '0';
c801d85f
KB
301
302 return firstDigit * 16 + secondDigit;
303}
304
305// Convert decimal integer to 2-character hex string
306void wxDecToHex(int dec, char *buf)
307{
308 int firstDigit = (int)(dec/16.0);
309 int secondDigit = (int)(dec - (firstDigit*16.0));
310 buf[0] = hexArray[firstDigit];
311 buf[1] = hexArray[secondDigit];
312 buf[2] = 0;
313}
314
fd71308f
JS
315// Convert decimal integer to 2-character hex string
316wxString wxDecToHex(int dec)
317{
318 char buf[3];
319 wxDecToHex(dec, buf);
320 return wxString(buf);
321}
322
c801d85f
KB
323// Match a string INDEPENDENT OF CASE
324bool
325StringMatch (char *str1, char *str2, bool subString, bool exact)
326{
327 if (str1 == NULL || str2 == NULL)
328 return FALSE;
329 if (str1 == str2)
330 return TRUE;
331
332 if (subString)
333 {
334 int len1 = strlen (str1);
335 int len2 = strlen (str2);
336 int i;
337
338 // Search for str1 in str2
339 // Slow .... but acceptable for short strings
340 for (i = 0; i <= len2 - len1; i++)
341 {
342 if (strncasecmp (str1, str2 + i, len1) == 0)
343 return TRUE;
344 }
345 }
346 else if (exact)
347 {
348 if (strcasecmp (str1, str2) == 0)
349 return TRUE;
350 }
351 else
352 {
353 int len1 = strlen (str1);
354 int len2 = strlen (str2);
355
356 if (strncasecmp (str1, str2, wxMin (len1, len2)) == 0)
357 return TRUE;
358 }
359
360 return FALSE;
361}
362
363// Return the current date/time
364// [volatile]
365wxString wxNow( void )
366{
c67daf87 367 time_t now = time((time_t *) NULL);
c801d85f
KB
368 char *date = ctime(&now);
369 date[24] = '\0';
370 return wxString(date);
371}
372
373/* Get Full RFC822 style email address */
374bool
375wxGetEmailAddress (char *address, int maxSize)
376{
377 char host[65];
378 char user[65];
379
380 if (wxGetHostName(host, 64) == FALSE)
381 return FALSE;
382 if (wxGetUserId(user, 64) == FALSE)
383 return FALSE;
384
385 char tmp[130];
386 strcpy(tmp, user);
387 strcat(tmp, "@");
388 strcat(tmp, host);
389
390 strncpy(address, tmp, maxSize - 1);
391 address[maxSize-1] = '\0';
392 return TRUE;
393}
394
395/*
396 * Strip out any menu codes
397 */
398
399char *wxStripMenuCodes (char *in, char *out)
400{
401 if (!in)
c67daf87 402 return (char *) NULL;
c801d85f
KB
403
404 if (!out)
405 out = copystring(in);
406
407 char *tmpOut = out;
408
409 while (*in)
410 {
411 if (*in == '&')
412 {
413 // Check && -> &, &x -> x
414 if (*++in == '&')
415 *out++ = *in++;
416 }
417 else if (*in == '\t')
418 {
419 // Remove all stuff after \t in X mode, and let the stuff as is
420 // in Windows mode.
421 // Accelerators are handled in wx_item.cc for Motif, and are not
422 // YET supported in XView
423 break;
424 }
425 else
426 *out++ = *in++;
427 } // while
428
429 *out = '\0';
430
431 return tmpOut;
432}
433
47bc1060
JS
434wxString wxStripMenuCodes(const wxString& str)
435{
436 char *buf = new char[str.Length() + 1];
437 wxStripMenuCodes((char*) (const char*) str, buf);
438 wxString str1(buf);
439 delete[] buf;
440 return str1;
441}
c801d85f
KB
442
443/*
444 * Window search functions
445 *
446 */
447
448/*
449 * If parent is non-NULL, look through children for a label or title
450 * matching the specified string. If NULL, look through all top-level windows.
451 *
452 */
453
454static wxWindow *wxFindWindowByLabel1 (const wxString& title, wxWindow * parent);
455
456wxWindow *
457wxFindWindowByLabel (const wxString& title, wxWindow * parent)
458{
459 if (parent)
460 {
461 return wxFindWindowByLabel1 (title, parent);
462 }
463 else
464 {
465 for (wxNode * node = wxTopLevelWindows.First (); node; node = node->Next ())
466 {
467 wxWindow *win = (wxWindow *) node->Data ();
468 wxWindow *retwin = wxFindWindowByLabel1 (title, win);
469 if (retwin)
470 return retwin;
471 } // for()
472
473 }
c67daf87 474 return (wxWindow *) NULL;
c801d85f
KB
475}
476
477// Recursive
478static wxWindow *
479wxFindWindowByLabel1 (const wxString& title, wxWindow * parent)
480{
481 if (parent)
482 {
483 if (parent->GetLabel() == title)
484 return parent;
485 }
486
487 if (parent)
488 {
c0ed460c 489 for (wxNode * node = parent->GetChildren().First (); node; node = node->Next ())
c801d85f
KB
490 {
491 wxWindow *win = (wxWindow *) node->Data ();
492 wxWindow *retwin = wxFindWindowByLabel1 (title, win);
493 if (retwin)
494 return retwin;
495 } // for()
496
497 }
498
c67daf87 499 return (wxWindow *) NULL; // Not found
c801d85f
KB
500
501}
502
503/*
504 * If parent is non-NULL, look through children for a name
505 * matching the specified string. If NULL, look through all top-level windows.
506 *
507 */
508
509static wxWindow *wxFindWindowByName1 (const wxString& title, wxWindow * parent);
510
511wxWindow *
512wxFindWindowByName (const wxString& title, wxWindow * parent)
513{
514 if (parent)
515 {
516 return wxFindWindowByName1 (title, parent);
517 }
518 else
519 {
520 for (wxNode * node = wxTopLevelWindows.First (); node; node = node->Next ())
521 {
522 wxWindow *win = (wxWindow *) node->Data ();
523 wxWindow *retwin = wxFindWindowByName1 (title, win);
524 if (retwin)
525 return retwin;
526 } // for()
527
528 }
529 // Failed? Try by label instead.
530 return wxFindWindowByLabel(title, parent);
531}
532
533// Recursive
534static wxWindow *
535wxFindWindowByName1 (const wxString& title, wxWindow * parent)
536{
537 if (parent)
538 {
539 if ( parent->GetName() == title )
540 return parent;
541 }
542
543 if (parent)
544 {
c0ed460c 545 for (wxNode * node = parent->GetChildren().First (); node; node = node->Next ())
c801d85f
KB
546 {
547 wxWindow *win = (wxWindow *) node->Data ();
548 wxWindow *retwin = wxFindWindowByName1 (title, win);
549 if (retwin)
550 return retwin;
551 } // for()
552
553 }
554
c67daf87 555 return (wxWindow *) NULL; // Not found
c801d85f
KB
556
557}
558
559// Returns menu item id or -1 if none.
560int
561wxFindMenuItemId (wxFrame * frame, const wxString& menuString, const wxString& itemString)
562{
563 wxMenuBar *menuBar = frame->GetMenuBar ();
564 if (!menuBar)
565 return -1;
566 return menuBar->FindMenuItem (menuString, itemString);
567}
568
c801d85f
KB
569/*
570On Fri, 21 Jul 1995, Paul Craven wrote:
571
572> Is there a way to find the path of running program's executable? I can get
573> my home directory, and the current directory, but I don't know how to get the
574> executable directory.
575>
576
577The code below (warty as it is), does what you want on most Unix,
578DOS, and Mac platforms (it's from the ALS Prolog main).
579
580|| Ken Bowen Applied Logic Systems, Inc. PO Box 180,
581||==== Voice: +1 (617)965-9191 Newton Centre,
582|| FAX: +1 (617)965-1636 MA 02159 USA
583 Email: ken@als.com WWW: http://www.als.com
584------------------------------------------------------------------------
585*/
586
587// This code is commented out but it may be integrated with wxWin at
588// a later date, after testing. Thanks Ken!
589#if 0
590
591/*--------------------------------------------------------------------*
592 | whereami is given a filename f in the form: whereami(argv[0])
593 | It returns the directory in which the executable file (containing
594 | this code [main.c] ) may be found. A dot will be returned to indicate
595 | the current directory.
596 *--------------------------------------------------------------------*/
597
598static void
599whereami(name)
600 char *name;
601{
602 register char *cutoff = NULL; /* stifle -Wall */
603 register char *s;
604 register char *t;
605 int cc;
606 char ebuf[4096];
607
608 /*
609 * See if the file is accessible either through the current directory
610 * or through an absolute path.
611 */
612
613 if (access(name, R_OK) == 0) {
614
615 /*-------------------------------------------------------------*
616 * The file was accessible without any other work. But the current
617 * working directory might change on us, so if it was accessible
618 * through the cwd, then we should get it for later accesses.
619 *-------------------------------------------------------------*/
620
621 t = imagedir;
622 if (!absolute_pathname(name)) {
623#if defined(DOS) || defined(__WIN32__)
624 int drive;
625 char *newrbuf;
626
627 newrbuf = imagedir;
628#ifndef __DJGPP__
629 if (*(name + 1) == ':') {
630 if (*name >= 'a' && *name <= 'z')
631 drive = (int) (*name - 'a' + 1);
632 else
633 drive = (int) (*name - 'A' + 1);
634 *newrbuf++ = *name;
635 *newrbuf++ = *(name + 1);
636 *newrbuf++ = DIR_SEPARATOR;
637 }
638 else {
639 drive = 0;
640 *newrbuf++ = DIR_SEPARATOR;
641 }
642 if (getcwd(newrbuf, drive) == 0) { /* } */
643#else
644 if (getcwd(newrbuf, 1024) == 0) { /* } */
645#endif
646#else /* DOS */
647#ifdef HAVE_GETWD
648 if (getwd(imagedir) == 0) { /* } */
649#else /* !HAVE_GETWD */
650 if (getcwd(imagedir, 1024) == 0) {
651#endif /* !HAVE_GETWD */
652#endif /* DOS */
653 fatal_error(FE_GETCWD, 0);
654 }
655 for (; *t; t++) /* Set t to end of buffer */
656 ;
657 if (*(t - 1) == DIR_SEPARATOR) /* leave slash if already
658 * last char
659 */
660 cutoff = t - 1;
661 else {
662 cutoff = t; /* otherwise put one in */
663 *t++ = DIR_SEPARATOR;
664 }
665 }
666#if (!defined(__MAC__) && !defined(__DJGPP__) && !defined(__GO32__) && !defined(__WIN32__))
667 else
668 (*t++ = DIR_SEPARATOR);
669#endif
670
671 /*-------------------------------------------------------------*
672 * Copy the rest of the string and set the cutoff if it was not
673 * already set. If the first character of name is a slash, cutoff
674 * is not presently set but will be on the first iteration of the
675 * loop below.
676 *-------------------------------------------------------------*/
677
678 for ((*name == DIR_SEPARATOR ? (s = name+1) : (s = name));;) {
679 if (*s == DIR_SEPARATOR)
680 cutoff = t;
681 if (!(*t++ = *s++))
682 break;
683 }
684
685 }
686 else {
687
688 /*-------------------------------------------------------------*
689 * Get the path list from the environment. If the path list is
690 * inaccessible for any reason, leave with fatal error.
691 *-------------------------------------------------------------*/
692
693#ifdef __MAC__
694 if ((s = getenv("Commands")) == (char *) 0)
695#else
696 if ((s = getenv("PATH")) == (char *) 0)
697#endif
698 fatal_error(FE_PATH, 0);
699
700 /*
701 * Copy path list into ebuf and set the source pointer to the
702 * beginning of this buffer.
703 */
704
705 strcpy(ebuf, s);
706 s = ebuf;
707
708 for (;;) {
709 t = imagedir;
710 while (*s && *s != PATH_SEPARATOR)
711 *t++ = *s++;
712 if (t > imagedir && *(t - 1) == DIR_SEPARATOR)
713 ; /* do nothing -- slash already is in place */
714 else
715 *t++ = DIR_SEPARATOR; /* put in the slash */
716 cutoff = t - 1; /* set cutoff */
717 strcpy(t, name);
718 if (access(imagedir, R_OK) == 0)
719 break;
720
721 if (*s)
722 s++; /* advance source pointer */
723 else
724 fatal_error(FE_INFND, 0);
725 }
726
727 }
728
729 /*-------------------------------------------------------------*
730 | At this point the full pathname should exist in imagedir and
731 | cutoff should be set to the final slash. We must now determine
732 | whether the file name is a symbolic link or not and chase it down
733 | if it is. Note that we reuse ebuf for getting the link.
734 *-------------------------------------------------------------*/
735
736#ifdef HAVE_SYMLINK
737 while ((cc = readlink(imagedir, ebuf, 512)) != -1) {
738 ebuf[cc] = 0;
739 s = ebuf;
740 if (*s == DIR_SEPARATOR) {
741 t = imagedir;
742 }
743 else {
744 t = cutoff + 1;
745 }
746 for (;;) {
747 if (*s == DIR_SEPARATOR)
748 cutoff = t; /* mark the last slash seen */
749 if (!(*t++ = *s++)) /* copy the character */
750 break;
751 }
752 }
753
754#endif /* HAVE_SYMLINK */
755
756 strcpy(imagename, cutoff + 1); /* keep the image name */
757 *(cutoff + 1) = 0; /* chop off the filename part */
758}
759
760#endif
761
dfad0599
JS
762/*
763 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
764 * since otherwise the generic code may be pulled in unnecessarily.
765 */
766
767int wxMessageBox(const wxString& message, const wxString& caption, long style,
768 wxWindow *parent, int WXUNUSED(x), int WXUNUSED(y) )
769{
770 wxMessageDialog dialog(parent, message, caption, style);
771
772 int ans = dialog.ShowModal();
773 switch ( ans )
774 {
775 case wxID_OK:
776 return wxOK;
777 break;
778 case wxID_YES:
779 return wxYES;
780 break;
781 case wxID_NO:
782 return wxNO;
783 break;
784 default:
785 case wxID_CANCEL:
786 return wxCANCEL;
787 break;
788 }
789 return ans;
790}
791
792wxString wxGetTextFromUser(const wxString& message, const wxString& caption,
793 const wxString& defaultValue, wxWindow *parent,
794 int x, int y, bool WXUNUSED(centre) )
795{
796 wxTextEntryDialog dialog(parent, message, caption, defaultValue, wxOK|wxCANCEL, wxPoint(x, y));
797 if (dialog.ShowModal() == wxID_OK)
798 return dialog.GetValue();
799 else
800 return wxString("");
801}
802
469e1e5c
SC
803#ifdef __MWERKS__
804char *strdup(const char *s)
805{
806 return strcpy( (char*) malloc( strlen( s ) + 1 ) , s ) ;
807}
808
809int isascii( int c )
810{
811 return ( c >= 0 && c < 128 ) ;
812}
f60d0f94 813#endif
e2a6f233
JS
814
815// Overloaded functions, taking a wxString
816bool wxGetHostName(wxString& name)
817{
818 bool success = wxGetHostName(wxBuffer, 500);
819 if (success)
820 {
821 name = wxBuffer;
822 return TRUE;
823 }
824 else
825 return FALSE;
826}
827
828bool wxGetUserId(wxString& buf)
829{
830 bool success = wxGetUserId(wxBuffer, 500);
831 if (success)
832 {
833 buf = wxBuffer;
834 return TRUE;
835 }
836 else
837 return FALSE;
838}
839
840bool wxGetUserName(wxString& buf)
841{
842 bool success = wxGetUserName(wxBuffer, 500);
843 if (success)
844 {
845 buf = wxBuffer;
846 return TRUE;
847 }
848 else
849 return FALSE;
850}
851