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