]> git.saurik.com Git - wxWidgets.git/blame - src/common/utilscmn.cpp
Window management and sizer layout corrections
[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
3f4a0c5b 9// Licence: wxWindows license
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
e90c1d2a
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
c801d85f 20#ifdef __GNUG__
e90c1d2a 21 #pragma implementation "utils.h"
c801d85f
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
e90c1d2a 28 #pragma hdrstop
c801d85f
KB
29#endif
30
31#ifndef WX_PRECOMP
e90c1d2a
VZ
32 #include "wx/defs.h"
33 #include "wx/string.h"
34 #include "wx/utils.h"
974e8d94
VZ
35 #include "wx/intl.h"
36 #include "wx/log.h"
e90c1d2a
VZ
37
38 #if wxUSE_GUI
8461e4c2 39 #include "wx/app.h"
e90c1d2a 40 #include "wx/window.h"
e90c1d2a 41 #include "wx/frame.h"
1e6feb95 42 #include "wx/menu.h"
e90c1d2a
VZ
43 #include "wx/msgdlg.h"
44 #include "wx/textdlg.h"
78bcfcfc 45 #include "wx/textctrl.h" // for wxTE_PASSWORD
974e8d94
VZ
46 #if wxUSE_ACCEL
47 #include "wx/menuitem.h"
48 #include "wx/accel.h"
49 #endif // wxUSE_ACCEL
e90c1d2a
VZ
50 #endif // wxUSE_GUI
51#endif // WX_PRECOMP
c801d85f 52
669f7a11 53#ifndef __WIN16__
cd6ce4a9
VZ
54#include "wx/process.h"
55#include "wx/txtstrm.h"
669f7a11 56#endif
cd6ce4a9 57
c801d85f
KB
58#include <ctype.h>
59#include <stdio.h>
60#include <stdlib.h>
61#include <string.h>
e90c1d2a 62
c801d85f 63#if !defined(__WATCOMC__)
3f4a0c5b
VZ
64 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
65 #include <errno.h>
66 #endif
c801d85f 67#endif
e90c1d2a 68
91b4c08d
VZ
69#if wxUSE_GUI
70 #include "wx/colordlg.h"
bf31fa26 71 #include "wx/fontdlg.h"
d1c8aaa3
JS
72 #include "wx/notebook.h"
73 #include "wx/frame.h"
74 #include "wx/statusbr.h"
75 #include "wx/toolbar.h"
91b4c08d
VZ
76#endif // wxUSE_GUI
77
c801d85f 78#include <time.h>
e90c1d2a 79
469e1e5c 80#ifndef __MWERKS__
e90c1d2a
VZ
81 #include <sys/types.h>
82 #include <sys/stat.h>
469e1e5c 83#endif
c801d85f 84
ce3ed50d 85#ifdef __SALFORDC__
e90c1d2a 86 #include <clib.h>
ce3ed50d
JS
87#endif
88
2049ba38 89#ifdef __WXMSW__
5e1febfa 90 #include "wx/msw/private.h"
c801d85f
KB
91#endif
92
73deed44
VZ
93// ----------------------------------------------------------------------------
94// common data
95// ----------------------------------------------------------------------------
96
97#if WXWIN_COMPATIBILITY_2_2
98 const wxChar *wxInternalErrorStr = wxT("wxWindows Internal Error");
99 const wxChar *wxFatalErrorStr = wxT("wxWindows Fatal Error");
100#endif // WXWIN_COMPATIBILITY_2_2
101
e90c1d2a
VZ
102// ----------------------------------------------------------------------------
103// function protoypes
104// ----------------------------------------------------------------------------
105
106#if wxUSE_GUI
107 static wxWindow *wxFindWindowByLabel1(const wxString& title, wxWindow *parent);
108 static wxWindow *wxFindWindowByName1 (const wxString& title, wxWindow *parent);
109#endif // wxUSE_GUI
c801d85f 110
e90c1d2a
VZ
111// ============================================================================
112// implementation
113// ============================================================================
c801d85f 114
e146b8c8 115// ----------------------------------------------------------------------------
e90c1d2a 116// string functions
e146b8c8
VZ
117// ----------------------------------------------------------------------------
118
5271933e 119#if defined(__WXMAC__) && !defined(__DARWIN__)
17dff81c
SC
120int strcasecmp(const char *str_1, const char *str_2)
121{
122 register char c1, c2;
123 do {
124 c1 = tolower(*str_1++);
125 c2 = tolower(*str_2++);
126 } while ( c1 && (c1 == c2) );
127
128 return c1 - c2;
129}
130
131int strncasecmp(const char *str_1, const char *str_2, size_t maxchar)
132{
133
134 register char c1, c2;
3f4a0c5b 135 while( maxchar--)
17dff81c
SC
136 {
137 c1 = tolower(*str_1++);
138 c2 = tolower(*str_2++);
3f4a0c5b 139
17dff81c 140 if ( !c1 || c1!=c2 )
3f4a0c5b
VZ
141 return c1 - c2;
142
17dff81c
SC
143 } ;
144
145 return 0 ;
146
147}
ed12f1dd 148#endif // __WXMAC__ && !__DARWIN__
e90c1d2a 149
7e72d7aa 150#if defined( __VMS__ ) && ( __VMS_VER < 70000000 )
c801d85f
KB
151// we have no strI functions under VMS, therefore I have implemented
152// an inefficient but portable version: convert copies of strings to lowercase
153// and then use the normal comparison
154static void myLowerString(char *s)
155{
156 while(*s){
157 if(isalpha(*s)) *s = (char)tolower(*s);
158 s++;
159 }
160}
161
162int strcasecmp(const char *str_1, const char *str_2)
163{
164 char *temp1 = new char[strlen(str_1)+1];
165 char *temp2 = new char[strlen(str_2)+1];
166 strcpy(temp1,str_1);
167 strcpy(temp2,str_2);
168 myLowerString(temp1);
169 myLowerString(temp2);
170
81c67e27 171 int result = wxStrcmp(temp1,temp2);
c801d85f
KB
172 delete[] temp1;
173 delete[] temp2;
174
175 return(result);
176}
177
178int strncasecmp(const char *str_1, const char *str_2, size_t maxchar)
179{
180 char *temp1 = new char[strlen(str_1)+1];
181 char *temp2 = new char[strlen(str_2)+1];
182 strcpy(temp1,str_1);
183 strcpy(temp2,str_2);
184 myLowerString(temp1);
185 myLowerString(temp2);
186
187 int result = strncmp(temp1,temp2,maxchar);
188 delete[] temp1;
189 delete[] temp2;
190
191 return(result);
192}
e90c1d2a 193#endif // __VMS__
c801d85f 194
04ef50df 195#if defined(__WINDOWS__) && !defined(__WXMICROWIN__)
c801d85f
KB
196
197#ifndef __GNUWIN32__
469e1e5c 198#ifndef __MWERKS__
c801d85f
KB
199#define strcasecmp stricmp
200#define strncasecmp strnicmp
469e1e5c
SC
201#else
202#define strcasecmp _stricmp
203#define strncasecmp _strnicmp
204#endif
c801d85f
KB
205#endif
206
c801d85f 207#else
91b8de8d
RR
208
209#ifdef __EMX__
210#define strcasecmp stricmp
211#define strncasecmp strnicmp
212#endif
213
c801d85f
KB
214// This declaration is missing in SunOS!
215// (Yes, I know it is NOT ANSI-C but its in BSD libc)
216#if defined(__xlC) || defined(__AIX__) || defined(__GNUG__)
217extern "C"
218{
219 int strcasecmp (const char *, const char *);
220 int strncasecmp (const char *, const char *, size_t);
221}
222#endif
3f4a0c5b 223#endif /* __WXMSW__ */
c801d85f 224
717b9bf2
DW
225#ifdef __WXPM__
226#define strcasecmp stricmp
227#define strncasecmp strnicmp
228#endif
c801d85f 229
36786970
VS
230#ifdef __WATCOMC__
231#define strcasecmp stricmp
232#define strncasecmp strnicmp
233#endif
234
0080691b
OK
235wxChar *
236copystring (const wxChar *s)
c801d85f 237{
223d09f6 238 if (s == NULL) s = wxT("");
0080691b 239 size_t len = wxStrlen (s) + 1;
c801d85f 240
0080691b
OK
241 wxChar *news = new wxChar[len];
242 memcpy (news, s, len * sizeof(wxChar)); // Should be the fastest
c801d85f
KB
243
244 return news;
245}
246
247// Id generation
248static long wxCurrentId = 100;
249
3f4a0c5b 250long
c801d85f
KB
251wxNewId (void)
252{
253 return wxCurrentId++;
254}
255
256long
257wxGetCurrentId(void) { return wxCurrentId; }
258
3f4a0c5b 259void
c801d85f
KB
260wxRegisterId (long id)
261{
262 if (id >= wxCurrentId)
263 wxCurrentId = id + 1;
264}
265
3f4a0c5b 266void
bc87fd68 267StringToFloat (const wxChar *s, float *number)
c801d85f
KB
268{
269 if (s && *s && number)
0080691b 270 *number = (float) wxStrtod (s, (wxChar **) NULL);
c801d85f
KB
271}
272
3f4a0c5b 273void
bc87fd68 274StringToDouble (const wxChar *s, double *number)
c801d85f
KB
275{
276 if (s && *s && number)
0080691b 277 *number = wxStrtod (s, (wxChar **) NULL);
c801d85f
KB
278}
279
0080691b
OK
280wxChar *
281FloatToString (float number, const wxChar *fmt)
c801d85f 282{
0080691b 283 static wxChar buf[256];
c801d85f 284
0080691b 285 wxSprintf (buf, fmt, number);
c801d85f
KB
286 return buf;
287}
288
0080691b
OK
289wxChar *
290DoubleToString (double number, const wxChar *fmt)
c801d85f 291{
0080691b 292 static wxChar buf[256];
c801d85f 293
0080691b 294 wxSprintf (buf, fmt, number);
c801d85f
KB
295 return buf;
296}
297
3f4a0c5b 298void
bc87fd68 299StringToInt (const wxChar *s, int *number)
c801d85f
KB
300{
301 if (s && *s && number)
0080691b 302 *number = (int) wxStrtol (s, (wxChar **) NULL, 10);
c801d85f
KB
303}
304
3f4a0c5b 305void
bc87fd68 306StringToLong (const wxChar *s, long *number)
c801d85f
KB
307{
308 if (s && *s && number)
0080691b 309 *number = wxStrtol (s, (wxChar **) NULL, 10);
c801d85f
KB
310}
311
84fff0b3 312wxChar *
c801d85f
KB
313IntToString (int number)
314{
84fff0b3 315 static wxChar buf[20];
c801d85f 316
223d09f6 317 wxSprintf (buf, wxT("%d"), number);
c801d85f
KB
318 return buf;
319}
320
84fff0b3 321wxChar *
c801d85f
KB
322LongToString (long number)
323{
84fff0b3 324 static wxChar buf[20];
c801d85f 325
223d09f6 326 wxSprintf (buf, wxT("%ld"), number);
c801d85f
KB
327 return buf;
328}
329
330// Array used in DecToHex conversion routine.
223d09f6 331static wxChar hexArray[] = wxT("0123456789ABCDEF");
c801d85f
KB
332
333// Convert 2-digit hex number to decimal
fd71308f 334int wxHexToDec(const wxString& buf)
c801d85f
KB
335{
336 int firstDigit, secondDigit;
3f4a0c5b 337
223d09f6
KB
338 if (buf.GetChar(0) >= wxT('A'))
339 firstDigit = buf.GetChar(0) - wxT('A') + 10;
c801d85f 340 else
223d09f6 341 firstDigit = buf.GetChar(0) - wxT('0');
c801d85f 342
223d09f6
KB
343 if (buf.GetChar(1) >= wxT('A'))
344 secondDigit = buf.GetChar(1) - wxT('A') + 10;
c801d85f 345 else
223d09f6 346 secondDigit = buf.GetChar(1) - wxT('0');
3f4a0c5b 347
4b1f6faa 348 return (firstDigit & 0xF) * 16 + (secondDigit & 0xF );
c801d85f
KB
349}
350
351// Convert decimal integer to 2-character hex string
84fff0b3 352void wxDecToHex(int dec, wxChar *buf)
c801d85f
KB
353{
354 int firstDigit = (int)(dec/16.0);
355 int secondDigit = (int)(dec - (firstDigit*16.0));
356 buf[0] = hexArray[firstDigit];
357 buf[1] = hexArray[secondDigit];
358 buf[2] = 0;
359}
360
fd71308f
JS
361// Convert decimal integer to 2-character hex string
362wxString wxDecToHex(int dec)
363{
84fff0b3 364 wxChar buf[3];
fd71308f
JS
365 wxDecToHex(dec, buf);
366 return wxString(buf);
367}
368
c801d85f 369// Match a string INDEPENDENT OF CASE
3f4a0c5b 370bool
bc87fd68 371StringMatch (const char *str1, const char *str2, bool subString, bool exact)
c801d85f
KB
372{
373 if (str1 == NULL || str2 == NULL)
374 return FALSE;
375 if (str1 == str2)
376 return TRUE;
377
378 if (subString)
379 {
380 int len1 = strlen (str1);
381 int len2 = strlen (str2);
382 int i;
383
384 // Search for str1 in str2
385 // Slow .... but acceptable for short strings
386 for (i = 0; i <= len2 - len1; i++)
3f4a0c5b
VZ
387 {
388 if (strncasecmp (str1, str2 + i, len1) == 0)
389 return TRUE;
390 }
c801d85f
KB
391 }
392 else if (exact)
393 {
394 if (strcasecmp (str1, str2) == 0)
3f4a0c5b 395 return TRUE;
c801d85f
KB
396 }
397 else
398 {
399 int len1 = strlen (str1);
400 int len2 = strlen (str2);
401
402 if (strncasecmp (str1, str2, wxMin (len1, len2)) == 0)
3f4a0c5b 403 return TRUE;
c801d85f
KB
404 }
405
406 return FALSE;
407}
408
409// Return the current date/time
410// [volatile]
e90c1d2a 411wxString wxNow()
c801d85f 412{
c67daf87 413 time_t now = time((time_t *) NULL);
3f4a0c5b 414 char *date = ctime(&now);
c801d85f
KB
415 date[24] = '\0';
416 return wxString(date);
417}
418
e90c1d2a
VZ
419#if wxUSE_GUI
420
1e6feb95
VZ
421#if wxUSE_MENUS
422
e90c1d2a 423// ----------------------------------------------------------------------------
974e8d94 424// Menu accelerators related functions
e90c1d2a 425// ----------------------------------------------------------------------------
c801d85f 426
bc87fd68 427wxChar *wxStripMenuCodes(const wxChar *in, wxChar *out)
c801d85f 428{
1e6feb95
VZ
429 wxString s = wxMenuItem::GetLabelFromText(in);
430 if ( out )
c801d85f 431 {
1e6feb95
VZ
432 // go smash their buffer if it's not big enough - I love char * params
433 memcpy(out, s.c_str(), s.length() * sizeof(wxChar));
434 }
435 else
436 {
437 out = copystring(s);
438 }
c801d85f 439
1e6feb95 440 return out;
c801d85f
KB
441}
442
1e6feb95 443wxString wxStripMenuCodes(const wxString& in)
47bc1060 444{
1e6feb95 445 wxString out;
c801d85f 446
1e6feb95
VZ
447 size_t len = in.length();
448 out.reserve(len);
974e8d94 449
1e6feb95
VZ
450 for ( size_t n = 0; n < len; n++ )
451 {
452 wxChar ch = in[n];
453 if ( ch == _T('&') )
454 {
455 // skip it, it is used to introduce the accel char (or to quote
456 // itself in which case it should still be skipped): note that it
457 // can't be the last character of the string
458 if ( ++n == len )
459 {
460 wxLogDebug(_T("Invalid menu string '%s'"), in.c_str());
974e8d94 461 }
1e6feb95
VZ
462 else
463 {
464 // use the next char instead
465 ch = in[n];
974e8d94
VZ
466 }
467 }
1e6feb95
VZ
468 else if ( ch == _T('\t') )
469 {
470 // everything after TAB is accel string, exit the loop
471 break;
974e8d94
VZ
472 }
473
1e6feb95 474 out += ch;
974e8d94
VZ
475 }
476
1e6feb95 477 return out;
974e8d94
VZ
478}
479
1e6feb95 480#endif // wxUSE_MENUS
974e8d94 481
e90c1d2a
VZ
482// ----------------------------------------------------------------------------
483// Window search functions
484// ----------------------------------------------------------------------------
c801d85f
KB
485
486/*
487 * If parent is non-NULL, look through children for a label or title
488 * matching the specified string. If NULL, look through all top-level windows.
489 *
490 */
491
c801d85f
KB
492wxWindow *
493wxFindWindowByLabel (const wxString& title, wxWindow * parent)
494{
e146b8c8 495 if (parent)
c801d85f 496 {
e146b8c8 497 return wxFindWindowByLabel1(title, parent);
c801d85f 498 }
e146b8c8 499 else
c801d85f 500 {
e146b8c8
VZ
501 for ( wxWindowList::Node * node = wxTopLevelWindows.GetFirst();
502 node;
503 node = node->GetNext() )
3f4a0c5b 504 {
e146b8c8
VZ
505 wxWindow *win = node->GetData();
506 wxWindow *retwin = wxFindWindowByLabel1 (title, win);
507 if (retwin)
508 return retwin;
3f4a0c5b 509 } // for()
c801d85f
KB
510
511 }
e146b8c8 512 return (wxWindow *) NULL;
c801d85f
KB
513}
514
515// Recursive
516static wxWindow *
517wxFindWindowByLabel1 (const wxString& title, wxWindow * parent)
518{
e146b8c8 519 if (parent)
c801d85f 520 {
e146b8c8
VZ
521 if (parent->GetLabel() == title)
522 return parent;
c801d85f
KB
523 }
524
e146b8c8 525 if (parent)
c801d85f 526 {
f03fc89f 527 for ( wxWindowList::Node * node = parent->GetChildren().GetFirst();
e146b8c8
VZ
528 node;
529 node = node->GetNext() )
3f4a0c5b 530 {
e146b8c8
VZ
531 wxWindow *win = (wxWindow *)node->GetData();
532 wxWindow *retwin = wxFindWindowByLabel1 (title, win);
533 if (retwin)
534 return retwin;
535 }
c801d85f
KB
536
537 }
538
e146b8c8 539 return (wxWindow *) NULL; // Not found
c801d85f
KB
540}
541
542/*
543 * If parent is non-NULL, look through children for a name
544 * matching the specified string. If NULL, look through all top-level windows.
545 *
546 */
547
c801d85f
KB
548wxWindow *
549wxFindWindowByName (const wxString& title, wxWindow * parent)
550{
e146b8c8 551 if (parent)
c801d85f 552 {
e146b8c8 553 return wxFindWindowByName1 (title, parent);
c801d85f 554 }
e146b8c8 555 else
c801d85f 556 {
e146b8c8
VZ
557 for ( wxWindowList::Node * node = wxTopLevelWindows.GetFirst();
558 node;
559 node = node->GetNext() )
3f4a0c5b 560 {
e146b8c8
VZ
561 wxWindow *win = node->GetData();
562 wxWindow *retwin = wxFindWindowByName1 (title, win);
563 if (retwin)
564 return retwin;
565 }
c801d85f
KB
566
567 }
e146b8c8
VZ
568
569 // Failed? Try by label instead.
570 return wxFindWindowByLabel(title, parent);
c801d85f
KB
571}
572
573// Recursive
574static wxWindow *
575wxFindWindowByName1 (const wxString& title, wxWindow * parent)
576{
577 if (parent)
578 {
3f4a0c5b
VZ
579 if ( parent->GetName() == title )
580 return parent;
c801d85f
KB
581 }
582
583 if (parent)
584 {
c0ed460c 585 for (wxNode * node = parent->GetChildren().First (); node; node = node->Next ())
3f4a0c5b
VZ
586 {
587 wxWindow *win = (wxWindow *) node->Data ();
588 wxWindow *retwin = wxFindWindowByName1 (title, win);
589 if (retwin)
590 return retwin;
591 } // for()
c801d85f
KB
592
593 }
594
3f4a0c5b 595 return (wxWindow *) NULL; // Not found
c801d85f
KB
596
597}
598
599// Returns menu item id or -1 if none.
3f4a0c5b 600int
c801d85f
KB
601wxFindMenuItemId (wxFrame * frame, const wxString& menuString, const wxString& itemString)
602{
1e6feb95 603#if wxUSE_MENUS
c801d85f 604 wxMenuBar *menuBar = frame->GetMenuBar ();
1e6feb95
VZ
605 if ( menuBar )
606 return menuBar->FindMenuItem (menuString, itemString);
607#endif // wxUSE_MENUS
608
609 return -1;
59a12e90
JS
610}
611
d1c8aaa3
JS
612// Try to find the deepest child that contains 'pt'.
613// We go backwards, to try to allow for controls that are spacially
614// within other controls, but are still siblings (e.g. buttons within
615// static boxes). Static boxes are likely to be created _before_ controls
616// that sit inside them.
59a12e90
JS
617wxWindow* wxFindWindowAtPoint(wxWindow* win, const wxPoint& pt)
618{
d1c8aaa3
JS
619 if (!win->IsShown())
620 return NULL;
621
622 // Hack for wxNotebook case: at least in wxGTK, all pages
623 // claim to be shown, so we must only deal with the selected one.
c67d6888 624#if wxUSE_NOTEBOOK
d1c8aaa3
JS
625 if (win->IsKindOf(CLASSINFO(wxNotebook)))
626 {
627 wxNotebook* nb = (wxNotebook*) win;
628 int sel = nb->GetSelection();
629 if (sel >= 0)
630 {
631 wxWindow* child = nb->GetPage(sel);
632 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
633 if (foundWin)
634 return foundWin;
635 }
636 }
c67d6888
JS
637#endif
638
d1c8aaa3
JS
639 /* Doesn't work
640 // Frame case
641 else if (win->IsKindOf(CLASSINFO(wxFrame)))
642 {
643 // Pseudo-children that may not be mentioned in the child list
644 wxWindowList extraChildren;
645 wxFrame* frame = (wxFrame*) win;
646 if (frame->GetStatusBar())
647 extraChildren.Append(frame->GetStatusBar());
648 if (frame->GetToolBar())
649 extraChildren.Append(frame->GetToolBar());
650
651 wxNode* node = extraChildren.First();
652 while (node)
653 {
654 wxWindow* child = (wxWindow*) node->Data();
655 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
656 if (foundWin)
657 return foundWin;
658 node = node->Next();
659 }
660 }
661 */
662
663 wxNode* node = win->GetChildren().Last();
59a12e90
JS
664 while (node)
665 {
666 wxWindow* child = (wxWindow*) node->Data();
667 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
668 if (foundWin)
d1c8aaa3
JS
669 return foundWin;
670 node = node->Previous();
59a12e90
JS
671 }
672
673 wxPoint pos = win->GetPosition();
674 wxSize sz = win->GetSize();
675 if (win->GetParent())
676 {
677 pos = win->GetParent()->ClientToScreen(pos);
678 }
679
680 wxRect rect(pos, sz);
681 if (rect.Inside(pt))
682 return win;
683 else
684 return NULL;
685}
686
57591e0e 687wxWindow* wxGenericFindWindowAtPoint(const wxPoint& pt)
59a12e90 688{
57591e0e
JS
689 // Go backwards through the list since windows
690 // on top are likely to have been appended most
691 // recently.
692 wxNode* node = wxTopLevelWindows.Last();
59a12e90
JS
693 while (node)
694 {
695 wxWindow* win = (wxWindow*) node->Data();
696 wxWindow* found = wxFindWindowAtPoint(win, pt);
697 if (found)
698 return found;
57591e0e 699 node = node->Previous();
59a12e90
JS
700 }
701 return NULL;
c801d85f
KB
702}
703
e90c1d2a
VZ
704#endif // wxUSE_GUI
705
c801d85f
KB
706/*
707On Fri, 21 Jul 1995, Paul Craven wrote:
708
709> Is there a way to find the path of running program's executable? I can get
710> my home directory, and the current directory, but I don't know how to get the
711> executable directory.
3f4a0c5b 712>
c801d85f
KB
713
714The code below (warty as it is), does what you want on most Unix,
715DOS, and Mac platforms (it's from the ALS Prolog main).
716
3f4a0c5b 717|| Ken Bowen Applied Logic Systems, Inc. PO Box 180,
c801d85f
KB
718||==== Voice: +1 (617)965-9191 Newton Centre,
719|| FAX: +1 (617)965-1636 MA 02159 USA
720 Email: ken@als.com WWW: http://www.als.com
721------------------------------------------------------------------------
722*/
723
724// This code is commented out but it may be integrated with wxWin at
725// a later date, after testing. Thanks Ken!
726#if 0
727
728/*--------------------------------------------------------------------*
729 | whereami is given a filename f in the form: whereami(argv[0])
3f4a0c5b
VZ
730 | It returns the directory in which the executable file (containing
731 | this code [main.c] ) may be found. A dot will be returned to indicate
c801d85f
KB
732 | the current directory.
733 *--------------------------------------------------------------------*/
734
735static void
736whereami(name)
737 char *name;
738{
3f4a0c5b 739 register char *cutoff = NULL; /* stifle -Wall */
c801d85f
KB
740 register char *s;
741 register char *t;
742 int cc;
743 char ebuf[4096];
744
745 /*
746 * See if the file is accessible either through the current directory
747 * or through an absolute path.
748 */
749
750 if (access(name, R_OK) == 0) {
751
3f4a0c5b
VZ
752 /*-------------------------------------------------------------*
753 * The file was accessible without any other work. But the current
754 * working directory might change on us, so if it was accessible
755 * through the cwd, then we should get it for later accesses.
756 *-------------------------------------------------------------*/
c801d85f 757
3f4a0c5b
VZ
758 t = imagedir;
759 if (!absolute_pathname(name)) {
abb85561 760#if defined(__DOS__) || defined(__WIN32__)
3f4a0c5b
VZ
761 int drive;
762 char *newrbuf;
c801d85f 763
3f4a0c5b 764 newrbuf = imagedir;
c801d85f 765#ifndef __DJGPP__
3f4a0c5b
VZ
766 if (*(name + 1) == ':') {
767 if (*name >= 'a' && *name <= 'z')
768 drive = (int) (*name - 'a' + 1);
769 else
770 drive = (int) (*name - 'A' + 1);
771 *newrbuf++ = *name;
772 *newrbuf++ = *(name + 1);
773 *newrbuf++ = DIR_SEPARATOR;
774 }
775 else {
776 drive = 0;
777 *newrbuf++ = DIR_SEPARATOR;
778 }
779 if (getcwd(newrbuf, drive) == 0) { /* } */
c801d85f 780#else
3f4a0c5b 781 if (getcwd(newrbuf, 1024) == 0) { /* } */
c801d85f
KB
782#endif
783#else /* DOS */
784#ifdef HAVE_GETWD
3f4a0c5b 785 if (getwd(imagedir) == 0) { /* } */
c801d85f 786#else /* !HAVE_GETWD */
3f4a0c5b 787 if (getcwd(imagedir, 1024) == 0) {
c801d85f
KB
788#endif /* !HAVE_GETWD */
789#endif /* DOS */
3f4a0c5b
VZ
790 fatal_error(FE_GETCWD, 0);
791 }
792 for (; *t; t++) /* Set t to end of buffer */
793 ;
794 if (*(t - 1) == DIR_SEPARATOR) /* leave slash if already
795 * last char
796 */
797 cutoff = t - 1;
798 else {
799 cutoff = t; /* otherwise put one in */
800 *t++ = DIR_SEPARATOR;
801 }
802 }
c801d85f 803#if (!defined(__MAC__) && !defined(__DJGPP__) && !defined(__GO32__) && !defined(__WIN32__))
3f4a0c5b
VZ
804 else
805 (*t++ = DIR_SEPARATOR);
c801d85f
KB
806#endif
807
3f4a0c5b
VZ
808 /*-------------------------------------------------------------*
809 * Copy the rest of the string and set the cutoff if it was not
810 * already set. If the first character of name is a slash, cutoff
811 * is not presently set but will be on the first iteration of the
812 * loop below.
813 *-------------------------------------------------------------*/
c801d85f 814
3f4a0c5b
VZ
815 for ((*name == DIR_SEPARATOR ? (s = name+1) : (s = name));;) {
816 if (*s == DIR_SEPARATOR)
817 cutoff = t;
818 if (!(*t++ = *s++))
819 break;
820 }
c801d85f
KB
821
822 }
823 else {
824
3f4a0c5b
VZ
825 /*-------------------------------------------------------------*
826 * Get the path list from the environment. If the path list is
827 * inaccessible for any reason, leave with fatal error.
828 *-------------------------------------------------------------*/
c801d85f
KB
829
830#ifdef __MAC__
3f4a0c5b 831 if ((s = getenv("Commands")) == (char *) 0)
c801d85f 832#else
3f4a0c5b 833 if ((s = getenv("PATH")) == (char *) 0)
c801d85f 834#endif
3f4a0c5b
VZ
835 fatal_error(FE_PATH, 0);
836
837 /*
838 * Copy path list into ebuf and set the source pointer to the
839 * beginning of this buffer.
840 */
841
842 strcpy(ebuf, s);
843 s = ebuf;
844
845 for (;;) {
846 t = imagedir;
847 while (*s && *s != PATH_SEPARATOR)
848 *t++ = *s++;
849 if (t > imagedir && *(t - 1) == DIR_SEPARATOR)
850 ; /* do nothing -- slash already is in place */
851 else
852 *t++ = DIR_SEPARATOR; /* put in the slash */
853 cutoff = t - 1; /* set cutoff */
854 strcpy(t, name);
855 if (access(imagedir, R_OK) == 0)
856 break;
857
858 if (*s)
859 s++; /* advance source pointer */
860 else
861 fatal_error(FE_INFND, 0);
862 }
c801d85f
KB
863
864 }
865
866 /*-------------------------------------------------------------*
867 | At this point the full pathname should exist in imagedir and
868 | cutoff should be set to the final slash. We must now determine
869 | whether the file name is a symbolic link or not and chase it down
870 | if it is. Note that we reuse ebuf for getting the link.
871 *-------------------------------------------------------------*/
872
873#ifdef HAVE_SYMLINK
874 while ((cc = readlink(imagedir, ebuf, 512)) != -1) {
3f4a0c5b
VZ
875 ebuf[cc] = 0;
876 s = ebuf;
877 if (*s == DIR_SEPARATOR) {
878 t = imagedir;
879 }
880 else {
881 t = cutoff + 1;
882 }
883 for (;;) {
884 if (*s == DIR_SEPARATOR)
885 cutoff = t; /* mark the last slash seen */
886 if (!(*t++ = *s++)) /* copy the character */
887 break;
888 }
c801d85f
KB
889 }
890
891#endif /* HAVE_SYMLINK */
892
3f4a0c5b
VZ
893 strcpy(imagename, cutoff + 1); /* keep the image name */
894 *(cutoff + 1) = 0; /* chop off the filename part */
c801d85f
KB
895}
896
897#endif
ead7ce10 898
e90c1d2a
VZ
899#if wxUSE_GUI
900
901// ----------------------------------------------------------------------------
902// GUI helpers
903// ----------------------------------------------------------------------------
ead7ce10 904
dfad0599
JS
905/*
906 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
907 * since otherwise the generic code may be pulled in unnecessarily.
908 */
909
1e6feb95
VZ
910#if wxUSE_MSGDLG
911
dfad0599
JS
912int wxMessageBox(const wxString& message, const wxString& caption, long style,
913 wxWindow *parent, int WXUNUSED(x), int WXUNUSED(y) )
914{
915 wxMessageDialog dialog(parent, message, caption, style);
916
917 int ans = dialog.ShowModal();
918 switch ( ans )
919 {
920 case wxID_OK:
921 return wxOK;
dfad0599
JS
922 case wxID_YES:
923 return wxYES;
dfad0599
JS
924 case wxID_NO:
925 return wxNO;
dfad0599
JS
926 case wxID_CANCEL:
927 return wxCANCEL;
dfad0599 928 }
3ca6a5f0
BP
929
930 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
931
932 return wxCANCEL;
dfad0599
JS
933}
934
1e6feb95
VZ
935#endif // wxUSE_MSGDLG
936
88ac883a 937#if wxUSE_TEXTDLG
1e6feb95 938
dfad0599
JS
939wxString wxGetTextFromUser(const wxString& message, const wxString& caption,
940 const wxString& defaultValue, wxWindow *parent,
941 int x, int y, bool WXUNUSED(centre) )
942{
d2f50933 943 wxString str;
dfad0599
JS
944 wxTextEntryDialog dialog(parent, message, caption, defaultValue, wxOK|wxCANCEL, wxPoint(x, y));
945 if (dialog.ShowModal() == wxID_OK)
d2f50933
VZ
946 {
947 str = dialog.GetValue();
948 }
949
950 return str;
dfad0599 951}
d2f50933
VZ
952
953wxString wxGetPasswordFromUser(const wxString& message,
954 const wxString& caption,
955 const wxString& defaultValue,
956 wxWindow *parent)
957{
958 wxString str;
959 wxTextEntryDialog dialog(parent, message, caption, defaultValue,
960 wxOK | wxCANCEL | wxTE_PASSWORD);
961 if ( dialog.ShowModal() == wxID_OK )
962 {
963 str = dialog.GetValue();
964 }
965
966 return str;
967}
968
88ac883a 969#endif // wxUSE_TEXTDLG
dfad0599 970
1e6feb95
VZ
971#if wxUSE_COLOURDLG
972
91b4c08d
VZ
973wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit)
974{
bf31fa26
VZ
975 wxColourData data;
976 data.SetChooseFull(TRUE);
977 if ( colInit.Ok() )
978 {
979 data.SetColour((wxColour &)colInit); // const_cast
980 }
91b4c08d 981
bf31fa26
VZ
982 wxColour colRet;
983 wxColourDialog dialog(parent, &data);
984 if ( dialog.ShowModal() == wxID_OK )
985 {
986 colRet = dialog.GetColourData().GetColour();
987 }
988 //else: leave it invalid
91b4c08d 989
bf31fa26 990 return colRet;
91b4c08d
VZ
991}
992
1e6feb95
VZ
993#endif // wxUSE_COLOURDLG
994
bf31fa26
VZ
995#if wxUSE_FONTDLG
996
997wxFont wxGetFontFromUser(wxWindow *parent, const wxFont& fontInit)
998{
999 wxFontData data;
1000 if ( fontInit.Ok() )
1001 {
1002 data.SetInitialFont(fontInit);
1003 }
1004
1005 wxFont fontRet;
1006 wxFontDialog dialog(parent, &data);
1007 if ( dialog.ShowModal() == wxID_OK )
1008 {
1009 fontRet = dialog.GetFontData().GetChosenFont();
1010 }
1011 //else: leave it invalid
1012
1013 return fontRet;
1014}
1015
1016#endif // wxUSE_FONTDLG
91b4c08d
VZ
1017// ----------------------------------------------------------------------------
1018// missing C RTL functions (FIXME shouldn't be here at all)
1019// ----------------------------------------------------------------------------
1020
469e1e5c 1021#ifdef __MWERKS__
4b0b35f1 1022#if __MSL__ < 0x7000
3f4a0c5b 1023char *strdup(const char *s)
469e1e5c 1024{
3f4a0c5b 1025 return strcpy( (char*) malloc( strlen( s ) + 1 ) , s ) ;
469e1e5c 1026}
4b0b35f1 1027#endif
3f4a0c5b 1028int isascii( int c )
469e1e5c 1029{
3f4a0c5b 1030 return ( c >= 0 && c < 128 ) ;
469e1e5c 1031}
e90c1d2a
VZ
1032#endif // __MWERKS__
1033
1034// ----------------------------------------------------------------------------
cbc66a27 1035// wxSafeYield and supporting functions
e90c1d2a
VZ
1036// ----------------------------------------------------------------------------
1037
1038void wxEnableTopLevelWindows(bool enable)
1039{
225fe9d6
VZ
1040 wxWindowList::Node *node;
1041 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
1042 node->GetData()->Enable(enable);
e90c1d2a
VZ
1043}
1044
cd6ce4a9 1045wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip)
e90c1d2a 1046{
79f585d9
VZ
1047 // remember the top level windows which were already disabled, so that we
1048 // don't reenable them later
1049 m_winDisabled = NULL;
1050
225fe9d6
VZ
1051 wxWindowList::Node *node;
1052 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
1053 {
1054 wxWindow *winTop = node->GetData();
79f585d9
VZ
1055 if ( winTop == winToSkip )
1056 continue;
1057
1058 if ( winTop->IsEnabled() )
1059 {
1060 winTop->Disable();
1061 }
1062 else
cd6ce4a9 1063 {
79f585d9
VZ
1064 if ( !m_winDisabled )
1065 {
1066 m_winDisabled = new wxWindowList;
1067 }
225fe9d6 1068
cd6ce4a9 1069 m_winDisabled->Append(winTop);
cd6ce4a9 1070 }
225fe9d6 1071 }
cd6ce4a9 1072}
225fe9d6 1073
cd6ce4a9
VZ
1074wxWindowDisabler::~wxWindowDisabler()
1075{
1076 wxWindowList::Node *node;
79f585d9 1077 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
225fe9d6 1078 {
79f585d9
VZ
1079 wxWindow *winTop = node->GetData();
1080 if ( !m_winDisabled || !m_winDisabled->Find(winTop) )
1081 {
1082 winTop->Enable();
1083 }
1084 //else: had been already disabled, don't reenable
225fe9d6
VZ
1085 }
1086
cd6ce4a9
VZ
1087 delete m_winDisabled;
1088}
1089
1090// Yield to other apps/messages and disable user input to all windows except
1091// the given one
1092bool wxSafeYield(wxWindow *win)
1093{
bc1dcfc1 1094 wxWindowDisabler wd(win);
cd6ce4a9
VZ
1095
1096 bool rc = wxYield();
1097
225fe9d6 1098 return rc;
e90c1d2a
VZ
1099}
1100
cbc66a27
VZ
1101// ----------------------------------------------------------------------------
1102// misc functions
1103// ----------------------------------------------------------------------------
1104
e90c1d2a
VZ
1105// Don't synthesize KeyUp events holding down a key and producing KeyDown
1106// events with autorepeat. On by default and always on in wxMSW. wxGTK version
1107// in utilsgtk.cpp.
1108#ifndef __WXGTK__
1109bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) )
1110{
225fe9d6 1111 return TRUE; // detectable auto-repeat is the only mode MSW supports
e90c1d2a
VZ
1112}
1113#endif // !wxGTK
1114
1115#endif // wxUSE_GUI
e2a6f233 1116
134677bd
VS
1117const wxChar *wxGetInstallPrefix()
1118{
1119 wxString prefix;
1120
8f50c527 1121 if ( wxGetEnv(wxT("WXPREFIX"), &prefix) )
134677bd
VS
1122 return prefix.c_str();
1123
1124#ifdef wxINSTALL_PREFIX
1125 return wxT(wxINSTALL_PREFIX);
1126#else
1127 return wxT("");
1128#endif
1129}
1130
2c18f21d
VS
1131wxString wxGetDataDir()
1132{
1133 wxString format = wxGetInstallPrefix();
1134 format << wxFILE_SEP_PATH
1135 << wxT("share") << wxFILE_SEP_PATH
1136 << wxT("wx") << wxFILE_SEP_PATH
1137 << wxT("%i.%i");
1138 wxString dir;
1139 dir.Printf(format.c_str(), wxMAJOR_VERSION, wxMINOR_VERSION);
1140 return dir;
1141}
1142
134677bd 1143
0fb67cd1
VZ
1144// ----------------------------------------------------------------------------
1145// network and user id functions
1146// ----------------------------------------------------------------------------
1147
1148// Get Full RFC822 style email address
84fff0b3 1149bool wxGetEmailAddress(wxChar *address, int maxSize)
e2a6f233 1150{
0fb67cd1
VZ
1151 wxString email = wxGetEmailAddress();
1152 if ( !email )
e2a6f233 1153 return FALSE;
0fb67cd1 1154
84fff0b3 1155 wxStrncpy(address, email, maxSize - 1);
223d09f6 1156 address[maxSize - 1] = wxT('\0');
0fb67cd1
VZ
1157
1158 return TRUE;
e2a6f233
JS
1159}
1160
0fb67cd1 1161wxString wxGetEmailAddress()
e2a6f233 1162{
0fb67cd1
VZ
1163 wxString email;
1164
1f0500b3 1165 wxString host = wxGetFullHostName();
0fb67cd1 1166 if ( !!host )
e2a6f233 1167 {
0fb67cd1
VZ
1168 wxString user = wxGetUserId();
1169 if ( !!user )
1170 {
1f0500b3 1171 email << user << wxT('@') << host;
0fb67cd1 1172 }
e2a6f233 1173 }
0fb67cd1
VZ
1174
1175 return email;
1176}
1177
1178wxString wxGetUserId()
1179{
1180 static const int maxLoginLen = 256; // FIXME arbitrary number
1181
1182 wxString buf;
1183 bool ok = wxGetUserId(buf.GetWriteBuf(maxLoginLen), maxLoginLen);
1184 buf.UngetWriteBuf();
1185
1186 if ( !ok )
1187 buf.Empty();
1188
1189 return buf;
1190}
1191
1192wxString wxGetUserName()
1193{
1194 static const int maxUserNameLen = 1024; // FIXME arbitrary number
1195
1196 wxString buf;
1197 bool ok = wxGetUserName(buf.GetWriteBuf(maxUserNameLen), maxUserNameLen);
1198 buf.UngetWriteBuf();
1199
1200 if ( !ok )
1201 buf.Empty();
1202
1203 return buf;
e2a6f233
JS
1204}
1205
0fb67cd1 1206wxString wxGetHostName()
518b5d2f
VZ
1207{
1208 static const size_t hostnameSize = 257;
0fb67cd1
VZ
1209
1210 wxString buf;
518b5d2f
VZ
1211 bool ok = wxGetHostName(buf.GetWriteBuf(hostnameSize), hostnameSize);
1212
1213 buf.UngetWriteBuf();
1214
0fb67cd1
VZ
1215 if ( !ok )
1216 buf.Empty();
1217
1218 return buf;
518b5d2f
VZ
1219}
1220
96c5bd7f
KB
1221wxString wxGetFullHostName()
1222{
1223 static const size_t hostnameSize = 257;
1224
1225 wxString buf;
1226 bool ok = wxGetFullHostName(buf.GetWriteBuf(hostnameSize), hostnameSize);
1227
1228 buf.UngetWriteBuf();
1229
1230 if ( !ok )
1231 buf.Empty();
1232
1233 return buf;
1234}
1235
c51deffc
VZ
1236wxString wxGetHomeDir()
1237{
1238 wxString home;
1239 wxGetHomeDir(&home);
1240
1241 return home;
1242}
bc385ba9
VZ
1243
1244#if 0
1245
1246wxString wxGetCurrentDir()
1247{
1248 wxString dir;
1249 size_t len = 1024;
1250 bool ok;
1251 do
1252 {
1253 ok = getcwd(dir.GetWriteBuf(len + 1), len) != NULL;
1254 dir.UngetWriteBuf();
1255
1256 if ( !ok )
1257 {
1258 if ( errno != ERANGE )
1259 {
1260 wxLogSysError(_T("Failed to get current directory"));
1261
1262 return wxEmptyString;
1263 }
1264 else
1265 {
1266 // buffer was too small, retry with a larger one
1267 len *= 2;
1268 }
1269 }
1270 //else: ok
1271 } while ( !ok );
1272
1273 return dir;
1274}
1275
1276#endif // 0
cd6ce4a9
VZ
1277
1278// ----------------------------------------------------------------------------
1279// wxExecute
1280// ----------------------------------------------------------------------------
1281
f6bcfd97
BP
1282// this is a private function because it hasn't a clean interface: the first
1283// array is passed by reference, the second by pointer - instead we have 2
1284// public versions of wxExecute() below
1285static long wxDoExecuteWithCapture(const wxString& command,
1286 wxArrayString& output,
1287 wxArrayString* error)
cd6ce4a9 1288{
669f7a11
JS
1289#ifdef __WIN16__
1290 wxFAIL_MSG("Sorry, this version of wxExecute not implemented on WIN16.");
f6bcfd97 1291
669f7a11 1292 return 0;
f6bcfd97 1293#else // !Win16
cd6ce4a9
VZ
1294 // create a wxProcess which will capture the output
1295 wxProcess *process = new wxProcess;
1296 process->Redirect();
1297
1298 long rc = wxExecute(command, TRUE /* sync */, process);
f6bcfd97
BP
1299
1300#if wxUSE_STREAMS
cd6ce4a9
VZ
1301 if ( rc != -1 )
1302 {
f6bcfd97
BP
1303 wxInputStream* is = process->GetInputStream();
1304 wxCHECK_MSG( is, -1, _T("if wxExecute() succeded, stream can't be NULL") );
1305 wxTextInputStream tis(*is);
1306
1307 wxTextInputStream *tes = NULL;
1308 wxInputStream *es = NULL;
1309 if ( error )
cd6ce4a9 1310 {
f6bcfd97
BP
1311 es = process->GetErrorStream();
1312
1313 wxCHECK_MSG( es, -1, _T("stderr can't be NULL") );
1314
1315 tes = new wxTextInputStream(*es);
1316 }
1317
1318 bool cont;
1319 do
1320 {
1321 cont = FALSE;
1322
1323 if ( !is->Eof() && is->IsOk() )
1324 {
1325 wxString line = tis.ReadLine();
1326 if ( is->LastError() )
1327 break;
1328
1329 cont = TRUE;
1330
1331 output.Add(line);
1332 }
1333
1334 if ( error && !es->Eof() && es->IsOk() )
1335 {
1336 wxString line = tes->ReadLine();
1337 if ( es->LastError() )
1338 break;
1339
1340 cont = TRUE;
cd6ce4a9 1341
f6bcfd97
BP
1342 error->Add(line);
1343 }
cd6ce4a9 1344 }
f6bcfd97
BP
1345 while ( cont );
1346
1347 delete tes;
cd6ce4a9 1348 }
f6bcfd97
BP
1349#endif // wxUSE_STREAMS
1350
1351 delete process;
cd6ce4a9
VZ
1352
1353 return rc;
f6bcfd97
BP
1354#endif // IO redirection supoprted
1355}
1356
1357long wxExecute(const wxString& command, wxArrayString& output)
1358{
1359 return wxDoExecuteWithCapture(command, output, NULL);
1360}
1361
1362long wxExecute(const wxString& command,
1363 wxArrayString& output,
1364 wxArrayString& error)
1365{
1366 return wxDoExecuteWithCapture(command, output, &error);
cd6ce4a9 1367}
21709999 1368
8461e4c2
VZ
1369// ----------------------------------------------------------------------------
1370// wxApp::Yield() wrappers for backwards compatibility
1371// ----------------------------------------------------------------------------
1372
1373bool wxYield()
1374{
1375#if wxUSE_GUI
1376 return wxTheApp && wxTheApp->Yield();
1377#else
1378 return FALSE;
1379#endif
1380}
1381
1382bool wxYieldIfNeeded()
1383{
1384#if wxUSE_GUI
1385 return wxTheApp && wxTheApp->Yield(TRUE);
1386#else
1387 return FALSE;
1388#endif
1389}
21709999 1390