]> git.saurik.com Git - wxWidgets.git/blob - src/common/utilscmn.cpp
wxString::Right() changed to AfterLast() (config works again)
[wxWidgets.git] / src / common / utilscmn.cpp
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__
13 #pragma implementation "utils.h"
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"
29 #include "wx/msgdlg.h"
30 #include "wx/textdlg.h"
31 #endif
32
33 #if wxUSE_IOSTREAMH
34 #include <iostream.h>
35 #include <fstream.h>
36 #else
37 #include <iostream>
38 #include <fstream>
39 # ifdef _MSC_VER
40 using namespace std;
41 # endif
42 #endif
43
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>
54 #ifndef __MWERKS__
55 #include <sys/types.h>
56 #include <sys/stat.h>
57 #endif
58
59 #ifdef __SALFORDC__
60 #include <clib.h>
61 #endif
62
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
71 #ifdef __WXMSW__
72 #include "windows.h"
73 #endif
74
75 #define _MAXPATHLEN 500
76
77 extern char *wxBuffer;
78
79 #ifdef __WXMAC__
80 int 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
91 int 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
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
113 static void myLowerString(char *s)
114 {
115 while(*s){
116 if(isalpha(*s)) *s = (char)tolower(*s);
117 s++;
118 }
119 }
120
121 int 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
137 int 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
154 #ifdef __WINDOWS__
155
156 #ifndef __GNUWIN32__
157 #ifndef __MWERKS__
158 #define strcasecmp stricmp
159 #define strncasecmp strnicmp
160 #else
161 #define strcasecmp _stricmp
162 #define strncasecmp _strnicmp
163 #endif
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__)
178 extern "C"
179 {
180 int strcasecmp (const char *, const char *);
181 int strncasecmp (const char *, const char *, size_t);
182 }
183 #endif
184 #endif /* __WXMSW__ */
185
186
187 char *
188 copystring (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
200 static long wxCurrentId = 100;
201
202 long
203 wxNewId (void)
204 {
205 return wxCurrentId++;
206 }
207
208 long
209 wxGetCurrentId(void) { return wxCurrentId; }
210
211 void
212 wxRegisterId (long id)
213 {
214 if (id >= wxCurrentId)
215 wxCurrentId = id + 1;
216 }
217
218 void
219 StringToFloat (char *s, float *number)
220 {
221 if (s && *s && number)
222 *number = (float) strtod (s, (char **) NULL);
223 }
224
225 void
226 StringToDouble (char *s, double *number)
227 {
228 if (s && *s && number)
229 *number = strtod (s, (char **) NULL);
230 }
231
232 char *
233 FloatToString (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
242 char *
243 DoubleToString (double number, const char *fmt)
244 {
245 static char buf[256];
246
247 sprintf (buf, fmt, number);
248 return buf;
249 }
250
251 void
252 StringToInt (char *s, int *number)
253 {
254 if (s && *s && number)
255 *number = (int) strtol (s, (char **) NULL, 10);
256 }
257
258 void
259 StringToLong (char *s, long *number)
260 {
261 if (s && *s && number)
262 *number = strtol (s, (char **) NULL, 10);
263 }
264
265 char *
266 IntToString (int number)
267 {
268 static char buf[20];
269
270 sprintf (buf, "%d", number);
271 return buf;
272 }
273
274 char *
275 LongToString (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.
284 static 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
288 int wxHexToDec(const wxString& buf)
289 {
290 int firstDigit, secondDigit;
291
292 if (buf.GetChar(0) >= 'A')
293 firstDigit = buf.GetChar(0) - 'A' + 10;
294 else
295 firstDigit = buf.GetChar(0) - '0';
296
297 if (buf.GetChar(1) >= 'A')
298 secondDigit = buf.GetChar(1) - 'A' + 10;
299 else
300 secondDigit = buf.GetChar(1) - '0';
301
302 return firstDigit * 16 + secondDigit;
303 }
304
305 // Convert decimal integer to 2-character hex string
306 void 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
315 // Convert decimal integer to 2-character hex string
316 wxString wxDecToHex(int dec)
317 {
318 char buf[3];
319 wxDecToHex(dec, buf);
320 return wxString(buf);
321 }
322
323 // Match a string INDEPENDENT OF CASE
324 bool
325 StringMatch (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]
365 wxString wxNow( void )
366 {
367 time_t now = time((time_t *) NULL);
368 char *date = ctime(&now);
369 date[24] = '\0';
370 return wxString(date);
371 }
372
373 /* Get Full RFC822 style email address */
374 bool
375 wxGetEmailAddress (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
399 char *wxStripMenuCodes (char *in, char *out)
400 {
401 if (!in)
402 return (char *) NULL;
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
434 wxString 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 }
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
454 static wxWindow *wxFindWindowByLabel1 (const wxString& title, wxWindow * parent);
455
456 wxWindow *
457 wxFindWindowByLabel (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 }
474 return (wxWindow *) NULL;
475 }
476
477 // Recursive
478 static wxWindow *
479 wxFindWindowByLabel1 (const wxString& title, wxWindow * parent)
480 {
481 if (parent)
482 {
483 if (parent->GetLabel() == title)
484 return parent;
485 }
486
487 if (parent)
488 {
489 for (wxNode * node = parent->GetChildren().First (); node; node = node->Next ())
490 {
491 wxWindow *win = (wxWindow *) node->Data ();
492 wxWindow *retwin = wxFindWindowByLabel1 (title, win);
493 if (retwin)
494 return retwin;
495 } // for()
496
497 }
498
499 return (wxWindow *) NULL; // Not found
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
509 static wxWindow *wxFindWindowByName1 (const wxString& title, wxWindow * parent);
510
511 wxWindow *
512 wxFindWindowByName (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
534 static wxWindow *
535 wxFindWindowByName1 (const wxString& title, wxWindow * parent)
536 {
537 if (parent)
538 {
539 if ( parent->GetName() == title )
540 return parent;
541 }
542
543 if (parent)
544 {
545 for (wxNode * node = parent->GetChildren().First (); node; node = node->Next ())
546 {
547 wxWindow *win = (wxWindow *) node->Data ();
548 wxWindow *retwin = wxFindWindowByName1 (title, win);
549 if (retwin)
550 return retwin;
551 } // for()
552
553 }
554
555 return (wxWindow *) NULL; // Not found
556
557 }
558
559 // Returns menu item id or -1 if none.
560 int
561 wxFindMenuItemId (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
569 /*
570 On 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
577 The code below (warty as it is), does what you want on most Unix,
578 DOS, 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
598 static void
599 whereami(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
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
767 int 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
792 wxString 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
803 #ifdef __MWERKS__
804 char *strdup(const char *s)
805 {
806 return strcpy( (char*) malloc( strlen( s ) + 1 ) , s ) ;
807 }
808
809 int isascii( int c )
810 {
811 return ( c >= 0 && c < 128 ) ;
812 }
813 #endif