X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/fd71308fc89eac2dd212b715eba68a993fa78f53..82713003dc446ad0353127abe66a1ecc66f4df67:/src/common/utilscmn.cpp diff --git a/src/common/utilscmn.cpp b/src/common/utilscmn.cpp index cb7890e7a8..6020b8780d 100644 --- a/src/common/utilscmn.cpp +++ b/src/common/utilscmn.cpp @@ -6,67 +6,136 @@ // Created: 29/01/98 // RCS-ID: $Id$ // Copyright: (c) 1998 Julian Smart -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + #ifdef __GNUG__ -#pragma implementation "utils.h" + #pragma implementation "utils.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif #ifndef WX_PRECOMP -#include "wx/defs.h" -#include "wx/utils.h" -#include "wx/window.h" -#include "wx/menu.h" -#include "wx/frame.h" -#include "wx/msgdlg.h" -#include "wx/textdlg.h" -#endif - -#if wxUSE_IOSTREAMH -#include -#else -#include + #include "wx/defs.h" + #include "wx/string.h" + #include "wx/utils.h" + #include "wx/intl.h" + #include "wx/log.h" + + #if wxUSE_GUI + #include "wx/window.h" + #include "wx/menu.h" + #include "wx/frame.h" + #include "wx/msgdlg.h" + #include "wx/textdlg.h" + #if wxUSE_ACCEL + #include "wx/menuitem.h" + #include "wx/accel.h" + #endif // wxUSE_ACCEL + #endif // wxUSE_GUI +#endif // WX_PRECOMP + +#ifndef __WIN16__ +#include "wx/process.h" +#include "wx/txtstrm.h" #endif -#include #include #include #include #include + #if !defined(__WATCOMC__) -#if !(defined(_MSC_VER) && (_MSC_VER > 800)) -#include -#endif + #if !(defined(_MSC_VER) && (_MSC_VER > 800)) + #include + #endif #endif + +#if wxUSE_GUI + #include "wx/colordlg.h" + #include "wx/notebook.h" + #include "wx/frame.h" + #include "wx/statusbr.h" + #include "wx/toolbar.h" +#endif // wxUSE_GUI + #include -#include -#include -// Pattern matching code. -// Yes, this path is deliberate (for Borland compilation) -#ifdef wx_mac /* MATTHEW: [5] Mac doesn't like paths with "/" */ -#include "glob.inc" -#else -#include "../common/glob.inc" +#ifndef __MWERKS__ + #include + #include +#endif + +#ifdef __SALFORDC__ + #include #endif #ifdef __WXMSW__ -#include "windows.h" + #include "wx/msw/private.h" #endif -#define _MAXPATHLEN 500 +// ---------------------------------------------------------------------------- +// function protoypes +// ---------------------------------------------------------------------------- + +#if wxUSE_GUI + static wxWindow *wxFindWindowByLabel1(const wxString& title, wxWindow *parent); + static wxWindow *wxFindWindowByName1 (const wxString& title, wxWindow *parent); +#endif // wxUSE_GUI + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// string functions +// ---------------------------------------------------------------------------- -extern char *wxBuffer; +#ifdef __WXMAC__ +int strcasecmp(const char *str_1, const char *str_2) +{ + register char c1, c2; + do { + c1 = tolower(*str_1++); + c2 = tolower(*str_2++); + } while ( c1 && (c1 == c2) ); + + return c1 - c2; +} + +int strncasecmp(const char *str_1, const char *str_2, size_t maxchar) +{ + + register char c1, c2; + while( maxchar--) + { + c1 = tolower(*str_1++); + c2 = tolower(*str_2++); -#ifdef __VMS__ + if ( !c1 || c1!=c2 ) + return c1 - c2; + + } ; + + return 0 ; + +} +#endif // wxMAC + +#if defined( __VMS__ ) && ( __VMS_VER < 70000000 ) // we have no strI functions under VMS, therefore I have implemented // an inefficient but portable version: convert copies of strings to lowercase // and then use the normal comparison @@ -87,7 +156,7 @@ int strcasecmp(const char *str_1, const char *str_2) myLowerString(temp1); myLowerString(temp2); - int result = strcmp(temp1,temp2); + int result = wxStrcmp(temp1,temp2); delete[] temp1; delete[] temp2; @@ -109,24 +178,27 @@ int strncasecmp(const char *str_1, const char *str_2, size_t maxchar) return(result); } -#endif +#endif // __VMS__ #ifdef __WINDOWS__ #ifndef __GNUWIN32__ +#ifndef __MWERKS__ #define strcasecmp stricmp #define strncasecmp strnicmp +#else +#define strcasecmp _stricmp +#define strncasecmp _strnicmp #endif - -#ifdef _MSC_VER -#pragma warning (disable : 4245) #endif -#ifdef _MSC_VER -#pragma warning (default : 4245) +#else + +#ifdef __EMX__ +#define strcasecmp stricmp +#define strncasecmp strnicmp #endif -#else // This declaration is missing in SunOS! // (Yes, I know it is NOT ANSI-C but its in BSD libc) #if defined(__xlC) || defined(__AIX__) || defined(__GNUG__) @@ -136,17 +208,21 @@ extern "C" int strncasecmp (const char *, const char *, size_t); } #endif -#endif /* __WXMSW__ */ +#endif /* __WXMSW__ */ +#ifdef __WXPM__ +#define strcasecmp stricmp +#define strncasecmp strnicmp +#endif -char * -copystring (const char *s) +wxChar * +copystring (const wxChar *s) { - if (s == NULL) s = ""; - size_t len = strlen (s) + 1; + if (s == NULL) s = wxT(""); + size_t len = wxStrlen (s) + 1; - char *news = new char[len]; - memcpy (news, s, len); // Should be the fastest + wxChar *news = new wxChar[len]; + memcpy (news, s, len * sizeof(wxChar)); // Should be the fastest return news; } @@ -154,7 +230,7 @@ copystring (const char *s) // Id generation static long wxCurrentId = 100; -long +long wxNewId (void) { return wxCurrentId++; @@ -163,102 +239,101 @@ wxNewId (void) long wxGetCurrentId(void) { return wxCurrentId; } -void +void wxRegisterId (long id) { if (id >= wxCurrentId) wxCurrentId = id + 1; } -void -StringToFloat (char *s, float *number) +void +StringToFloat (wxChar *s, float *number) { if (s && *s && number) - *number = (float) strtod (s, (char **) NULL); + *number = (float) wxStrtod (s, (wxChar **) NULL); } -void -StringToDouble (char *s, double *number) +void +StringToDouble (wxChar *s, double *number) { if (s && *s && number) - *number = strtod (s, (char **) NULL); + *number = wxStrtod (s, (wxChar **) NULL); } -char * -FloatToString (float number, const char *fmt) +wxChar * +FloatToString (float number, const wxChar *fmt) { - static char buf[256]; + static wxChar buf[256]; // sprintf (buf, "%.2f", number); - sprintf (buf, fmt, number); + wxSprintf (buf, fmt, number); return buf; } -char * -DoubleToString (double number, const char *fmt) +wxChar * +DoubleToString (double number, const wxChar *fmt) { - static char buf[256]; + static wxChar buf[256]; - sprintf (buf, fmt, number); + wxSprintf (buf, fmt, number); return buf; } -void -StringToInt (char *s, int *number) +void +StringToInt (wxChar *s, int *number) { if (s && *s && number) - *number = (int) strtol (s, (char **) NULL, 10); + *number = (int) wxStrtol (s, (wxChar **) NULL, 10); } -void -StringToLong (char *s, long *number) +void +StringToLong (wxChar *s, long *number) { if (s && *s && number) - *number = strtol (s, (char **) NULL, 10); + *number = wxStrtol (s, (wxChar **) NULL, 10); } -char * +wxChar * IntToString (int number) { - static char buf[20]; + static wxChar buf[20]; - sprintf (buf, "%d", number); + wxSprintf (buf, wxT("%d"), number); return buf; } -char * +wxChar * LongToString (long number) { - static char buf[20]; + static wxChar buf[20]; - sprintf (buf, "%ld", number); + wxSprintf (buf, wxT("%ld"), number); return buf; } // Array used in DecToHex conversion routine. -static char hexArray[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', - 'C', 'D', 'E', 'F' }; +static wxChar hexArray[] = wxT("0123456789ABCDEF"); // Convert 2-digit hex number to decimal int wxHexToDec(const wxString& buf) { int firstDigit, secondDigit; - - if (buf.GetChar(0) >= 'A') - firstDigit = buf.GetChar(0) - 'A' + 10; + + if (buf.GetChar(0) >= wxT('A')) + firstDigit = buf.GetChar(0) - wxT('A') + 10; else - firstDigit = buf.GetChar(0) - '0'; + firstDigit = buf.GetChar(0) - wxT('0'); - if (buf.GetChar(1) >= 'A') - secondDigit = buf.GetChar(1) - 'A' + 10; + if (buf.GetChar(1) >= wxT('A')) + secondDigit = buf.GetChar(1) - wxT('A') + 10; else - secondDigit = buf.GetChar(1) - '0'; - - return firstDigit * 16 + secondDigit; + secondDigit = buf.GetChar(1) - wxT('0'); + + return (firstDigit & 0xF) * 16 + (secondDigit & 0xF ); } // Convert decimal integer to 2-character hex string -void wxDecToHex(int dec, char *buf) +void wxDecToHex(int dec, wxChar *buf) { int firstDigit = (int)(dec/16.0); int secondDigit = (int)(dec - (firstDigit*16.0)); @@ -270,13 +345,13 @@ void wxDecToHex(int dec, char *buf) // Convert decimal integer to 2-character hex string wxString wxDecToHex(int dec) { - char buf[3]; + wxChar buf[3]; wxDecToHex(dec, buf); return wxString(buf); } // Match a string INDEPENDENT OF CASE -bool +bool StringMatch (char *str1, char *str2, bool subString, bool exact) { if (str1 == NULL || str2 == NULL) @@ -293,15 +368,15 @@ StringMatch (char *str1, char *str2, bool subString, bool exact) // Search for str1 in str2 // Slow .... but acceptable for short strings for (i = 0; i <= len2 - len1; i++) - { - if (strncasecmp (str1, str2 + i, len1) == 0) - return TRUE; - } + { + if (strncasecmp (str1, str2 + i, len1) == 0) + return TRUE; + } } else if (exact) { if (strcasecmp (str1, str2) == 0) - return TRUE; + return TRUE; } else { @@ -309,7 +384,7 @@ StringMatch (char *str1, char *str2, bool subString, bool exact) int len2 = strlen (str2); if (strncasecmp (str1, str2, wxMin (len1, len2)) == 0) - return TRUE; + return TRUE; } return FALSE; @@ -317,80 +392,161 @@ StringMatch (char *str1, char *str2, bool subString, bool exact) // Return the current date/time // [volatile] -wxString wxNow( void ) +wxString wxNow() { time_t now = time((time_t *) NULL); - char *date = ctime(&now); + char *date = ctime(&now); date[24] = '\0'; return wxString(date); } -/* Get Full RFC822 style email address */ -bool -wxGetEmailAddress (char *address, int maxSize) -{ - char host[65]; - char user[65]; +#if wxUSE_GUI - if (wxGetHostName(host, 64) == FALSE) - return FALSE; - if (wxGetUserId(user, 64) == FALSE) - return FALSE; - - char tmp[130]; - strcpy(tmp, user); - strcat(tmp, "@"); - strcat(tmp, host); - - strncpy(address, tmp, maxSize - 1); - address[maxSize-1] = '\0'; - return TRUE; -} - -/* - * Strip out any menu codes - */ +// ---------------------------------------------------------------------------- +// Menu accelerators related functions +// ---------------------------------------------------------------------------- -char *wxStripMenuCodes (char *in, char *out) +wxChar *wxStripMenuCodes (wxChar *in, wxChar *out) { if (!in) - return (char *) NULL; - + return (wxChar *) NULL; + if (!out) out = copystring(in); - char *tmpOut = out; - + wxChar *tmpOut = out; + while (*in) { - if (*in == '&') - { - // Check && -> &, &x -> x - if (*++in == '&') - *out++ = *in++; - } - else if (*in == '\t') - { + if (*in == wxT('&')) + { + // Check && -> &, &x -> x + if (*++in == wxT('&')) + *out++ = *in++; + } + else if (*in == wxT('\t')) + { // Remove all stuff after \t in X mode, and let the stuff as is // in Windows mode. // Accelerators are handled in wx_item.cc for Motif, and are not // YET supported in XView - break; - } + break; + } else - *out++ = *in++; - } // while + *out++ = *in++; + } // while - *out = '\0'; + *out = wxT('\0'); return tmpOut; } +wxString wxStripMenuCodes(const wxString& str) +{ + wxChar *buf = new wxChar[str.Length() + 1]; + wxStripMenuCodes(WXSTRINGCAST str, buf); + wxString str1(buf); + delete[] buf; + return str1; +} -/* - * Window search functions - * - */ +#if wxUSE_ACCEL + +// return wxAcceleratorEntry for the given menu string or NULL if none +// specified +wxAcceleratorEntry *wxGetAccelFromString(const wxString& label) +{ + // check for accelerators: they are given after '\t' + int posTab = label.Find(wxT('\t')); + if ( posTab != wxNOT_FOUND ) { + // parse the accelerator string + int keyCode = 0; + int accelFlags = wxACCEL_NORMAL; + wxString current; + for ( size_t n = (size_t)posTab + 1; n < label.Len(); n++ ) { + if ( (label[n] == '+') || (label[n] == '-') ) { + if ( current == _("ctrl") ) + accelFlags |= wxACCEL_CTRL; + else if ( current == _("alt") ) + accelFlags |= wxACCEL_ALT; + else if ( current == _("shift") ) + accelFlags |= wxACCEL_SHIFT; + else { + wxLogDebug(wxT("Unknown accel modifier: '%s'"), + current.c_str()); + } + + current.Empty(); + } + else { + current += wxTolower(label[n]); + } + } + + if ( current.IsEmpty() ) { + wxLogDebug(wxT("No accel key found, accel string ignored.")); + } + else { + if ( current.Len() == 1 ) { + // it's a letter + keyCode = wxToupper(current[0U]); + } + else { + // is it a function key? + if ( current[0U] == 'f' && isdigit(current[1U]) && + (current.Len() == 2 || + (current.Len() == 3 && isdigit(current[2U]))) ) { + int n; + wxSscanf(current.c_str() + 1, wxT("%d"), &n); + + keyCode = WXK_F1 + n - 1; + } + else { + // several special cases + current.MakeUpper(); + if ( current == _("DEL") ) { + keyCode = WXK_DELETE; + } + else if ( current == _("DELETE") ) { + keyCode = WXK_DELETE; + } + else if ( current == _("INS") ) { + keyCode = WXK_INSERT; + } + else if ( current == _("INSERT") ) { + keyCode = WXK_INSERT; + } +#if 0 + else if ( current == _("PGUP") ) { + keyCode = VK_PRIOR; + } + else if ( current == _("PGDN") ) { + keyCode = VK_NEXT; + } +#endif + else + { + wxLogDebug(wxT("Unrecognized accel key '%s', accel string ignored."), + current.c_str()); + } + } + } + } + + if ( keyCode ) { + // we do have something + return new wxAcceleratorEntry(accelFlags, keyCode); + } + } + + return (wxAcceleratorEntry *)NULL; +} + +#endif // wxUSE_ACCEL + +// ---------------------------------------------------------------------------- +// Window search functions +// ---------------------------------------------------------------------------- /* * If parent is non-NULL, look through children for a label or title @@ -398,53 +554,54 @@ char *wxStripMenuCodes (char *in, char *out) * */ -static wxWindow *wxFindWindowByLabel1 (const wxString& title, wxWindow * parent); - wxWindow * wxFindWindowByLabel (const wxString& title, wxWindow * parent) { - if (parent) + if (parent) { - return wxFindWindowByLabel1 (title, parent); + return wxFindWindowByLabel1(title, parent); } - else + else { - for (wxNode * node = wxTopLevelWindows.First (); node; node = node->Next ()) - { - wxWindow *win = (wxWindow *) node->Data (); - wxWindow *retwin = wxFindWindowByLabel1 (title, win); - if (retwin) - return retwin; - } // for() + for ( wxWindowList::Node * node = wxTopLevelWindows.GetFirst(); + node; + node = node->GetNext() ) + { + wxWindow *win = node->GetData(); + wxWindow *retwin = wxFindWindowByLabel1 (title, win); + if (retwin) + return retwin; + } // for() } - return (wxWindow *) NULL; + return (wxWindow *) NULL; } // Recursive static wxWindow * wxFindWindowByLabel1 (const wxString& title, wxWindow * parent) { - if (parent) + if (parent) { - if (parent->GetLabel() == title) - return parent; + if (parent->GetLabel() == title) + return parent; } - if (parent) + if (parent) { - for (wxNode * node = parent->GetChildren()->First (); node; node = node->Next ()) - { - wxWindow *win = (wxWindow *) node->Data (); - wxWindow *retwin = wxFindWindowByLabel1 (title, win); - if (retwin) - return retwin; - } // for() + for ( wxWindowList::Node * node = parent->GetChildren().GetFirst(); + node; + node = node->GetNext() ) + { + wxWindow *win = (wxWindow *)node->GetData(); + wxWindow *retwin = wxFindWindowByLabel1 (title, win); + if (retwin) + return retwin; + } } - return (wxWindow *) NULL; // Not found - + return (wxWindow *) NULL; // Not found } /* @@ -453,28 +610,29 @@ wxFindWindowByLabel1 (const wxString& title, wxWindow * parent) * */ -static wxWindow *wxFindWindowByName1 (const wxString& title, wxWindow * parent); - wxWindow * wxFindWindowByName (const wxString& title, wxWindow * parent) { - if (parent) + if (parent) { - return wxFindWindowByName1 (title, parent); + return wxFindWindowByName1 (title, parent); } - else + else { - for (wxNode * node = wxTopLevelWindows.First (); node; node = node->Next ()) - { - wxWindow *win = (wxWindow *) node->Data (); - wxWindow *retwin = wxFindWindowByName1 (title, win); - if (retwin) - return retwin; - } // for() + for ( wxWindowList::Node * node = wxTopLevelWindows.GetFirst(); + node; + node = node->GetNext() ) + { + wxWindow *win = node->GetData(); + wxWindow *retwin = wxFindWindowByName1 (title, win); + if (retwin) + return retwin; + } } - // Failed? Try by label instead. - return wxFindWindowByLabel(title, parent); + + // Failed? Try by label instead. + return wxFindWindowByLabel(title, parent); } // Recursive @@ -483,28 +641,28 @@ wxFindWindowByName1 (const wxString& title, wxWindow * parent) { if (parent) { - if ( parent->GetName() == title ) - return parent; + if ( parent->GetName() == title ) + return parent; } if (parent) { - for (wxNode * node = parent->GetChildren()->First (); node; node = node->Next ()) - { - wxWindow *win = (wxWindow *) node->Data (); - wxWindow *retwin = wxFindWindowByName1 (title, win); - if (retwin) - return retwin; - } // for() + for (wxNode * node = parent->GetChildren().First (); node; node = node->Next ()) + { + wxWindow *win = (wxWindow *) node->Data (); + wxWindow *retwin = wxFindWindowByName1 (title, win); + if (retwin) + return retwin; + } // for() } - return (wxWindow *) NULL; // Not found + return (wxWindow *) NULL; // Not found } // Returns menu item id or -1 if none. -int +int wxFindMenuItemId (wxFrame * frame, const wxString& menuString, const wxString& itemString) { wxMenuBar *menuBar = frame->GetMenuBar (); @@ -513,49 +671,96 @@ wxFindMenuItemId (wxFrame * frame, const wxString& menuString, const wxString& i return menuBar->FindMenuItem (menuString, itemString); } -/* - * wxDebugStreamBuf - */ -#if !defined(_WINDLL) - -wxDebugStreamBuf::wxDebugStreamBuf(void) +// Try to find the deepest child that contains 'pt'. +// We go backwards, to try to allow for controls that are spacially +// within other controls, but are still siblings (e.g. buttons within +// static boxes). Static boxes are likely to be created _before_ controls +// that sit inside them. +wxWindow* wxFindWindowAtPoint(wxWindow* win, const wxPoint& pt) { - if (allocate()) setp(base(),ebuf()); -} + if (!win->IsShown()) + return NULL; -int wxDebugStreamBuf::overflow(int WXUNUSED(i)) -{ - int len = pptr() - pbase(); - char *txt = new char[len+1]; - strncpy(txt, pbase(), len); - txt[len] = '\0'; -#ifdef __WXMSW__ - OutputDebugString((LPCSTR)txt); -#else - fprintf(stderr, txt); -#endif - setp(pbase(), epptr()); - delete[] txt; - return EOF; + // Hack for wxNotebook case: at least in wxGTK, all pages + // claim to be shown, so we must only deal with the selected one. + if (win->IsKindOf(CLASSINFO(wxNotebook))) + { + wxNotebook* nb = (wxNotebook*) win; + int sel = nb->GetSelection(); + if (sel >= 0) + { + wxWindow* child = nb->GetPage(sel); + wxWindow* foundWin = wxFindWindowAtPoint(child, pt); + if (foundWin) + return foundWin; + } + } + /* Doesn't work + // Frame case + else if (win->IsKindOf(CLASSINFO(wxFrame))) + { + // Pseudo-children that may not be mentioned in the child list + wxWindowList extraChildren; + wxFrame* frame = (wxFrame*) win; + if (frame->GetStatusBar()) + extraChildren.Append(frame->GetStatusBar()); + if (frame->GetToolBar()) + extraChildren.Append(frame->GetToolBar()); + + wxNode* node = extraChildren.First(); + while (node) + { + wxWindow* child = (wxWindow*) node->Data(); + wxWindow* foundWin = wxFindWindowAtPoint(child, pt); + if (foundWin) + return foundWin; + node = node->Next(); + } + } + */ + + wxNode* node = win->GetChildren().Last(); + while (node) + { + wxWindow* child = (wxWindow*) node->Data(); + wxWindow* foundWin = wxFindWindowAtPoint(child, pt); + if (foundWin) + return foundWin; + node = node->Previous(); + } + + wxPoint pos = win->GetPosition(); + wxSize sz = win->GetSize(); + if (win->GetParent()) + { + pos = win->GetParent()->ClientToScreen(pos); + } + + wxRect rect(pos, sz); + if (rect.Inside(pt)) + return win; + else + return NULL; } -int wxDebugStreamBuf::sync(void) +wxWindow* wxGenericFindWindowAtPoint(const wxPoint& pt) { - int len = pptr() - pbase(); - char *txt = new char[len+1]; - strncpy(txt, pbase(), len); - txt[len] = '\0'; -#ifdef __WXMSW__ - OutputDebugString((LPCSTR)txt); -#else - fprintf(stderr, txt); -#endif - setp(pbase(), epptr()); - delete[] txt; - return 0; + // Go backwards through the list since windows + // on top are likely to have been appended most + // recently. + wxNode* node = wxTopLevelWindows.Last(); + while (node) + { + wxWindow* win = (wxWindow*) node->Data(); + wxWindow* found = wxFindWindowAtPoint(win, pt); + if (found) + return found; + node = node->Previous(); + } + return NULL; } -#endif +#endif // wxUSE_GUI /* On Fri, 21 Jul 1995, Paul Craven wrote: @@ -563,12 +768,12 @@ On Fri, 21 Jul 1995, Paul Craven wrote: > Is there a way to find the path of running program's executable? I can get > my home directory, and the current directory, but I don't know how to get the > executable directory. -> +> The code below (warty as it is), does what you want on most Unix, DOS, and Mac platforms (it's from the ALS Prolog main). -|| Ken Bowen Applied Logic Systems, Inc. PO Box 180, +|| Ken Bowen Applied Logic Systems, Inc. PO Box 180, ||==== Voice: +1 (617)965-9191 Newton Centre, || FAX: +1 (617)965-1636 MA 02159 USA Email: ken@als.com WWW: http://www.als.com @@ -581,8 +786,8 @@ DOS, and Mac platforms (it's from the ALS Prolog main). /*--------------------------------------------------------------------* | whereami is given a filename f in the form: whereami(argv[0]) - | It returns the directory in which the executable file (containing - | this code [main.c] ) may be found. A dot will be returned to indicate + | It returns the directory in which the executable file (containing + | this code [main.c] ) may be found. A dot will be returned to indicate | the current directory. *--------------------------------------------------------------------*/ @@ -590,7 +795,7 @@ static void whereami(name) char *name; { - register char *cutoff = NULL; /* stifle -Wall */ + register char *cutoff = NULL; /* stifle -Wall */ register char *s; register char *t; int cc; @@ -603,117 +808,117 @@ whereami(name) if (access(name, R_OK) == 0) { - /*-------------------------------------------------------------* - * The file was accessible without any other work. But the current - * working directory might change on us, so if it was accessible - * through the cwd, then we should get it for later accesses. - *-------------------------------------------------------------*/ + /*-------------------------------------------------------------* + * The file was accessible without any other work. But the current + * working directory might change on us, so if it was accessible + * through the cwd, then we should get it for later accesses. + *-------------------------------------------------------------*/ - t = imagedir; - if (!absolute_pathname(name)) { + t = imagedir; + if (!absolute_pathname(name)) { #if defined(DOS) || defined(__WIN32__) - int drive; - char *newrbuf; + int drive; + char *newrbuf; - newrbuf = imagedir; + newrbuf = imagedir; #ifndef __DJGPP__ - if (*(name + 1) == ':') { - if (*name >= 'a' && *name <= 'z') - drive = (int) (*name - 'a' + 1); - else - drive = (int) (*name - 'A' + 1); - *newrbuf++ = *name; - *newrbuf++ = *(name + 1); - *newrbuf++ = DIR_SEPARATOR; - } - else { - drive = 0; - *newrbuf++ = DIR_SEPARATOR; - } - if (getcwd(newrbuf, drive) == 0) { /* } */ + if (*(name + 1) == ':') { + if (*name >= 'a' && *name <= 'z') + drive = (int) (*name - 'a' + 1); + else + drive = (int) (*name - 'A' + 1); + *newrbuf++ = *name; + *newrbuf++ = *(name + 1); + *newrbuf++ = DIR_SEPARATOR; + } + else { + drive = 0; + *newrbuf++ = DIR_SEPARATOR; + } + if (getcwd(newrbuf, drive) == 0) { /* } */ #else - if (getcwd(newrbuf, 1024) == 0) { /* } */ + if (getcwd(newrbuf, 1024) == 0) { /* } */ #endif #else /* DOS */ #ifdef HAVE_GETWD - if (getwd(imagedir) == 0) { /* } */ + if (getwd(imagedir) == 0) { /* } */ #else /* !HAVE_GETWD */ - if (getcwd(imagedir, 1024) == 0) { + if (getcwd(imagedir, 1024) == 0) { #endif /* !HAVE_GETWD */ #endif /* DOS */ - fatal_error(FE_GETCWD, 0); - } - for (; *t; t++) /* Set t to end of buffer */ - ; - if (*(t - 1) == DIR_SEPARATOR) /* leave slash if already - * last char - */ - cutoff = t - 1; - else { - cutoff = t; /* otherwise put one in */ - *t++ = DIR_SEPARATOR; - } - } + fatal_error(FE_GETCWD, 0); + } + for (; *t; t++) /* Set t to end of buffer */ + ; + if (*(t - 1) == DIR_SEPARATOR) /* leave slash if already + * last char + */ + cutoff = t - 1; + else { + cutoff = t; /* otherwise put one in */ + *t++ = DIR_SEPARATOR; + } + } #if (!defined(__MAC__) && !defined(__DJGPP__) && !defined(__GO32__) && !defined(__WIN32__)) - else - (*t++ = DIR_SEPARATOR); + else + (*t++ = DIR_SEPARATOR); #endif - /*-------------------------------------------------------------* - * Copy the rest of the string and set the cutoff if it was not - * already set. If the first character of name is a slash, cutoff - * is not presently set but will be on the first iteration of the - * loop below. - *-------------------------------------------------------------*/ + /*-------------------------------------------------------------* + * Copy the rest of the string and set the cutoff if it was not + * already set. If the first character of name is a slash, cutoff + * is not presently set but will be on the first iteration of the + * loop below. + *-------------------------------------------------------------*/ - for ((*name == DIR_SEPARATOR ? (s = name+1) : (s = name));;) { - if (*s == DIR_SEPARATOR) - cutoff = t; - if (!(*t++ = *s++)) - break; - } + for ((*name == DIR_SEPARATOR ? (s = name+1) : (s = name));;) { + if (*s == DIR_SEPARATOR) + cutoff = t; + if (!(*t++ = *s++)) + break; + } } else { - /*-------------------------------------------------------------* - * Get the path list from the environment. If the path list is - * inaccessible for any reason, leave with fatal error. - *-------------------------------------------------------------*/ + /*-------------------------------------------------------------* + * Get the path list from the environment. If the path list is + * inaccessible for any reason, leave with fatal error. + *-------------------------------------------------------------*/ #ifdef __MAC__ - if ((s = getenv("Commands")) == (char *) 0) + if ((s = getenv("Commands")) == (char *) 0) #else - if ((s = getenv("PATH")) == (char *) 0) + if ((s = getenv("PATH")) == (char *) 0) #endif - fatal_error(FE_PATH, 0); - - /* - * Copy path list into ebuf and set the source pointer to the - * beginning of this buffer. - */ - - strcpy(ebuf, s); - s = ebuf; - - for (;;) { - t = imagedir; - while (*s && *s != PATH_SEPARATOR) - *t++ = *s++; - if (t > imagedir && *(t - 1) == DIR_SEPARATOR) - ; /* do nothing -- slash already is in place */ - else - *t++ = DIR_SEPARATOR; /* put in the slash */ - cutoff = t - 1; /* set cutoff */ - strcpy(t, name); - if (access(imagedir, R_OK) == 0) - break; - - if (*s) - s++; /* advance source pointer */ - else - fatal_error(FE_INFND, 0); - } + fatal_error(FE_PATH, 0); + + /* + * Copy path list into ebuf and set the source pointer to the + * beginning of this buffer. + */ + + strcpy(ebuf, s); + s = ebuf; + + for (;;) { + t = imagedir; + while (*s && *s != PATH_SEPARATOR) + *t++ = *s++; + if (t > imagedir && *(t - 1) == DIR_SEPARATOR) + ; /* do nothing -- slash already is in place */ + else + *t++ = DIR_SEPARATOR; /* put in the slash */ + cutoff = t - 1; /* set cutoff */ + strcpy(t, name); + if (access(imagedir, R_OK) == 0) + break; + + if (*s) + s++; /* advance source pointer */ + else + fatal_error(FE_INFND, 0); + } } @@ -726,30 +931,36 @@ whereami(name) #ifdef HAVE_SYMLINK while ((cc = readlink(imagedir, ebuf, 512)) != -1) { - ebuf[cc] = 0; - s = ebuf; - if (*s == DIR_SEPARATOR) { - t = imagedir; - } - else { - t = cutoff + 1; - } - for (;;) { - if (*s == DIR_SEPARATOR) - cutoff = t; /* mark the last slash seen */ - if (!(*t++ = *s++)) /* copy the character */ - break; - } + ebuf[cc] = 0; + s = ebuf; + if (*s == DIR_SEPARATOR) { + t = imagedir; + } + else { + t = cutoff + 1; + } + for (;;) { + if (*s == DIR_SEPARATOR) + cutoff = t; /* mark the last slash seen */ + if (!(*t++ = *s++)) /* copy the character */ + break; + } } #endif /* HAVE_SYMLINK */ - strcpy(imagename, cutoff + 1); /* keep the image name */ - *(cutoff + 1) = 0; /* chop off the filename part */ + strcpy(imagename, cutoff + 1); /* keep the image name */ + *(cutoff + 1) = 0; /* chop off the filename part */ } #endif +#if wxUSE_GUI + +// ---------------------------------------------------------------------------- +// GUI helpers +// ---------------------------------------------------------------------------- + /* * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp * since otherwise the generic code may be pulled in unnecessarily. @@ -765,29 +976,392 @@ int wxMessageBox(const wxString& message, const wxString& caption, long style, { case wxID_OK: return wxOK; - break; case wxID_YES: return wxYES; - break; case wxID_NO: return wxNO; - break; - default: case wxID_CANCEL: return wxCANCEL; - break; } - return ans; + + wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") ); + + return wxCANCEL; } +#if wxUSE_TEXTDLG wxString wxGetTextFromUser(const wxString& message, const wxString& caption, const wxString& defaultValue, wxWindow *parent, int x, int y, bool WXUNUSED(centre) ) { + wxString str; wxTextEntryDialog dialog(parent, message, caption, defaultValue, wxOK|wxCANCEL, wxPoint(x, y)); if (dialog.ShowModal() == wxID_OK) - return dialog.GetValue(); - else - return wxString(""); + { + str = dialog.GetValue(); + } + + return str; } +wxString wxGetPasswordFromUser(const wxString& message, + const wxString& caption, + const wxString& defaultValue, + wxWindow *parent) +{ + wxString str; + wxTextEntryDialog dialog(parent, message, caption, defaultValue, + wxOK | wxCANCEL | wxTE_PASSWORD); + if ( dialog.ShowModal() == wxID_OK ) + { + str = dialog.GetValue(); + } + + return str; +} + +#endif // wxUSE_TEXTDLG + +wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit) +{ + wxColourData data; + data.SetChooseFull(TRUE); + if ( colInit.Ok() ) + { + data.SetColour((wxColour &)colInit); // const_cast + } + + wxColour colRet; + wxColourDialog dialog(parent, &data); + if ( dialog.ShowModal() == wxID_OK ) + { + colRet = dialog.GetColourData().GetColour(); + } + //else: leave it invalid + + return colRet; +} + +// ---------------------------------------------------------------------------- +// missing C RTL functions (FIXME shouldn't be here at all) +// ---------------------------------------------------------------------------- + +#ifdef __MWERKS__ +char *strdup(const char *s) +{ + return strcpy( (char*) malloc( strlen( s ) + 1 ) , s ) ; +} + +int isascii( int c ) +{ + return ( c >= 0 && c < 128 ) ; +} +#endif // __MWERKS__ + +// ---------------------------------------------------------------------------- +// wxSafeYield and supporting functions +// ---------------------------------------------------------------------------- + +void wxEnableTopLevelWindows(bool enable) +{ + wxWindowList::Node *node; + for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() ) + node->GetData()->Enable(enable); +} + +wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip) +{ + // remember the top level windows which were already disabled, so that we + // don't reenable them later + m_winDisabled = NULL; + + wxWindowList::Node *node; + for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() ) + { + wxWindow *winTop = node->GetData(); + if ( winTop == winToSkip ) + continue; + + if ( winTop->IsEnabled() ) + { + winTop->Disable(); + } + else + { + if ( !m_winDisabled ) + { + m_winDisabled = new wxWindowList; + } + + m_winDisabled->Append(winTop); + } + } +} + +wxWindowDisabler::~wxWindowDisabler() +{ + wxWindowList::Node *node; + for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() ) + { + wxWindow *winTop = node->GetData(); + if ( !m_winDisabled || !m_winDisabled->Find(winTop) ) + { + winTop->Enable(); + } + //else: had been already disabled, don't reenable + } + + delete m_winDisabled; +} + +// Yield to other apps/messages and disable user input to all windows except +// the given one +bool wxSafeYield(wxWindow *win) +{ + wxWindowDisabler wd(win); + + bool rc = wxYield(); + + return rc; +} + +// ---------------------------------------------------------------------------- +// misc functions +// ---------------------------------------------------------------------------- + +// Don't synthesize KeyUp events holding down a key and producing KeyDown +// events with autorepeat. On by default and always on in wxMSW. wxGTK version +// in utilsgtk.cpp. +#ifndef __WXGTK__ +bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) ) +{ + return TRUE; // detectable auto-repeat is the only mode MSW supports +} +#endif // !wxGTK + +#endif // wxUSE_GUI + +// ---------------------------------------------------------------------------- +// network and user id functions +// ---------------------------------------------------------------------------- + +// Get Full RFC822 style email address +bool wxGetEmailAddress(wxChar *address, int maxSize) +{ + wxString email = wxGetEmailAddress(); + if ( !email ) + return FALSE; + + wxStrncpy(address, email, maxSize - 1); + address[maxSize - 1] = wxT('\0'); + + return TRUE; +} + +wxString wxGetEmailAddress() +{ + wxString email; + + wxString host = wxGetFullHostName(); + if ( !!host ) + { + wxString user = wxGetUserId(); + if ( !!user ) + { + email << user << wxT('@') << host; + } + } + + return email; +} + +wxString wxGetUserId() +{ + static const int maxLoginLen = 256; // FIXME arbitrary number + + wxString buf; + bool ok = wxGetUserId(buf.GetWriteBuf(maxLoginLen), maxLoginLen); + buf.UngetWriteBuf(); + + if ( !ok ) + buf.Empty(); + + return buf; +} + +wxString wxGetUserName() +{ + static const int maxUserNameLen = 1024; // FIXME arbitrary number + + wxString buf; + bool ok = wxGetUserName(buf.GetWriteBuf(maxUserNameLen), maxUserNameLen); + buf.UngetWriteBuf(); + + if ( !ok ) + buf.Empty(); + + return buf; +} + +wxString wxGetHostName() +{ + static const size_t hostnameSize = 257; + + wxString buf; + bool ok = wxGetHostName(buf.GetWriteBuf(hostnameSize), hostnameSize); + + buf.UngetWriteBuf(); + + if ( !ok ) + buf.Empty(); + + return buf; +} + +wxString wxGetFullHostName() +{ + static const size_t hostnameSize = 257; + + wxString buf; + bool ok = wxGetFullHostName(buf.GetWriteBuf(hostnameSize), hostnameSize); + + buf.UngetWriteBuf(); + + if ( !ok ) + buf.Empty(); + + return buf; +} + +wxString wxGetHomeDir() +{ + wxString home; + wxGetHomeDir(&home); + + return home; +} + +#if 0 + +wxString wxGetCurrentDir() +{ + wxString dir; + size_t len = 1024; + bool ok; + do + { + ok = getcwd(dir.GetWriteBuf(len + 1), len) != NULL; + dir.UngetWriteBuf(); + + if ( !ok ) + { + if ( errno != ERANGE ) + { + wxLogSysError(_T("Failed to get current directory")); + + return wxEmptyString; + } + else + { + // buffer was too small, retry with a larger one + len *= 2; + } + } + //else: ok + } while ( !ok ); + + return dir; +} + +#endif // 0 + +// ---------------------------------------------------------------------------- +// wxExecute +// ---------------------------------------------------------------------------- + +// this is a private function because it hasn't a clean interface: the first +// array is passed by reference, the second by pointer - instead we have 2 +// public versions of wxExecute() below +static long wxDoExecuteWithCapture(const wxString& command, + wxArrayString& output, + wxArrayString* error) +{ +#ifdef __WIN16__ + wxFAIL_MSG("Sorry, this version of wxExecute not implemented on WIN16."); + + return 0; +#else // !Win16 + // create a wxProcess which will capture the output + wxProcess *process = new wxProcess; + process->Redirect(); + + long rc = wxExecute(command, TRUE /* sync */, process); + +#if wxUSE_STREAMS + if ( rc != -1 ) + { + wxInputStream* is = process->GetInputStream(); + wxCHECK_MSG( is, -1, _T("if wxExecute() succeded, stream can't be NULL") ); + wxTextInputStream tis(*is); + + wxTextInputStream *tes = NULL; + wxInputStream *es = NULL; + if ( error ) + { + es = process->GetErrorStream(); + + wxCHECK_MSG( es, -1, _T("stderr can't be NULL") ); + + tes = new wxTextInputStream(*es); + } + + bool cont; + do + { + cont = FALSE; + + if ( !is->Eof() && is->IsOk() ) + { + wxString line = tis.ReadLine(); + if ( is->LastError() ) + break; + + cont = TRUE; + + output.Add(line); + } + + if ( error && !es->Eof() && es->IsOk() ) + { + wxString line = tes->ReadLine(); + if ( es->LastError() ) + break; + + cont = TRUE; + + error->Add(line); + } + } + while ( cont ); + + delete tes; + } +#endif // wxUSE_STREAMS + + delete process; + + return rc; +#endif // IO redirection supoprted +} + +long wxExecute(const wxString& command, wxArrayString& output) +{ + return wxDoExecuteWithCapture(command, output, NULL); +} + +long wxExecute(const wxString& command, + wxArrayString& output, + wxArrayString& error) +{ + return wxDoExecuteWithCapture(command, output, &error); +}