]> git.saurik.com Git - wxWidgets.git/blob - src/common/utilscmn.cpp
Dialog unit mods; wxProp tidying
[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(const wxString& buf)
244 {
245 int firstDigit, secondDigit;
246
247 if (buf.GetChar(0) >= 'A')
248 firstDigit = buf.GetChar(0) - 'A' + 10;
249 else
250 firstDigit = buf.GetChar(0) - '0';
251
252 if (buf.GetChar(1) >= 'A')
253 secondDigit = buf.GetChar(1) - 'A' + 10;
254 else
255 secondDigit = buf.GetChar(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 // Convert decimal integer to 2-character hex string
271 wxString wxDecToHex(int dec)
272 {
273 char buf[3];
274 wxDecToHex(dec, buf);
275 return wxString(buf);
276 }
277
278 // Match a string INDEPENDENT OF CASE
279 bool
280 StringMatch (char *str1, char *str2, bool subString, bool exact)
281 {
282 if (str1 == NULL || str2 == NULL)
283 return FALSE;
284 if (str1 == str2)
285 return TRUE;
286
287 if (subString)
288 {
289 int len1 = strlen (str1);
290 int len2 = strlen (str2);
291 int i;
292
293 // Search for str1 in str2
294 // Slow .... but acceptable for short strings
295 for (i = 0; i <= len2 - len1; i++)
296 {
297 if (strncasecmp (str1, str2 + i, len1) == 0)
298 return TRUE;
299 }
300 }
301 else if (exact)
302 {
303 if (strcasecmp (str1, str2) == 0)
304 return TRUE;
305 }
306 else
307 {
308 int len1 = strlen (str1);
309 int len2 = strlen (str2);
310
311 if (strncasecmp (str1, str2, wxMin (len1, len2)) == 0)
312 return TRUE;
313 }
314
315 return FALSE;
316 }
317
318 // Return the current date/time
319 // [volatile]
320 wxString wxNow( void )
321 {
322 time_t now = time((time_t *) NULL);
323 char *date = ctime(&now);
324 date[24] = '\0';
325 return wxString(date);
326 }
327
328 /* Get Full RFC822 style email address */
329 bool
330 wxGetEmailAddress (char *address, int maxSize)
331 {
332 char host[65];
333 char user[65];
334
335 if (wxGetHostName(host, 64) == FALSE)
336 return FALSE;
337 if (wxGetUserId(user, 64) == FALSE)
338 return FALSE;
339
340 char tmp[130];
341 strcpy(tmp, user);
342 strcat(tmp, "@");
343 strcat(tmp, host);
344
345 strncpy(address, tmp, maxSize - 1);
346 address[maxSize-1] = '\0';
347 return TRUE;
348 }
349
350 /*
351 * Strip out any menu codes
352 */
353
354 char *wxStripMenuCodes (char *in, char *out)
355 {
356 if (!in)
357 return (char *) NULL;
358
359 if (!out)
360 out = copystring(in);
361
362 char *tmpOut = out;
363
364 while (*in)
365 {
366 if (*in == '&')
367 {
368 // Check && -> &, &x -> x
369 if (*++in == '&')
370 *out++ = *in++;
371 }
372 else if (*in == '\t')
373 {
374 // Remove all stuff after \t in X mode, and let the stuff as is
375 // in Windows mode.
376 // Accelerators are handled in wx_item.cc for Motif, and are not
377 // YET supported in XView
378 break;
379 }
380 else
381 *out++ = *in++;
382 } // while
383
384 *out = '\0';
385
386 return tmpOut;
387 }
388
389
390 /*
391 * Window search functions
392 *
393 */
394
395 /*
396 * If parent is non-NULL, look through children for a label or title
397 * matching the specified string. If NULL, look through all top-level windows.
398 *
399 */
400
401 static wxWindow *wxFindWindowByLabel1 (const wxString& title, wxWindow * parent);
402
403 wxWindow *
404 wxFindWindowByLabel (const wxString& title, wxWindow * parent)
405 {
406 if (parent)
407 {
408 return wxFindWindowByLabel1 (title, parent);
409 }
410 else
411 {
412 for (wxNode * node = wxTopLevelWindows.First (); node; node = node->Next ())
413 {
414 wxWindow *win = (wxWindow *) node->Data ();
415 wxWindow *retwin = wxFindWindowByLabel1 (title, win);
416 if (retwin)
417 return retwin;
418 } // for()
419
420 }
421 return (wxWindow *) NULL;
422 }
423
424 // Recursive
425 static wxWindow *
426 wxFindWindowByLabel1 (const wxString& title, wxWindow * parent)
427 {
428 if (parent)
429 {
430 if (parent->GetLabel() == title)
431 return parent;
432 }
433
434 if (parent)
435 {
436 for (wxNode * node = parent->GetChildren()->First (); node; node = node->Next ())
437 {
438 wxWindow *win = (wxWindow *) node->Data ();
439 wxWindow *retwin = wxFindWindowByLabel1 (title, win);
440 if (retwin)
441 return retwin;
442 } // for()
443
444 }
445
446 return (wxWindow *) NULL; // Not found
447
448 }
449
450 /*
451 * If parent is non-NULL, look through children for a name
452 * matching the specified string. If NULL, look through all top-level windows.
453 *
454 */
455
456 static wxWindow *wxFindWindowByName1 (const wxString& title, wxWindow * parent);
457
458 wxWindow *
459 wxFindWindowByName (const wxString& title, wxWindow * parent)
460 {
461 if (parent)
462 {
463 return wxFindWindowByName1 (title, parent);
464 }
465 else
466 {
467 for (wxNode * node = wxTopLevelWindows.First (); node; node = node->Next ())
468 {
469 wxWindow *win = (wxWindow *) node->Data ();
470 wxWindow *retwin = wxFindWindowByName1 (title, win);
471 if (retwin)
472 return retwin;
473 } // for()
474
475 }
476 // Failed? Try by label instead.
477 return wxFindWindowByLabel(title, parent);
478 }
479
480 // Recursive
481 static wxWindow *
482 wxFindWindowByName1 (const wxString& title, wxWindow * parent)
483 {
484 if (parent)
485 {
486 if ( parent->GetName() == title )
487 return parent;
488 }
489
490 if (parent)
491 {
492 for (wxNode * node = parent->GetChildren()->First (); node; node = node->Next ())
493 {
494 wxWindow *win = (wxWindow *) node->Data ();
495 wxWindow *retwin = wxFindWindowByName1 (title, win);
496 if (retwin)
497 return retwin;
498 } // for()
499
500 }
501
502 return (wxWindow *) NULL; // Not found
503
504 }
505
506 // Returns menu item id or -1 if none.
507 int
508 wxFindMenuItemId (wxFrame * frame, const wxString& menuString, const wxString& itemString)
509 {
510 wxMenuBar *menuBar = frame->GetMenuBar ();
511 if (!menuBar)
512 return -1;
513 return menuBar->FindMenuItem (menuString, itemString);
514 }
515
516 /*
517 * wxDebugStreamBuf
518 */
519 #if !defined(_WINDLL)
520
521 wxDebugStreamBuf::wxDebugStreamBuf(void)
522 {
523 if (allocate()) setp(base(),ebuf());
524 }
525
526 int wxDebugStreamBuf::overflow(int WXUNUSED(i))
527 {
528 int len = pptr() - pbase();
529 char *txt = new char[len+1];
530 strncpy(txt, pbase(), len);
531 txt[len] = '\0';
532 #ifdef __WXMSW__
533 OutputDebugString((LPCSTR)txt);
534 #else
535 fprintf(stderr, txt);
536 #endif
537 setp(pbase(), epptr());
538 delete[] txt;
539 return EOF;
540 }
541
542 int wxDebugStreamBuf::sync(void)
543 {
544 int len = pptr() - pbase();
545 char *txt = new char[len+1];
546 strncpy(txt, pbase(), len);
547 txt[len] = '\0';
548 #ifdef __WXMSW__
549 OutputDebugString((LPCSTR)txt);
550 #else
551 fprintf(stderr, txt);
552 #endif
553 setp(pbase(), epptr());
554 delete[] txt;
555 return 0;
556 }
557
558 #endif
559
560 /*
561 On Fri, 21 Jul 1995, Paul Craven wrote:
562
563 > Is there a way to find the path of running program's executable? I can get
564 > my home directory, and the current directory, but I don't know how to get the
565 > executable directory.
566 >
567
568 The code below (warty as it is), does what you want on most Unix,
569 DOS, and Mac platforms (it's from the ALS Prolog main).
570
571 || Ken Bowen Applied Logic Systems, Inc. PO Box 180,
572 ||==== Voice: +1 (617)965-9191 Newton Centre,
573 || FAX: +1 (617)965-1636 MA 02159 USA
574 Email: ken@als.com WWW: http://www.als.com
575 ------------------------------------------------------------------------
576 */
577
578 // This code is commented out but it may be integrated with wxWin at
579 // a later date, after testing. Thanks Ken!
580 #if 0
581
582 /*--------------------------------------------------------------------*
583 | whereami is given a filename f in the form: whereami(argv[0])
584 | It returns the directory in which the executable file (containing
585 | this code [main.c] ) may be found. A dot will be returned to indicate
586 | the current directory.
587 *--------------------------------------------------------------------*/
588
589 static void
590 whereami(name)
591 char *name;
592 {
593 register char *cutoff = NULL; /* stifle -Wall */
594 register char *s;
595 register char *t;
596 int cc;
597 char ebuf[4096];
598
599 /*
600 * See if the file is accessible either through the current directory
601 * or through an absolute path.
602 */
603
604 if (access(name, R_OK) == 0) {
605
606 /*-------------------------------------------------------------*
607 * The file was accessible without any other work. But the current
608 * working directory might change on us, so if it was accessible
609 * through the cwd, then we should get it for later accesses.
610 *-------------------------------------------------------------*/
611
612 t = imagedir;
613 if (!absolute_pathname(name)) {
614 #if defined(DOS) || defined(__WIN32__)
615 int drive;
616 char *newrbuf;
617
618 newrbuf = imagedir;
619 #ifndef __DJGPP__
620 if (*(name + 1) == ':') {
621 if (*name >= 'a' && *name <= 'z')
622 drive = (int) (*name - 'a' + 1);
623 else
624 drive = (int) (*name - 'A' + 1);
625 *newrbuf++ = *name;
626 *newrbuf++ = *(name + 1);
627 *newrbuf++ = DIR_SEPARATOR;
628 }
629 else {
630 drive = 0;
631 *newrbuf++ = DIR_SEPARATOR;
632 }
633 if (getcwd(newrbuf, drive) == 0) { /* } */
634 #else
635 if (getcwd(newrbuf, 1024) == 0) { /* } */
636 #endif
637 #else /* DOS */
638 #ifdef HAVE_GETWD
639 if (getwd(imagedir) == 0) { /* } */
640 #else /* !HAVE_GETWD */
641 if (getcwd(imagedir, 1024) == 0) {
642 #endif /* !HAVE_GETWD */
643 #endif /* DOS */
644 fatal_error(FE_GETCWD, 0);
645 }
646 for (; *t; t++) /* Set t to end of buffer */
647 ;
648 if (*(t - 1) == DIR_SEPARATOR) /* leave slash if already
649 * last char
650 */
651 cutoff = t - 1;
652 else {
653 cutoff = t; /* otherwise put one in */
654 *t++ = DIR_SEPARATOR;
655 }
656 }
657 #if (!defined(__MAC__) && !defined(__DJGPP__) && !defined(__GO32__) && !defined(__WIN32__))
658 else
659 (*t++ = DIR_SEPARATOR);
660 #endif
661
662 /*-------------------------------------------------------------*
663 * Copy the rest of the string and set the cutoff if it was not
664 * already set. If the first character of name is a slash, cutoff
665 * is not presently set but will be on the first iteration of the
666 * loop below.
667 *-------------------------------------------------------------*/
668
669 for ((*name == DIR_SEPARATOR ? (s = name+1) : (s = name));;) {
670 if (*s == DIR_SEPARATOR)
671 cutoff = t;
672 if (!(*t++ = *s++))
673 break;
674 }
675
676 }
677 else {
678
679 /*-------------------------------------------------------------*
680 * Get the path list from the environment. If the path list is
681 * inaccessible for any reason, leave with fatal error.
682 *-------------------------------------------------------------*/
683
684 #ifdef __MAC__
685 if ((s = getenv("Commands")) == (char *) 0)
686 #else
687 if ((s = getenv("PATH")) == (char *) 0)
688 #endif
689 fatal_error(FE_PATH, 0);
690
691 /*
692 * Copy path list into ebuf and set the source pointer to the
693 * beginning of this buffer.
694 */
695
696 strcpy(ebuf, s);
697 s = ebuf;
698
699 for (;;) {
700 t = imagedir;
701 while (*s && *s != PATH_SEPARATOR)
702 *t++ = *s++;
703 if (t > imagedir && *(t - 1) == DIR_SEPARATOR)
704 ; /* do nothing -- slash already is in place */
705 else
706 *t++ = DIR_SEPARATOR; /* put in the slash */
707 cutoff = t - 1; /* set cutoff */
708 strcpy(t, name);
709 if (access(imagedir, R_OK) == 0)
710 break;
711
712 if (*s)
713 s++; /* advance source pointer */
714 else
715 fatal_error(FE_INFND, 0);
716 }
717
718 }
719
720 /*-------------------------------------------------------------*
721 | At this point the full pathname should exist in imagedir and
722 | cutoff should be set to the final slash. We must now determine
723 | whether the file name is a symbolic link or not and chase it down
724 | if it is. Note that we reuse ebuf for getting the link.
725 *-------------------------------------------------------------*/
726
727 #ifdef HAVE_SYMLINK
728 while ((cc = readlink(imagedir, ebuf, 512)) != -1) {
729 ebuf[cc] = 0;
730 s = ebuf;
731 if (*s == DIR_SEPARATOR) {
732 t = imagedir;
733 }
734 else {
735 t = cutoff + 1;
736 }
737 for (;;) {
738 if (*s == DIR_SEPARATOR)
739 cutoff = t; /* mark the last slash seen */
740 if (!(*t++ = *s++)) /* copy the character */
741 break;
742 }
743 }
744
745 #endif /* HAVE_SYMLINK */
746
747 strcpy(imagename, cutoff + 1); /* keep the image name */
748 *(cutoff + 1) = 0; /* chop off the filename part */
749 }
750
751 #endif
752
753 /*
754 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
755 * since otherwise the generic code may be pulled in unnecessarily.
756 */
757
758 int wxMessageBox(const wxString& message, const wxString& caption, long style,
759 wxWindow *parent, int WXUNUSED(x), int WXUNUSED(y) )
760 {
761 wxMessageDialog dialog(parent, message, caption, style);
762
763 int ans = dialog.ShowModal();
764 switch ( ans )
765 {
766 case wxID_OK:
767 return wxOK;
768 break;
769 case wxID_YES:
770 return wxYES;
771 break;
772 case wxID_NO:
773 return wxNO;
774 break;
775 default:
776 case wxID_CANCEL:
777 return wxCANCEL;
778 break;
779 }
780 return ans;
781 }
782
783 wxString wxGetTextFromUser(const wxString& message, const wxString& caption,
784 const wxString& defaultValue, wxWindow *parent,
785 int x, int y, bool WXUNUSED(centre) )
786 {
787 wxTextEntryDialog dialog(parent, message, caption, defaultValue, wxOK|wxCANCEL, wxPoint(x, y));
788 if (dialog.ShowModal() == wxID_OK)
789 return dialog.GetValue();
790 else
791 return wxString("");
792 }
793