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