]> git.saurik.com Git - wxWidgets.git/blame - utils/configtool/src/utils.cpp
wxCocoa build fix. Use XPM everywhere.
[wxWidgets.git] / utils / configtool / src / utils.cpp
CommitLineData
d7463f75
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: utils.cpp
3// Purpose: Utility functions and classes
4// Author: Julian Smart
5// Modified by:
6// Created: 2002-09-04
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
4fe30bce 9// Licence:
d7463f75
JS
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13// #pragma implementation
14#endif
15
d9ab621e
WS
16// For compilers that support precompilation, includes "wx/wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#include <math.h>
24
25#ifndef WX_PRECOMP
26
d7463f75 27#include "wx/splitter.h"
d7463f75
JS
28#include "wx/datstrm.h"
29#include "wx/file.h"
30#include "wx/listctrl.h"
d7463f75 31#include "wx/process.h"
d7463f75 32#include "wx/variant.h"
d7463f75 33#include "wx/cmdline.h"
60c474a0
MB
34#include "wx/msgdlg.h"
35#include "wx/log.h"
d21f1d8f
MB
36#include "wx/sizer.h"
37#include "wx/icon.h"
a04a377a 38#include "wx/intl.h"
d7463f75 39
d7463f75
JS
40#endif
41
d9ab621e
WS
42#include "wx/wfstream.h"
43#include "wx/cshelp.h"
44#include "wx/image.h"
45#include "wx/imaglist.h"
46#include "wx/tokenzr.h"
47#include "wx/notebook.h"
48#include "wx/mimetype.h"
d7463f75
JS
49#include "utils.h"
50
51// Returns the image type, or -1, determined from the extension.
52int apDetermineImageType(const wxString& filename)
53{
54 wxString path, name, ext;
55
56 wxSplitPath(filename, & path, & name, & ext);
57
58 ext.MakeLower();
69da0d99 59 if (ext == _T("jpg") || ext == _T("jpeg"))
d7463f75 60 return wxBITMAP_TYPE_JPEG;
69da0d99 61 else if (ext == _T("gif"))
d7463f75 62 return wxBITMAP_TYPE_GIF;
69da0d99 63 else if (ext == _T("bmp"))
d7463f75 64 return wxBITMAP_TYPE_BMP;
69da0d99 65 else if (ext == _T("png"))
d7463f75 66 return wxBITMAP_TYPE_PNG;
69da0d99 67 else if (ext == _T("pcx"))
d7463f75 68 return wxBITMAP_TYPE_PCX;
69da0d99 69 else if (ext == _T("tif") || ext == _T("tiff"))
d7463f75
JS
70 return wxBITMAP_TYPE_TIF;
71 else
72 return -1;
73}
74
75// Convert a colour to a 6-digit hex string
76wxString apColourToHexString(const wxColour& col)
77{
78 wxString hex;
79
80 hex += wxDecToHex(col.Red());
81 hex += wxDecToHex(col.Green());
82 hex += wxDecToHex(col.Blue());
83
84 return hex;
85}
86
87// Convert 6-digit hex string to a colour
88wxColour apHexStringToColour(const wxString& hex)
89{
254a2129
WS
90 unsigned char r = (unsigned char)wxHexToDec(hex.Mid(0, 2));
91 unsigned char g = (unsigned char)wxHexToDec(hex.Mid(2, 2));
92 unsigned char b = (unsigned char)wxHexToDec(hex.Mid(4, 2));
d7463f75
JS
93
94 return wxColour(r, g, b);
95}
96
97// Convert a wxFont to a string
98wxString apFontToString(const wxFont& font)
99{
100 wxString str;
101 str.Printf(wxT("%d,%d,%d,%d,%d,%s"), (int) font.GetPointSize(),
102 (int) font.GetFamily(), (int) font.GetStyle(), (int) font.GetWeight(),
103 (int) font.GetUnderlined(), font.GetFaceName().c_str());
104
105 return str;
106}
107
3ac35b57
MB
108static inline int StringToInt(const wxString& s)
109{
110 long tmp;
111 s.ToLong(&tmp);
112
113 return int(tmp);
114}
115
d7463f75
JS
116// Convert a string to a wxFont
117wxFont apStringToFont(const wxString& str)
118{
119 int pointSize = 12;
120 int family = wxSWISS;
121 int style = wxNORMAL;
122 int weight = wxNORMAL;
123 int underlined = 0;
a04a377a 124 wxString facename;
d7463f75
JS
125
126 wxStringTokenizer tkz(str, wxT(","));
127 int i = 0;
128 while (tkz.HasMoreTokens())
129 {
130 wxString token = tkz.GetNextToken();
131
132 if (i == 0)
133 {
3ac35b57 134 pointSize = StringToInt(token);
d7463f75
JS
135#if defined(__WXGTK__) || defined(__WXMAC__)
136 if (pointSize < 8)
137 pointSize = 8;
138 if (pointSize == 9)
139 pointSize = 10;
254a2129 140#endif
d7463f75
JS
141 }
142 else if (i == 1)
3ac35b57 143 family = StringToInt(token);
d7463f75 144 else if (i == 2)
3ac35b57 145 style = StringToInt(token);
d7463f75 146 else if (i == 3)
3ac35b57 147 weight = StringToInt(token);
d7463f75 148 else if (i == 4)
3ac35b57 149 underlined = StringToInt(token);
d7463f75
JS
150 else if (i == 5)
151 {
152 facename = token;
153#if defined(__WXGTK__)
154 if (facename == wxT("Arial"))
155 facename = wxT("helvetica");
156#endif
157 }
158 i ++;
159
160 }
161 return wxFont(pointSize, family, style, weight, (underlined != 0), facename);
162}
163
164
165// Get the index of the given named wxNotebook page
166int apFindNotebookPage(wxNotebook* notebook, const wxString& name)
167{
168 int i;
69da0d99 169 for (i = 0; i < (int)notebook->GetPageCount(); i++)
d7463f75
JS
170 if (name == notebook->GetPageText(i))
171 return i;
172 return -1;
173}
174
175/*
176 * View an HTML file
177 */
178
179void apViewHTMLFile(const wxString& url)
180{
181#ifdef __WXMSW__
182 HKEY hKey;
183 TCHAR szCmdName[1024];
184 DWORD dwType, dw = sizeof(szCmdName);
185 LONG lRes;
69da0d99 186 lRes = RegOpenKey(HKEY_CLASSES_ROOT, _T("htmlfile\\shell\\open\\command"), &hKey);
d7463f75
JS
187 if(lRes == ERROR_SUCCESS && RegQueryValueEx(hKey,(LPTSTR)NULL, NULL,
188 &dwType, (LPBYTE)szCmdName, &dw) == ERROR_SUCCESS)
189 {
69da0d99 190 wxStrcat(szCmdName, (const wxChar*) url);
d7463f75
JS
191 PROCESS_INFORMATION piProcInfo;
192 STARTUPINFO siStartInfo;
193 memset(&siStartInfo, 0, sizeof(STARTUPINFO));
194 siStartInfo.cb = sizeof(STARTUPINFO);
4fe30bce 195 CreateProcess(NULL, szCmdName, NULL, NULL, false, 0, NULL,
d7463f75
JS
196 NULL, &siStartInfo, &piProcInfo );
197 }
198 if(lRes == ERROR_SUCCESS)
199 RegCloseKey(hKey);
200#else
201 wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(wxT("html"));
202 if ( !ft )
203 {
204 wxLogError(_T("Impossible to determine the file type for extension html. Please edit your MIME types."));
205 return ;
206 }
207
208 wxString cmd;
209 bool ok = ft->GetOpenCommand(&cmd,
a04a377a 210 wxFileType::MessageParameters(url, wxEmptyString));
d7463f75
JS
211 delete ft;
212
213 if (!ok)
214 {
215 // TODO: some kind of configuration dialog here.
216 wxMessageBox(_("Could not determine the command for running the browser."),
4fe30bce 217 wxT("Browsing problem"), wxOK|wxICON_EXCLAMATION);
d7463f75
JS
218 return ;
219 }
220
4fe30bce 221 ok = (wxExecute(cmd, false) != 0);
d7463f75
JS
222#endif
223}
224
225wxString wxGetTempDir()
226{
227 wxString dir;
228#if defined(__WXMAC__) && !defined(__DARWIN__)
229 dir = wxMacFindFolder( (short) kOnSystemDisk, kTemporaryFolderType, kCreateFolder ) ;
230#else // !Mac
d9ab621e
WS
231 wxString dirEnv(wxGetenv(_T("TMP")));
232 dir = dirEnv;
d7463f75
JS
233 if ( dir.empty() )
234 {
d9ab621e
WS
235 wxString envVar(wxGetenv(_T("TEMP")));
236 dir = envVar;
d7463f75 237 }
254a2129 238
d7463f75
JS
239 if ( dir.empty() )
240 {
241 // default
242#ifdef __DOS__
243 dir = _T(".");
244#else
245 dir = _T("/tmp");
246#endif
247 }
248#endif // Mac/!Mac
249 return dir;
250}
251
252// Invoke app for file type
253// Eventually we should allow the user to select an app.
254bool apInvokeAppForFile(const wxString& filename)
255{
256 wxString path, file, ext;
257 wxSplitPath(filename, & path, & file, & ext);
258
259 wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(ext);
260 if ( !ft )
261 {
262 wxString msg;
263 msg.Printf(wxT("Sorry, could not determine what application to invoke for extension %s\nYou may need to edit your MIME types."),
264 ext.c_str());
265 wxMessageBox(msg, wxT("Application Invocation"), wxICON_EXCLAMATION|wxOK);
4fe30bce 266 return false;
d7463f75
JS
267 }
268
269 wxString cmd;
a04a377a 270 ft->GetOpenCommand(&cmd, wxFileType::MessageParameters(filename, wxEmptyString));
d7463f75
JS
271 delete ft;
272
4fe30bce 273 return (wxExecute(cmd, false) != 0);
d7463f75
JS
274}
275
276// Find the absolute path where this application has been run from.
277// argv0 is wxTheApp->argv[0]
278// cwd is the current working directory (at startup)
279// appVariableName is the name of a variable containing the directory for this app, e.g.
280// MYAPPDIR. This is checked first.
281
282wxString apFindAppPath(const wxString& argv0, const wxString& cwd, const wxString& appVariableName)
283{
d7463f75 284 // Try appVariableName
a04a377a 285 if (!appVariableName.empty())
d7463f75 286 {
d9ab621e 287 wxString strVar(wxGetenv(appVariableName.c_str()));
a04a377a 288 if (!strVar.empty())
d9ab621e 289 return strVar;
d7463f75
JS
290 }
291
292 if (wxIsAbsolutePath(argv0))
293 return wxPathOnly(argv0);
294 else
295 {
296 // Is it a relative path?
297 wxString currentDir(cwd);
298 if (currentDir.Last() != wxFILE_SEP_PATH)
299 currentDir += wxFILE_SEP_PATH;
300
d9ab621e
WS
301 currentDir += argv0;
302 if (wxFileExists(currentDir))
303 return wxPathOnly(currentDir);
d7463f75
JS
304 }
305
306 // OK, it's neither an absolute path nor a relative path.
307 // Search PATH.
308
309 wxPathList pathList;
310 pathList.AddEnvList(wxT("PATH"));
d9ab621e 311 wxString strPath = pathList.FindAbsoluteValidPath(argv0);
a04a377a 312 if (!strPath.empty())
d9ab621e 313 return wxPathOnly(strPath);
d7463f75
JS
314
315 // Failed
316 return wxEmptyString;
317}
318
319// Adds a context-sensitive help button, for non-Windows platforms
254a2129 320void apAddContextHelpButton(wxWindow*
69da0d99
JS
321 #if defined(__WXGTK__) || defined(__WXMAC__)
322 parent
323 #else
324 WXUNUSED(parent)
325 #endif
254a2129 326 , wxSizer*
69da0d99
JS
327 #if defined(__WXGTK__) || defined(__WXMAC__)
328 sizer
329 #else
330 WXUNUSED(sizer)
331 #endif
254a2129 332 , int
69da0d99
JS
333 #if defined(__WXGTK__) || defined(__WXMAC__)
334 sizerFlags
335 #else
336 WXUNUSED(sizerFlags)
337 #endif
254a2129 338 , int
69da0d99
JS
339 #if defined(__WXGTK__) || defined(__WXMAC__)
340 sizerBorder
341 #else
342 WXUNUSED(sizerBorder)
343 #endif
344 )
d7463f75
JS
345{
346#if defined(__WXGTK__) || defined(__WXMAC__)
347#ifdef __WXMAC__
348 wxSize buttonSize(20, 20);
349#else
4fe30bce 350 wxSize buttonSize = wxDefaultSize;
d7463f75
JS
351#endif
352 wxButton *contextButton = new wxContextHelpButton( parent, wxID_CONTEXT_HELP,
353 wxDefaultPosition, buttonSize);
354 sizer->Add( contextButton, 0, sizerFlags, sizerBorder );
355
356 // Add a bit of space on the right, to allow for the dialog resizing
357 // handle
358#ifdef __WXMAC__
359 sizer->Add(0, 0, 0, wxRIGHT, 10);
360#endif
361
362 contextButton->SetHelpText(_("Invokes context-sensitive help for the clicked-on window."));
02ae000a 363#if 0
d7463f75
JS
364 if (wxGetApp().UsingTooltips())
365 {
366 contextButton->SetToolTip(_("Invokes context-sensitive help for the clicked-on window."));
367 }
368#endif
02ae000a 369#endif
d7463f75
JS
370}
371
372// Get selected wxNotebook page
373wxWindow* apNotebookGetSelectedPage(wxNotebook* notebook)
374{
375 int sel = notebook->GetSelection();
376 if (sel > -1)
377 {
378 return notebook->GetPage(sel);
379 }
380 return NULL;
381}
382
383/*
384* wxIconInfo
385*/
386
387wxIconInfo::wxIconInfo(const wxString& name)
388{
389 m_maxStates = 0;
390 m_name = name;
391 int i;
392 for (i = 0; i < wxMAX_ICON_STATES; i++)
393 m_states[i] = 0;
394}
395
396int wxIconInfo::GetIconId(int state, bool enabled) const
397{
398 wxASSERT ( state < (wxMAX_ICON_STATES * 2) );
399 wxASSERT ( state < m_maxStates );
254a2129 400
d7463f75
JS
401 return m_states[state * 2 + (enabled ? 0 : 1)];
402}
403
404void wxIconInfo::SetIconId(int state, bool enabled, int iconId)
405{
406 wxASSERT ( state < (wxMAX_ICON_STATES * 2) );
407 if (state+1 > m_maxStates)
408 m_maxStates = state+1;
254a2129 409
d7463f75
JS
410 m_states[state * 2 + (enabled ? 0 : 1)] = iconId;
411}
412
413/*
414* wxIconTable
415* Contains a list of wxIconInfos
416*/
417
418wxIconTable::wxIconTable(wxImageList* imageList)
419{
420 m_imageList = imageList;
d9ab621e 421 WX_CLEAR_LIST(wxIconTable,*this);
d7463f75
JS
422}
423
424void wxIconTable::AppendInfo(wxIconInfo* info)
425{
426 Append(info);
427}
428
429// Easy way of initialising both the image list and the
430// table. It will generate image ids itself while appending the icon.
431bool wxIconTable::AddInfo(const wxString& name, const wxIcon& icon, int state, bool enabled)
432{
433 wxASSERT (m_imageList != NULL);
254a2129 434
d7463f75
JS
435 wxIconInfo* info = FindInfo(name);
436 if (!info)
437 {
438 info = new wxIconInfo(name);
439 Append(info);
440 }
441 info->SetIconId(state, enabled, m_imageList->Add(icon));
4fe30bce 442 return true;
d7463f75
JS
443}
444
445wxIconInfo* wxIconTable::FindInfo(const wxString& name) const
446{
d9ab621e 447 wxObjectList::compatibility_iterator node = GetFirst();
d7463f75
JS
448 while (node)
449 {
f8105809 450 wxIconInfo* info = (wxIconInfo*) node->GetData();
d7463f75
JS
451 if (info->GetName() == name)
452 return info;
f8105809 453 node = node->GetNext();
d7463f75
JS
454 }
455 return NULL;
456}
457
458int wxIconTable::GetIconId(const wxString& name, int state, bool enabled) const
459{
460 wxIconInfo* info = FindInfo(name);
461 if (!info)
462 return -1;
463 return info->GetIconId(state, enabled);
464}
465
466bool wxIconTable::SetIconId(const wxString& name, int state, bool enabled, int iconId)
467{
468 wxIconInfo* info = FindInfo(name);
469 if (!info)
4fe30bce 470 return false;
d7463f75 471 info->SetIconId(state, enabled, iconId);
4fe30bce 472 return true;
d7463f75
JS
473}
474
475// Output stream operators
476
477wxOutputStream& operator <<(wxOutputStream& stream, const wxString& s)
478{
479 stream.Write(s, s.Length());
480 return stream;
481}
482
483wxOutputStream& operator <<(wxOutputStream& stream, long l)
484{
485 wxString str;
486 str.Printf(_T("%ld"), l);
487 return stream << str;
488}
489
69da0d99 490wxOutputStream& operator <<(wxOutputStream& stream, const wxChar c)
d7463f75
JS
491{
492 wxString str;
493 str.Printf(_T("%c"), c);
494 return stream << str;
495}
496
497// Convert characters to HTML equivalents
498wxString ctEscapeHTMLCharacters(const wxString& str)
499{
500 wxString s;
501 size_t len = str.Length();
502 size_t i;
503 for (i = 0; i < len; i++)
504 {
505 wxChar c = str.GetChar(i);
506 if (c == _T('<'))
507 s += _T("&lt;");
508 else if (c == _T('>'))
509 s += _T("&gt;");
510 else if (c == _T('&'))
511 s += _T("&amp;");
512 else
513 s += c;
514 }
515 return s;
f8105809 516}
e7767867
JS
517
518// Match 'matchText' against 'matchAgainst', optionally constraining to
519// whole-word only.
520bool ctMatchString(const wxString& matchAgainst, const wxString& matchText, bool wholeWordOnly)
521{
522 // Fast operation if not matching against whole words only
523 if (!wholeWordOnly)
4fe30bce 524 return (matchAgainst.Find(matchText) != wxNOT_FOUND);
e7767867
JS
525
526 wxString left(matchAgainst);
4fe30bce 527 bool success = false;
e7767867 528 int matchTextLen = (int) matchText.Length();
a04a377a 529 while (!success && !matchAgainst.empty())
e7767867 530 {
79830320 531 int pos = left.Find(matchText);
4fe30bce
WS
532 if (pos == wxNOT_FOUND)
533 return false;
e7767867 534
4fe30bce
WS
535 bool firstCharOK = false;
536 bool lastCharOK = false;
e7767867 537 if (pos == 0 || !wxIsalnum(left[(size_t) (pos-1)]))
4fe30bce 538 firstCharOK = true;
e7767867
JS
539
540 if (((pos + matchTextLen) == (int) left.Length()) || !wxIsalnum(left[(size_t) (pos + matchTextLen)]))
4fe30bce 541 lastCharOK = true;
e7767867
JS
542
543 if (firstCharOK && lastCharOK)
4fe30bce 544 success = true;
e7767867
JS
545
546 left = left.Mid(pos+1);
547 }
548 return success;
549}