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