home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / src / common / utilscmn.cpp < prev    next >
C/C++ Source or Header  |  2002-08-30  |  33KB  |  1,297 lines

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