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