2
* This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3
* http://www.gnu.org/licenses/lgpl-3.0.html
6
* $Id: globals.cpp 4909 2008-02-27 13:15:26Z mortenmacfly $
7
* $HeadURL: svn://svn.berlios.de/codeblocks/tags/8.02/src/sdk/globals.cpp $
10
#include "sdk_precomp.h"
14
#include <wx/filename.h>
17
#include <wx/listctrl.h>
18
#include <wx/filesys.h>
19
#include "cbexception.h"
21
#include "configmanager.h" // ReadBool
22
#include "filemanager.h"
25
#include "tinyxml/tinyxml.h"
26
#include <wx/filefn.h>
27
#include <wx/tokenzr.h>
28
#include <wx/dirdlg.h>
29
#include <wx/msgdlg.h>
30
#include <wx/fontmap.h>
32
#include "filefilters.h"
33
#include "tinyxml/tinywxuni.h"
36
namespace compatibility { typedef TernaryCondTypedef<wxMinimumVersion<2,5>::eval, wxTreeItemIdValue, long int>::eval tree_cookie_t; };
39
const wxString DEFAULT_WORKSPACE = _T("default.workspace");
40
const wxString DEFAULT_ARRAY_SEP = _T(";");
43
const wxString DEFAULT_CONSOLE_TERM = _T("xterm -T $TITLE -e");
45
const wxString DEFAULT_CONSOLE_TERM = _T("osascript -e 'tell app \"Terminal\" to do script \"$SCRIPT\"'");
47
const wxString DEFAULT_CONSOLE_SHELL = _T("/bin/sh -c");
49
int GetPlatformsFromString(const wxString& platforms)
51
bool pW = platforms.Contains(_("Windows"));
52
bool pU = platforms.Contains(_("Unix"));
53
bool pM = platforms.Contains(_("Mac"));
54
bool pA = platforms.Contains(_("All"));
56
if (pA || (pW && pU && pM))
69
wxString GetStringFromPlatforms(int platforms, bool forceSeparate)
75
int tmpAll = spWindows | spUnix | spMac;
76
if (((platforms & tmpAll) == tmpAll) || ((platforms & spAll) == spAll))
80
if (platforms & spWindows)
82
if (platforms & spUnix)
84
if (platforms & spMac)
90
Killerbot : 6 Oktober 2007
91
The method has been extended with a bool to specify if the seperator should be appended at the end.
92
Ultimate goal : every client gives as a value : false.
93
Why : well a seperator should separate, there's nothing to separate at the end (like nothing to separate
94
at the begining, we don't put one there ...), but some client code is having problems when the separator is
95
not present at the end. So for compatibility issues we have as default value for the new argument true, so the
96
old code has the same behaviour as before [TODO: make those clients no longer dependent on this stupid final separator behaviour]
97
New code will specify false as the bool value, so hoping rather soon a search on this method will have all hits showing
98
false as the last argument ....
101
wxString GetStringFromArray(const wxArrayString& array, const wxString& separator, bool SeparatorAtEnd)
104
for (unsigned int i = 0; i < array.GetCount(); ++i)
107
if(i < array.GetCount() - 1 || SeparatorAtEnd)
113
} // end of GetStringFromArray
115
wxArrayString GetArrayFromString(const wxString& text, const wxString& separator, bool trimSpaces)
118
wxString search = text;
119
int seplen = separator.Length();
122
int idx = search.Find(separator);
130
if (!search.IsEmpty())
134
wxString part = search.Left(idx);
135
search.Remove(0, idx + seplen);
147
void AppendArray(const wxArrayString& from, wxArrayString& to)
149
for (unsigned int i = 0; i < from.GetCount(); ++i)
155
wxString UnixFilename(const wxString& filename)
157
wxString result = filename;
159
if(platform::windows)
161
bool unc_name = result.StartsWith(_T("\\\\"));
163
while (result.Replace(_T("/"), _T("\\")))
165
while (result.Replace(_T("\\\\"), _T("\\")))
169
result = _T("\\") + result;
173
while (result.Replace(_T("\\"), _T("/")))
175
while (result.Replace(_T("//"), _T("/")))
182
void QuoteStringIfNeeded(wxString& str)
184
bool hasSpace = str.Find(_T(' ')) != -1;
185
bool hasParen = !platform::windows && (str.Find(_T('(')) != -1 || str.Find(_T(')')) != -1);
186
if (!str.IsEmpty() && str.GetChar(0) != _T('"') && (hasSpace || hasParen))
187
str = wxString(_T("\"")) + str + _T("\"");
190
wxString EscapeSpaces(const wxString& str)
193
if (!ret.IsEmpty() && ret[0] != _T('"') && ret[0] != _T('\''))
195
// TODO: make it faster
196
ret.Replace(_T(" "), _T("\\ "));
197
ret.Replace(_T("\t"), _T("\\\t"));
202
FileType FileTypeOf(const wxString& filename)
204
wxString ext = filename.AfterLast(_T('.')).Lower();
206
if (ext.IsSameAs(FileFilters::ASM_EXT) ||
207
ext.IsSameAs(FileFilters::C_EXT) ||
208
ext.IsSameAs(FileFilters::CC_EXT) ||
209
ext.IsSameAs(FileFilters::CPP_EXT) ||
210
ext.IsSameAs(FileFilters::CXX_EXT) ||
211
ext.IsSameAs(FileFilters::S_EXT) ||
212
ext.IsSameAs(FileFilters::SS_EXT) ||
213
ext.IsSameAs(FileFilters::S62_EXT) ||
214
ext.IsSameAs(FileFilters::D_EXT) ||
215
ext.IsSameAs(FileFilters::F_EXT) ||
216
ext.IsSameAs(FileFilters::F77_EXT) ||
217
ext.IsSameAs(FileFilters::F90_EXT) ||
218
ext.IsSameAs(FileFilters::F95_EXT) ||
219
ext.IsSameAs(FileFilters::JAVA_EXT)
223
else if (ext.IsSameAs(FileFilters::H_EXT) ||
224
ext.IsSameAs(FileFilters::HH_EXT) ||
225
ext.IsSameAs(FileFilters::HPP_EXT) ||
226
ext.IsSameAs(FileFilters::HXX_EXT)
230
else if (ext.IsSameAs(FileFilters::CODEBLOCKS_EXT))
231
return ftCodeBlocksProject;
233
else if (ext.IsSameAs(FileFilters::WORKSPACE_EXT))
234
return ftCodeBlocksWorkspace;
236
else if (ext.IsSameAs(FileFilters::DEVCPP_EXT))
237
return ftDevCppProject;
239
else if (ext.IsSameAs(FileFilters::MSVC6_EXT))
240
return ftMSVC6Project;
242
else if (ext.IsSameAs(FileFilters::MSVC7_EXT))
243
return ftMSVC7Project;
245
else if (ext.IsSameAs(FileFilters::MSVC6_WORKSPACE_EXT))
246
return ftMSVC6Workspace;
248
else if (ext.IsSameAs(FileFilters::MSVC7_WORKSPACE_EXT))
249
return ftMSVC7Workspace;
251
else if (ext.IsSameAs(FileFilters::XCODE1_EXT))
252
return ftXcode1Project; // Xcode 1.0+ (Mac OS X 10.3)
254
else if (ext.IsSameAs(FileFilters::XCODE2_EXT))
255
return ftXcode2Project; // Xcode 2.1+ (Mac OS X 10.4)
257
else if (ext.IsSameAs(FileFilters::OBJECT_EXT))
260
else if (ext.IsSameAs(FileFilters::XRCRESOURCE_EXT))
261
return ftXRCResource;
263
else if (ext.IsSameAs(FileFilters::RESOURCE_EXT))
266
else if (ext.IsSameAs(FileFilters::RESOURCEBIN_EXT))
267
return ftResourceBin;
269
else if (ext.IsSameAs(FileFilters::STATICLIB_EXT))
272
else if (ext.IsSameAs(FileFilters::DYNAMICLIB_EXT))
275
else if (ext.IsSameAs(FileFilters::NATIVE_EXT))
278
else if (ext.IsSameAs(FileFilters::EXECUTABLE_EXT))
281
else if (ext.IsSameAs(FileFilters::XML_EXT))
282
return ftXMLDocument;
284
else if (ext.IsSameAs(FileFilters::SCRIPT_EXT))
290
bool DoRememberExpandedNodes(wxTreeCtrl* tree, const wxTreeItemId& parent, wxArrayString& nodePaths, wxString& path)
292
// remember expanded tree nodes of this tree
293
if (!tree || !parent.IsOk())
296
wxString originalPath = path;
299
compatibility::tree_cookie_t cookie = 0;
301
wxTreeItemId child = tree->GetFirstChild(parent, cookie);
304
if (tree->ItemHasChildren(child) && tree->IsExpanded(child))
307
path << _T("/") << tree->GetItemText(child);
308
DoRememberExpandedNodes(tree, child, nodePaths, path);
312
child = tree->GetNextChild(parent, cookie);
317
void DoExpandRememberedNode(wxTreeCtrl* tree, const wxTreeItemId& parent, const wxString& path)
321
//Manager::Get()->GetLogManager()->Log(mltDevDebug, path);
325
int pos = tmpPath.Find(_T('/'));
328
tmpPath = tmpPath.Right(tmpPath.Length() - pos - 1);
329
pos = tmpPath.Find(_T('/'));
332
if (pos < 0) // no '/'
339
folder = tmpPath.Left(pos);
340
tmpPath = tmpPath.Right(tmpPath.Length() - pos - 1);
343
//Manager::Get()->GetLogManager()->Log(mltDevDebug, "%s, %s", folder.c_str(), tmpPath.c_str());
345
compatibility::tree_cookie_t cookie = 0;
347
wxTreeItemId child = tree->GetFirstChild(parent, cookie);
350
wxString itemText = tree->GetItemText(child);
351
if (itemText.Matches(folder))
354
DoExpandRememberedNode(tree, child, tmpPath);
357
child = tree->GetNextChild(parent, cookie);
362
void SaveTreeState(wxTreeCtrl* tree, const wxTreeItemId& parent, wxArrayString& nodePaths)
365
if (!parent.IsOk() || !tree || !tree->ItemHasChildren(parent) || !tree->IsExpanded(parent))
368
if (!DoRememberExpandedNodes(tree, parent, nodePaths, tmp))
369
nodePaths.Add(tmp); // just the tree root
372
void RestoreTreeState(wxTreeCtrl* tree, const wxTreeItemId& parent, wxArrayString& nodePaths)
374
if (!parent.IsOk() || !tree)
376
if (nodePaths.GetCount() == 0)
378
tree->Collapse(parent);
381
for (unsigned int i = 0; i < nodePaths.GetCount(); ++i)
382
DoExpandRememberedNode(tree, parent, nodePaths[i]);
386
bool CreateDirRecursively(const wxString& full_path, int perms)
388
if(wxDirExists(full_path)) // early out
395
wxFileName tmp(full_path);
396
currdir = tmp.GetVolume() + tmp.GetVolumeSeparator() + wxFILE_SEP_PATH;
397
dirs = tmp.GetDirs();
399
for (size_t i = 0; i < dirs.GetCount(); ++i)
402
if (!wxDirExists(currdir) && !wxMkdir(currdir, perms))
404
currdir << wxFILE_SEP_PATH;
409
bool CreateDir(const wxString& full_path, int perms)
411
if (!wxDirExists(full_path) && !wxMkdir(full_path, perms))
417
wxString ChooseDirectory(wxWindow* parent,
418
const wxString& message,
419
const wxString& initialPath,
420
const wxString& basePath,
421
bool askToMakeRelative, // relative to initialPath
422
bool showCreateDirButton) // where supported
424
wxDirDialog dlg(parent,
427
(showCreateDirButton ? wxDD_NEW_DIR_BUTTON : 0) | wxRESIZE_BORDER);
428
dlg.SetPath(initialPath);
430
if (dlg.ShowModal() != wxID_OK)
431
return wxEmptyString;
433
wxFileName path(dlg.GetPath());
434
if (askToMakeRelative && !basePath.IsEmpty())
436
// ask the user if he wants it to be kept as relative
437
if (cbMessageBox(_("Keep this as a relative path?"),
439
wxICON_QUESTION | wxYES_NO) == wxID_YES)
441
path.MakeRelativeTo(basePath);
444
return path.GetFullPath();
447
// Reads a wxString from a file. File must be open. File is closed automatically.
448
bool cbRead(wxFile& file, wxString& st, wxFontEncoding encoding)
451
if (!file.IsOpened())
453
int len = file.Length();
460
char* buff = new char[len+1];
461
if (!buff) // remark by killerbot : this is useless, since when out of mem --> exception (this is not malloc you know)
466
file.Read((void*)buff, len);
470
DetectEncodingAndConvert(buff, st, encoding);
476
wxString cbReadFileContents(wxFile& file, wxFontEncoding encoding)
479
cbRead(file, st, encoding);
483
// Writes a wxString to a file. File must be open. File is closed automatically.
484
bool cbWrite(wxFile& file, const wxString& buff, wxFontEncoding encoding)
489
wxCSConv conv(encoding);
490
result = file.Write(buff,conv);
498
// Writes a wxString to a file. Takes care of unicode and uses a temporary file
499
// to save first and then it copies it over the original.
500
bool cbSaveToFile(const wxString& filename, const wxString& contents, wxFontEncoding encoding, bool bom)
502
return Manager::Get()->GetFileManager()->Save(filename, contents, encoding, bom);
505
// Saves a TinyXML document correctly, even if the path contains unicode characters.
506
bool cbSaveTinyXMLDocument(TiXmlDocument* doc, const wxString& filename)
508
return TinyXML::SaveDocument(filename, doc);
511
// Return @c str as a proper unicode-compatible string
512
wxString cbC2U(const char* str)
515
return wxString(str, wxConvUTF8);
517
return wxString(str);
521
// Return multibyte (C string) representation of the string
522
const wxWX2MBbuf cbU2C(const wxString& str)
524
if(platform::unicode)
525
return str.mb_str(wxConvUTF8);
530
// Try converting a C-string from different encodings until a possible match is found.
531
// This tries the following encoding converters (in the same order):
532
// utf8, system, default and iso8859-1 to iso8859-15
533
wxFontEncoding DetectEncodingAndConvert(const char* strIn, wxString& strOut, wxFontEncoding possibleEncoding)
535
wxFontEncoding encoding = possibleEncoding;
538
if(platform::unicode)
540
if (possibleEncoding != wxFONTENCODING_UTF16 &&
541
possibleEncoding != wxFONTENCODING_UTF16LE &&
542
possibleEncoding != wxFONTENCODING_UTF16BE &&
543
possibleEncoding != wxFONTENCODING_UTF32 &&
544
possibleEncoding != wxFONTENCODING_UTF32LE &&
545
possibleEncoding != wxFONTENCODING_UTF32BE)
547
// crashes deep in the runtime (windows, at least)
548
// if one of the above encodings, hence the guard
549
wxCSConv conv(possibleEncoding);
550
strOut = wxString(strIn, conv);
552
if (strOut.Length() == 0)
554
// oops! wrong encoding...
556
// try utf8 first, if that was not what was asked for
557
if (possibleEncoding != wxFONTENCODING_UTF8)
559
encoding = wxFONTENCODING_UTF8;
560
strOut = wxString(strIn, wxConvUTF8);
563
// check again: if still not right, try system encoding, default encoding and then iso8859-1 to iso8859-15
564
if (strOut.Length() == 0)
566
for (int i = wxFONTENCODING_SYSTEM; i < wxFONTENCODING_ISO8859_MAX; ++i)
568
encoding = (wxFontEncoding)i;
569
if (encoding == possibleEncoding)
570
continue; // skip if same as what was asked
571
wxCSConv conv(encoding);
572
strOut = wxString(strIn, conv);
573
if (strOut.Length() != 0)
581
strOut = (const wxChar*) strIn;
586
strOut = (const wxChar*) strIn;
591
wxString URLEncode(const wxString &str) // not sure this is 100% standards compliant, but I hope so
595
for(unsigned int i = 0; i < str.length(); ++i)
598
if( (c >= _T('A') && c <= _T('Z'))
599
|| (c >= _T('a') && c <= _T('z'))
600
|| (c >= _T('0') && c <= _T('9'))
601
|| c == _T('.') || c == _T('-') || c == _T('_') )
604
else if(c == _T(' '))
608
t.sprintf(_T("%%%02X"), (unsigned int) c);
615
bool IsWindowReallyShown(wxWindow* win)
617
while (win && win->IsShown())
619
win = win->GetParent();
626
bool NormalizePath(wxFileName& f,const wxString& base)
629
// if(!f.IsAbsolute())
631
f.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, base);
637
// function to check the common controls version
638
// (should it be moved in sdk globals?)
642
bool UsesCommonControls6()
647
hinstDll = LoadLibrary(_T("comctl32.dll"));
650
DLLGETVERSIONPROC pDllGetVersion;
651
pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion");
658
ZeroMemory(&dvi, sizeof(dvi));
659
dvi.cbSize = sizeof(dvi);
661
hr = (*pDllGetVersion)(&dvi);
665
dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);
666
result = dvi.dwMajorVersion == 6;
670
FreeLibrary(hinstDll);
675
bool UsesCommonControls6()
677
// for non-windows platforms, return true
678
// as this is only used for knowing if bitmaps support transparency or not
683
wxBitmap cbLoadBitmap(const wxString& filename, int bitmapType)
685
// cache this, can't change while we 're running :)
686
static bool oldCommonControls = !UsesCommonControls6();
689
wxFileSystem* fs = new wxFileSystem;
690
wxFSFile* f = fs->OpenFile(filename);
693
wxInputStream* is = f->GetStream();
694
im.LoadFile(*is, bitmapType);
698
if (oldCommonControls && im.HasAlpha())
699
im.ConvertAlphaToMask();
704
void SetSettingsIconsStyle(wxListCtrl* lc, SettingsIconsStyle style)
706
// this doesn't work under wxGTK...
708
long flags = lc->GetWindowStyleFlag();
711
case sisNoIcons: flags = (flags & ~wxLC_ICON) | wxLC_SMALL_ICON; break;
712
default: flags = (flags & ~wxLC_SMALL_ICON) | wxLC_ICON; break;
714
lc->SetWindowStyleFlag(flags);
718
SettingsIconsStyle GetSettingsIconsStyle(wxListCtrl* lc)
720
// this doesn't work under wxGTK...
722
long flags = lc->GetWindowStyleFlag();
723
if (flags & wxLC_SMALL_ICON)
726
return sisLargeIcons;
731
typedef APIENTRY HMONITOR (*MonitorFromWindow_t)(HWND, DWORD);
732
typedef APIENTRY BOOL (*GetMonitorInfo_t)(HMONITOR, LPMONITORINFO);
734
void PlaceWindow(wxTopLevelWindow *w, cbPlaceDialogMode mode, bool enforce)
743
cbThrow(_T("Passed NULL pointer to PlaceWindow."));
745
wxWindow* referenceWindow = Manager::Get()->GetAppWindow();
747
if(!referenceWindow) // no application window available, so this is as good as we can get
750
wxRect windowRect = w->GetRect();
752
ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("app"));
753
if(!enforce && cfg->ReadBool(_T("/dialog_placement/do_place")) == false)
757
the_mode = cfg->ReadInt(_T("/dialog_placement/dialog_position"), (int) pdlCentre);
759
the_mode = (int) mode;
762
static MonitorFromWindow_t MonitorFromWindowProc = (MonitorFromWindow_t) GetProcAddress(GetModuleHandle(_T("user32.dll")), "MonitorFromWindow");
763
static GetMonitorInfo_t GetMonitorInfoProc = (GetMonitorInfo_t) GetProcAddress(GetModuleHandle(_T("user32.dll")), "GetMonitorInfoA");
767
if(GetMonitorInfoProc)
769
hMonitor = MonitorFromWindowProc((HWND) referenceWindow->GetHandle(), MONITOR_DEFAULTTONEAREST);
771
mi.cbSize = sizeof(mi);
772
GetMonitorInfoProc(hMonitor, &mi);
775
monitorWidth = r.right - r.left;
776
monitorHeight = r.bottom - r. top;
778
else // Win95, NT4: support only single monitor
780
wxDisplaySize(&monitorWidth, &monitorHeight);
789
windowRect.x = r.left + (monitorWidth - windowRect.width)/2;
790
windowRect.y = r.top + (monitorHeight - windowRect.height)/2;
797
windowRect.x = r.left + (monitorWidth - windowRect.width)/2;
798
windowRect.y = r.top + (monitorHeight - windowRect.height)/3;
805
int x1 = windowRect.x;
806
int x2 = windowRect.x + windowRect.width;
807
int y1 = windowRect.y;
808
int y2 = windowRect.y + windowRect.height;
810
if(windowRect.width > monitorWidth) // cannot place without clipping, so centre it
812
x1 = r.left + (monitorWidth - windowRect.width)/2;
813
x2 = x1 + windowRect.width;
817
x2 = std::min((int) r.right, windowRect.GetRight());
818
x1 = std::max(x2 - windowRect.width, (int) r.left);
819
x2 = x1 + windowRect.width;
821
if(windowRect.height > monitorHeight) // cannot place without clipping, so centre it
823
y1 = r.top + (monitorHeight - windowRect.height)/2;
824
y2 = y1 + windowRect.height;
828
y2 = std::min((int) r.bottom, windowRect.GetBottom());
829
y1 = std::max(y2 - windowRect.height, (int) r.top);
830
y2 = y1 + windowRect.height;
832
windowRect = wxRect(x1, y1, x2-x1, y2-y1);
839
int x1 = windowRect.x;
840
int x2 = windowRect.x + windowRect.width;
841
int y1 = windowRect.y;
842
int y2 = windowRect.y + windowRect.height;
844
x1 = std::max(x1, (int) r.left);
845
x2 = std::min(x2, (int) r.right);
846
y1 = std::max(y1, (int) r.top);
847
y2 = std::min(y2, (int) r.bottom);
849
windowRect = wxRect(x1, y1, x2-x1, y2-y1);
854
w->SetSize(windowRect.x, windowRect.y, windowRect.width, windowRect.height, wxSIZE_ALLOW_MINUS_ONE);
858
#else // ----- non-Windows ----------------------------------------------
861
void PlaceWindow(wxTopLevelWindow *w, cbPlaceDialogMode mode, bool enforce)
862
// TODO (thomas#1#): The non-Windows implementation is *pathetic*.
863
// However, I don't know how to do it well under GTK / X / Xinerama / whatever.
868
wxWindow* referenceWindow = Manager::Get()->GetAppWindow();
869
if(!referenceWindow) // let's not crash on shutdown
873
cbThrow(_T("Passed NULL pointer to PlaceWindow."));
876
ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("app"));
877
if(!enforce && cfg->ReadBool(_T("/dialog_placement/do_place")) == false)
881
the_mode = cfg->ReadInt(_T("/dialog_placement/dialog_position"), (int) pdlCentre);
883
the_mode = (int) mode;
886
if(the_mode == pdlCentre || the_mode == pdlHead)
893
wxRect windowRect = w->GetRect();
894
wxRect parentRect = referenceWindow->GetRect(); // poo again!
896
int x1 = windowRect.x;
897
int x2 = windowRect.x + windowRect.width;
898
int y1 = windowRect.y;
899
int y2 = windowRect.y + windowRect.height;
901
x1 = std::max(x1, parentRect.x);
902
x2 = std::min(x2, parentRect.GetRight());
903
y1 = std::max(y1, parentRect.y);
904
y2 = std::min(y2, parentRect.GetBottom());
906
w->SetSize(x1, y1, x2-x1, y2-y1, wxSIZE_ALLOW_MINUS_ONE);
910
#endif //platform-specific placement code
912
DirAccessCheck cbDirAccessCheck(const wxString& dir)
914
wxString actualDir = dir;
915
// append ending path separator if needed
916
if (actualDir.Last() != _T('/') && actualDir.Last() != _T('\\'))
917
actualDir << wxFILE_SEP_PATH;
919
if (!wxDirExists(actualDir))
920
return dacInvalidDir;
922
wxString testFile = wxFileName::CreateTempFileName(actualDir);
923
if (!testFile.IsEmpty())
925
// ok, write-access confirmed
926
// now remove the temporary file and return success
927
wxRemoveFile(testFile);
931
// if we reached here, the directory is not writable
938
windows_version_t cb_get_os()
940
if(!platform::windows)
942
return winver_NotWindows;
947
int famWin95 = wxOS_WINDOWS_9X;
948
int famWinNT = wxOS_WINDOWS_NT;
951
int family = wxGetOsVersion(&Major, NULL);
953
if(family == famWin95)
954
return winver_Windows9598ME;
956
if(family == famWinNT)
959
return winver_WindowsXP;
961
if(Major == 6) // just guessing here, not sure if this is right
964
return winver_WindowsNT2000;
967
return winver_UnknownWindows;
971
windows_version_t WindowsVersion()
973
static const windows_version_t theOS = cb_get_os();