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