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