diff --git a/Lgi_vc9.vcproj b/Lgi_vc9.vcproj
--- a/Lgi_vc9.vcproj
+++ b/Lgi_vc9.vcproj
@@ -1,1451 +1,1451 @@
diff --git a/Updater/Updater_vc9.vcproj b/Updater/Updater_vc9.vcproj
--- a/Updater/Updater_vc9.vcproj
+++ b/Updater/Updater_vc9.vcproj
@@ -1,193 +1,193 @@
diff --git a/src/common/Lgi/Lgi.cpp b/src/common/Lgi/Lgi.cpp
--- a/src/common/Lgi/Lgi.cpp
+++ b/src/common/Lgi/Lgi.cpp
@@ -1,2196 +1,2198 @@
//
// Cross platform LGI functions
//
#include
#include
#include
#include
#ifdef _WINDOWS
#include
#include
#else
#include
#endif
#include "Lgi.h"
#include "GToken.h"
#include "GCapabilities.h"
#if defined(LINUX)
#include "LgiWinManGlue.h"
#elif defined(_WINDOWS)
#include "GRegKey.h"
#endif
#if defined POSIX
#include
#include
#include
#include
#include "GProcess.h"
#elif defined BEOS
#include
#endif
#if defined(WIN32) && defined(__GTK_H__)
#include "../win32/GSymLookup.h"
#else
#include "GSymLookup.h"
#endif
#include "GLibrary.h"
//////////////////////////////////////////////////////////////////////////
// Misc stuff
#if defined MAC && !defined COCOA
bool _get_path_FSRef(FSRef &fs, GStringPipe &a)
{
HFSUniStr255 Name;
ZeroObj(Name);
FSRef Parent;
FSCatalogInfo Cat;
ZeroObj(Cat);
OSErr e = FSGetCatalogInfo(&fs,
kFSCatInfoVolume|kFSCatInfoNodeID,
&Cat,
&Name,
NULL,
&Parent);
if (!e)
{
if (_get_path_FSRef(Parent, a))
{
GAutoString u(LgiNewUtf16To8((char16*)Name.unicode, Name.length * sizeof(char16)));
// printf("CatInfo = '%s' %x %x\n", u.Get(), Cat.nodeID, Cat.volume);
if (u && Cat.nodeID > 2)
{
a.Print("%s%s", DIR_STR, u.Get());
}
}
return true;
}
return false;
}
GAutoString FSRefPath(FSRef &fs)
{
GStringPipe a;
if (_get_path_FSRef(fs, a))
{
return GAutoString(a.NewStr());
}
return GAutoString();
}
#endif
bool LgiPostEvent(OsView Wnd, int Event, GMessage::Param a, GMessage::Param b)
{
#if WIN32NATIVE
return PostMessage(Wnd, Event, a, b);
#elif defined(__GTK_H__)
if (Wnd)
{
GMessage m(0);
m.Set(Event, a, b);
return m.Send(Wnd);
}
else
{
printf("%s:%i - Warning: LgiPostEvent failed because View=0\n", _FL);
}
#elif defined(BEOS)
if (Wnd)
{
BMessage Msg(Event);
Msg.AddInt32("a", a);
Msg.AddInt32("b", b);
BMessenger m(Wnd);
return m.SendMessage(&Msg) == B_OK;
}
#elif defined(MAC) && !defined COCOA
#if 0
int64 Now = LgiCurrentTime();
static int64 Last = 0;
static int Count = 0;
Count++;
if (Now > Last + 1000)
{
printf("Sent %i events in the last %ims\n", Count, (int)(Now-Last));
Last = Now;
Count = 0;
}
#endif
EventRef Ev;
OSStatus e = CreateEvent(NULL,
kEventClassUser,
kEventUser,
0, // EventTime
kEventAttributeNone,
&Ev);
if (e)
{
printf("%s:%i - CreateEvent failed with %i\n", __FILE__, __LINE__, (int)e);
}
else
{
EventTargetRef t = GetControlEventTarget(Wnd);
e = SetEventParameter(Ev, kEventParamLgiEvent, typeUInt32, sizeof(Event), &Event);
if (e) printf("%s:%i - error %i\n", __FILE__, __LINE__, (int)e);
e = SetEventParameter(Ev, kEventParamLgiA, typeUInt32, sizeof(a), &a);
if (e) printf("%s:%i - error %i\n", __FILE__, __LINE__, (int)e);
e = SetEventParameter(Ev, kEventParamLgiB, typeUInt32, sizeof(b), &b);
if (e) printf("%s:%i - error %i\n", __FILE__, __LINE__, (int)e);
// printf("Sent event %x,%x,%x\n", Event, a, b);
bool Status = false;
#if 1
e = SetEventParameter(Ev, kEventParamPostTarget, typeEventTargetRef, sizeof(t), &t);
if (e) printf("%s:%i - error %i\n", __FILE__, __LINE__, (int)e);
e = PostEventToQueue(GetMainEventQueue(), Ev, kEventPriorityStandard);
if (e) printf("%s:%i - error %i\n", __FILE__, __LINE__, (int)e);
else Status = true;
#else
e = SendEventToEventTarget(Ev, GetControlEventTarget(Wnd));
if (e) printf("%s:%i - error %i\n", __FILE__, __LINE__, e);
else Status = true;
#endif
ReleaseEvent(Ev);
return Status;
}
#endif
return false;
}
void LgiExitApp()
{
exit(0);
}
//////////////////////////////////////////////////////////////////////////
#ifdef WIN32
bool RegisterActiveXControl(char *Dll)
{
GLibrary Lib(Dll);
if (Lib.IsLoaded())
{
#ifdef _MSC_VER
typedef HRESULT (STDAPICALLTYPE *p_DllRegisterServer)(void);
p_DllRegisterServer DllRegisterServer = (p_DllRegisterServer)Lib.GetAddress("DllRegisterServer");
if (DllRegisterServer)
{
return DllRegisterServer() == S_OK;
}
#else
LgiAssert(!"Not impl.");
#endif
}
return false;
}
#endif
//////////////////////////////////////////////////////////////////////////
/// \brief Returns the operating system that Lgi is running on.
/// \sa Returns one of the defines starting with LGI_OS_UNKNOWN in LgiDefs.h
int LgiGetOs
(
/// Returns the version of the OS or NULL if you don't care
GArray *Ver
)
{
#if defined(WIN32) || defined(WIN64)
static int Os = LGI_OS_UNKNOWN;
static int Version = 0, Revision = 0;
if (Os == LGI_OS_UNKNOWN)
{
OSVERSIONINFO v;
v.dwOSVersionInfoSize=sizeof(v);
GetVersionEx(&v);
Version = v.dwMajorVersion;
Revision = v.dwMinorVersion;
#ifdef WIN32
BOOL IsWow64 = FALSE;
IsWow64Process(GetCurrentProcess(), &IsWow64);
#endif
Os = (v.dwPlatformId == VER_PLATFORM_WIN32_NT)
?
#ifdef WIN32
(IsWow64 ? LGI_OS_WIN64 : LGI_OS_WIN32)
#else
LGI_OS_WIN64
#endif
:
LGI_OS_WIN9X;
}
if (Ver)
{
Ver->Add(Version);
Ver->Add(Revision);
}
return Os;
#elif defined BEOS
if (Ver)
{
Ver->Add(5);
Ver->Add(0);
}
return LGI_OS_BEOS;
#elif defined LINUX
if (Ver)
{
utsname Buf;
if (!uname(&Buf))
{
GToken t(Buf.release, ".");
for (int i=0; iAdd(atoi(t[i]));
}
}
}
return LGI_OS_LINUX;
#elif defined MAC && !defined COCOA
if (Ver)
{
SInt32 i;
if (Gestalt(gestaltSystemVersionMajor, &i) == noErr)
{
Ver->Add(i);
if (Gestalt(gestaltSystemVersionMinor, &i) == noErr)
{
Ver->Add(i);
if (Gestalt(gestaltSystemVersionBugFix, &i) == noErr)
{
Ver->Add(i);
}
}
}
else if (Gestalt(gestaltSystemVersion, &i) == noErr)
{
char s[10];
sprintf_s(s, sizeof(s), "%x", (int)i);
char *e = s + strlen(s) - 1;
char a[3] = { e[-1], 0 };
char b[3] = { e[0], 0 };
e[-1] = 0;
Ver->Add(atoi(s));
Ver->Add(htoi(a));
Ver->Add(htoi(b));
}
}
return LGI_OS_MAC_OS_X;
#else
return LGI_OS_UNKNOWN;
#endif
}
const char *LgiGetOsName()
{
const char *Str[LGI_OS_MAX] =
{
"Unknown",
"Win9x",
"Win32",
"Win64",
"Haiku",
"Linux",
"MacOSX",
};
return Str[LgiGetOs()];
}
#ifdef WIN32
#define RecursiveFileSearch_Wildcard "*.*"
#else // unix'ish OS
#define RecursiveFileSearch_Wildcard "*"
#endif
bool LgiRecursiveFileSearch(const char *Root,
GArray *Ext,
GArray *Files,
uint64 *Size,
uint64 *Count,
RecursiveFileSearch_Callback Callback,
void *UserData)
{
bool Status = false;
// validate args
if (!Root) return 0;
// get directory enumerator
GDirectory Dir;
Status = true;
// enumerate the directory contents
for (bool Found = Dir.First(Root); Found; Found = Dir.Next())
{
char Name[256];
if (!Dir.Path(Name, sizeof(Name)))
continue;
if (Callback)
{
if (!Callback(UserData, Name, &Dir))
{
continue;
}
}
if (Dir.IsDir())
{
// dir
LgiRecursiveFileSearch( Name,
Ext,
Files,
Size,
Count,
Callback,
UserData);
}
else
{
// process file
bool Match = true; // if no Ext's then default to match
if (Ext)
{
for (int i=0; iLength(); i++)
{
const char *e = (*Ext)[i];
char *RawFile = strrchr(Name, DIR_CHAR);
if (RawFile &&
(Match = MatchStr(e, RawFile+1)))
{
break;
}
}
}
if (Match)
{
// file matched... process:
if (Files)
{
Files->Add(NewStr(Name));
}
if (Size)
{
*Size += Dir.GetSize();
}
if (Count)
{
Count++;
}
Status = true;
}
}
}
return Status;
}
#define LGI_TRACE_TO_FILE
// #include
#ifndef WIN32
#define _vsnprintf vsnprintf
#endif
void LgiTrace(const char *Msg, ...)
{
#if defined _INC_MALLOC && WIN32NATIVE
if (_heapchk() != _HEAPOK)
{
return;
}
#endif
if (Msg)
{
#ifdef WIN32
static GMutex Sem;
Sem.Lock(_FL);
#endif
char Buffer[2049] = "";
#ifdef LGI_TRACE_TO_FILE
GFile f;
static char LogPath[MAX_PATH] = "";
if (LogPath[0] == 0)
{
if (LgiGetExeFile(LogPath, sizeof(LogPath)))
{
#ifdef MAC
char *Dir = strrchr(LogPath, DIR_CHAR);
if (Dir)
{
char Part[256];
strcpy_s(Part, sizeof(Part), Dir+1);
LogPath[0] = 0;
LgiMakePath(LogPath, sizeof(LogPath), LogPath, "~/Library/Logs");
LgiMakePath(LogPath, sizeof(LogPath), LogPath, Dir+1);
strcat_s(LogPath, sizeof(LogPath), ".txt");
}
else
#endif
{
char *Dot = strrchr(LogPath, '.');
if (Dot && !strchr(Dot, DIR_CHAR))
strcpy(Dot+1, "txt");
else
strcat(LogPath, ".txt");
}
if (f.Open(LogPath, O_WRITE))
{
f.Close();
}
else
{
char Leaf[64];
char *Dir = strrchr(LogPath, DIR_CHAR);
if (Dir)
{
strcpy_s(Leaf, sizeof(Leaf), Dir + 1);
LgiGetSystemPath(LSP_APP_ROOT, LogPath, sizeof(LogPath));
if (!DirExists(LogPath))
FileDev->CreateFolder(LogPath);
LgiMakePath(LogPath, sizeof(LogPath), LogPath, Leaf);
}
else goto OnError;
}
}
else
{
// Well what to do now? I give up
OnError:
strcpy_s(LogPath, sizeof(LogPath), "trace.txt");
}
}
#endif
va_list Arg;
va_start(Arg, Msg);
_vsnprintf(Buffer, sizeof(Buffer)-1, Msg, Arg);
va_end(Arg);
#ifdef LGI_TRACE_TO_FILE
if (f.Open(LogPath, O_WRITE))
{
f.Seek(0, SEEK_END);
f.Write(Buffer, strlen(Buffer));
f.Close();
}
#endif
#if defined WIN32
OutputDebugString(Buffer);
Sem.Unlock();
#else
printf("%s", Buffer);
#endif
}
}
#ifndef LGI_STATIC
#define STACK_SIZE 12
void LgiStackTrace(const char *Msg, ...)
{
GSymLookup::Addr Stack[STACK_SIZE];
ZeroObj(Stack);
GSymLookup *Lu = LgiApp->GetSymLookup();
int Frames = Lu ? Lu->BackTrace(0, 0, Stack, STACK_SIZE) : 0;
if (Msg)
{
char Buffer[2049] = "";
#ifdef LGI_TRACE_TO_FILE
GFile f;
if (LgiGetExeFile(Buffer, sizeof(Buffer)))
{
char *Dot = strrchr(Buffer, '.');
if (Dot && !strchr(Dot, DIR_CHAR))
{
strcpy(Dot+1, "txt");
}
else
{
strcat(Buffer, ".txt");
}
f.Open(Buffer, O_WRITE);
}
#endif
va_list Arg;
va_start(Arg, Msg);
int Len = _vsnprintf(Buffer, sizeof(Buffer)-1, Msg, Arg);
va_end(Arg);
Lu->Lookup(Buffer+Len, sizeof(Buffer)-Len-1, Stack, Frames);
#ifdef LGI_TRACE_TO_FILE
if (f.IsOpen())
{
f.Seek(0, SEEK_END);
f.Write(Buffer, strlen(Buffer));
f.Close();
}
#endif
#if defined WIN32
OutputDebugString(Buffer);
#else
printf("Trace: %s", Buffer);
#endif
}
}
#endif
bool LgiTrimDir(char *Path)
{
if (Path)
{
char *p = strrchr(Path, DIR_CHAR);
if (p)
{
*p = 0;
return true;
}
}
return false;
}
GAutoString LgiMakeRelativePath(const char *Base, const char *Path)
{
GStringPipe Status;
if (Base && Path)
{
#ifdef WIN32
bool SameNs = strnicmp(Base, Path, 3) == 0;
#else
bool SameNs = true;
#endif
if (SameNs)
{
GToken b(Base + 1, ":" DIR_STR);
GToken p(Path + 1, ":" DIR_STR);
int Same = 0;
while (b[Same] && p[Same] && stricmp(b[Same], p[Same]) == 0)
{
Same++;
}
for (int i = Same; i= b.Length())
{
Status.Print(".%s", DIR_STR);
}
for (int n = Same; n Same)
{
Status.Push(DIR_STR);
}
Status.Push(p[n]);
}
}
}
return GAutoString(Status.NewStr());
}
bool LgiIsRelativePath(const char *Path)
{
if (!Path)
return false;
if (*Path == '.')
return true;
#ifdef WIN32
if (IsAlpha(Path[0]) && Path[1] == ':') // Drive letter path
return false;
#endif
if (*Path == DIR_CHAR)
return false;
if (strstr(Path, "://")) // Protocol def
return false;
return true; // Correct or not???
}
bool LgiMakePath(char *Str, int StrSize, const char *Path, const char *File)
{
LgiAssert(Str != 0 &&
StrSize > 0 &&
Path != 0 &&
File != 0);
if (StrSize <= 4)
{
printf("%s:%i - LgiMakeFile buf size=%i?\n", _FL, StrSize);
}
if (Str && Path && File)
{
if (Str != Path)
{
strcpy_s(Str, StrSize, Path);
}
char Dir[] = { '/', '\\', 0 };
#define EndStr() Str[strlen(Str)-1]
#define EndDir() if (!strchr(Dir, EndStr())) strcat(Str, DIR_STR);
int Len = strlen(Str);
char *End = Str + (Len ? Len - 1 : 0);
if (strchr(Dir, *End) && End > Str)
{
*End = 0;
}
GToken T(File, Dir);
for (int i=0; i= StrSize - 1)
return false;
Str[Len++] = DIR_CHAR;
Str[Len] = 0;
}
int SegLen = strlen(T[i]);
if (Len + SegLen + 1 > StrSize)
{
return false;
}
strcpy(Str + Len, T[i]);
}
}
}
return true;
}
bool LgiGetTempPath(char *Dst, int DstSize)
{
return LgiGetSystemPath(LSP_TEMP, Dst, DstSize);
}
bool LgiGetSystemPath(LgiSystemPath Which, char *Dst, int DstSize)
{
bool Status = false;
#if defined(WIN32)
#if !defined(CSIDL_MYDOCUMENTS)
#define CSIDL_MYDOCUMENTS 0x0005
#endif
#if !defined(CSIDL_MYMUSIC)
#define CSIDL_MYMUSIC 0x000d
#endif
#if !defined(CSIDL_MYVIDEO)
#define CSIDL_MYVIDEO 0x000e
#endif
#if !defined(CSIDL_LOCAL_APPDATA)
#define CSIDL_LOCAL_APPDATA 0x001c
#endif
#if !defined(CSIDL_COMMON_APPDATA)
#define CSIDL_COMMON_APPDATA 0x0023
#endif
#if !defined(CSIDL_APPDATA)
#define CSIDL_APPDATA 0x001a
#endif
#endif
if (Dst)
{
#ifdef LINUX
// Ask our window manager add-on if it knows the path
GLibrary *WmLib = LgiApp ? LgiApp->GetWindowManagerLib() : NULL;
if (WmLib)
{
Proc_LgiWmGetPath WmGetPath = (Proc_LgiWmGetPath) WmLib->GetAddress("LgiWmGetPath");
if (WmGetPath && WmGetPath(Which, Dst, DstSize))
{
return true;
}
}
#endif
switch (Which)
{
case LSP_USER_DOWNLOADS:
{
#if defined(WIN32) && defined(_MSC_VER)
// OMG!!!! Really?
#ifndef REFKNOWNFOLDERID
typedef GUID KNOWNFOLDERID;
#define REFKNOWNFOLDERID const KNOWNFOLDERID &
GUID FOLDERID_Downloads = {0x374DE290,0x123F,0x4565,{0x91,0x64,0x39,0xC4,0x92,0x5E,0x46,0x7B}};
#endif
GLibrary Shell("Shell32.dll");
typedef HRESULT (STDAPICALLTYPE *pSHGetKnownFolderPath)(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath);
pSHGetKnownFolderPath SHGetKnownFolderPath = (pSHGetKnownFolderPath)Shell.GetAddress("SHGetKnownFolderPath");
if (SHGetKnownFolderPath)
{
PWSTR ptr = NULL;
HRESULT r = SHGetKnownFolderPath(FOLDERID_Downloads, 0, NULL, &ptr);
if (SUCCEEDED(r))
{
GAutoString u8(LgiNewUtf16To8(ptr));
if (u8)
{
strcpy_s(Dst, DstSize, u8);
Status = true;
}
CoTaskMemFree(ptr);
}
}
if (!Status)
{
GRegKey k(false, "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
char *p = k.GetStr("{374DE290-123F-4565-9164-39C4925E467B}");
if (DirExists(p))
{
strcpy_s(Dst, DstSize, p);
Status = true;
}
}
if (!Status)
{
GAutoString MyDoc(GetWindowsFolder(CSIDL_MYDOCUMENTS));
if (MyDoc)
{
LgiMakePath(Dst, DstSize, MyDoc, "Downloads");
Status = DirExists(Dst);
}
}
if (!Status)
{
GAutoString MyDoc(GetWindowsFolder(CSIDL_PROFILE));
if (MyDoc)
{
LgiMakePath(Dst, DstSize, MyDoc, "Downloads");
Status = DirExists(Dst);
}
}
#else
LgiAssert(!"Not implemented");
#endif
break;
}
case LSP_USER_DOCUMENTS:
{
#if defined(WIN32) && defined(_MSC_VER)
GAutoString f(GetWindowsFolder(CSIDL_PERSONAL));
if (f)
{
strcpy_s(Dst, DstSize, f);
Status = true;
}
#else
LgiAssert(!"Not implemented");
#endif
break;
}
case LSP_USER_MUSIC:
{
#if defined WIN32
GAutoString f(GetWindowsFolder(CSIDL_MYMUSIC));
if (f)
{
strcpy_s(Dst, DstSize, f);
Status = true;
}
#elif defined MAC && !defined COCOA
FSRef Ref;
OSErr e = FSFindFolder(kUserDomain, kMusicDocumentsFolderType, kDontCreateFolder, &Ref);
if (e) printf("%s:%i - FSFindFolder failed e=%i\n", _FL, e);
else
{
GAutoString a = FSRefPath(Ref);
if (a)
{
strcpy_s(Dst, DstSize, a);
return true;
}
}
#else
LgiAssert(!"Not implemented");
#endif
break;
}
case LSP_USER_VIDEO:
{
#if defined WIN32
GAutoString f(GetWindowsFolder(CSIDL_MYVIDEO));
if (f)
{
strcpy_s(Dst, DstSize, f);
Status = true;
}
#elif defined MAC && !defined COCOA
FSRef Ref;
OSErr e = FSFindFolder(kUserDomain, kMovieDocumentsFolderType, kDontCreateFolder, &Ref);
if (e) printf("%s:%i - FSFindFolder failed e=%i\n", _FL, e);
else
{
GAutoString a = FSRefPath(Ref);
if (a)
{
strcpy_s(Dst, DstSize, a);
return true;
}
}
#else
LgiAssert(!"Not implemented");
#endif
break;
}
case LSP_USER_APPS:
{
- #if defined WINDOWS
+ #if defined WIN32
GAutoString f(GetWindowsFolder(
#ifdef WIN64
CSIDL_PROGRAM_FILES
#else
CSIDL_PROGRAM_FILESX86
#endif
));
- if (!f) return false;
- strcpy_s(Dst, DstSize, f);
- Status = true;
+ if (f)
+ {
+ strcpy_s(Dst, DstSize, f);
+ Status = true;
+ }
#elif defined MAC
strcpy_s(Dst, DstSize, "/Applications");
Status = true;
#elif defined LINUX
strcpy_s(Dst, DstSize, "/usr/bin");
Status = true;
#elif defined BEOS
LgiAssert(!"Impl me.");
#endif
break;
}
case LSP_APP_INSTALL:
{
if (LgiGetExePath(Dst, DstSize))
{
#if defined WIN32
char *Last = strrchr(Dst, DIR_CHAR);
if (Last)
{
if (stristr(Last,
#ifdef _DEBUG
"Debug"
#else
"Release"
#endif
))
*Last = 0;
}
#elif defined MAC
char *Last = strrchr(Dst, DIR_CHAR);
if (Last)
{
if (!stricmp(Last,
#ifdef _DEBUG
"/Debug"
#else
"/Release"
#endif
))
*Last = 0;
}
if ((Last = strrchr(Dst, DIR_CHAR)))
{
if (!stricmp(Last, "/build"))
*Last = 0;
}
#endif
return true;
}
break;
}
case LSP_APP_ROOT:
{
#ifndef LGI_STATIC
if (!LgiApp)
{
LgiAssert(0);
break;
}
char *Name = LgiApp->Name();
if (!Name)
{
LgiAssert(0);
break;
}
GAutoString Base;
#if defined MAC && !defined COCOA
FSRef Ref;
OSErr e = FSFindFolder(kUserDomain, kDomainLibraryFolderType, kDontCreateFolder, &Ref);
if (e)
{
printf("%s:%i - FSFindFolder failed e=%i\n", _FL, e);
LgiAssert(0);
}
else
{
Base = FSRefPath(Ref);
}
#elif defined WIN32
Base.Reset(GetWindowsFolder(CSIDL_APPDATA));
#elif defined LINUX
char Dot[128];
snprintf(Dot, sizeof(Dot), ".%s", Name);
Name = Dot;
struct passwd *pw = getpwuid(getuid());
if (pw)
{
Base.Reset(NewStr(pw->pw_dir));
}
else LgiAssert(0);
#else
LgiAssert(0);
#endif
if (Base)
{
LgiMakePath(Dst, DstSize, Base, Name);
Status = true;
}
else
#endif
{
LgiAssert(0);
}
break;
}
case LSP_OS:
{
#if defined WIN32
char p[MAX_PATH];
if (GetWindowsDirectory(p, sizeof(p)) > 0)
{
strcpy_s(Dst, DstSize, p);
Status = true;
}
#elif defined MAC && !defined COCOA
FSRef Ref;
OSErr e = FSFindFolder(kOnAppropriateDisk, kSystemFolderType, kDontCreateFolder, &Ref);
if (e) printf("%s:%i - FSFindFolder failed e=%i\n", __FILE__, __LINE__, e);
else
{
GAutoString u = FSRefPath(Ref);
if (u)
{
strcpy_s(Dst, DstSize, u);
Status = true;
}
}
#else
strcpy_s(Dst, DstSize, "/boot"); // it'll do for now...
Status = true;
#endif
break;
}
case LSP_OS_LIB:
{
#if defined WIN32
char p[MAX_PATH];
if (GetSystemDirectory(p, sizeof(p)) > 0)
{
strcpy_s(Dst, DstSize, p);
Status = true;
}
#elif defined MAC
strcpy_s(Dst, DstSize, "/Library");
Status = true;
#else
strcpy_s(Dst, DstSize, "/lib"); // it'll do for now...
Status = true;
#endif
break;
}
case LSP_TEMP:
{
#if defined WIN32
if (LgiGetOs() == LGI_OS_WIN9X)
{
char t[256];
if (GetTempPath(sizeof(t), t) > 0)
{
char *utf = LgiToNativeCp(t);
if (utf)
{
strcpy_s(Dst, DstSize, utf);
DeleteArray(utf);
Status = true;
}
}
}
else
{
char16 t[256];
if (GetTempPathW(CountOf(t), t) > 0)
{
char *utf = LgiNewUtf16To8(t);
if (utf)
{
strcpy_s(Dst, DstSize, utf);
DeleteArray(utf);
Status = true;
}
}
}
#elif defined MAC && !defined COCOA
FSRef Ref;
OSErr e = FSFindFolder(kUserDomain, kTemporaryFolderType, kCreateFolder, &Ref);
if (e) LgiTrace("%s:%i - FSFindFolder failed e=%i\n", _FL, e);
else
{
GAutoString u = FSRefPath(Ref);
if (u)
{
strcpy_s(Dst, DstSize, u);
Status = true;
}
else LgiTrace("%s:%i - FSRefPath failed.\n", _FL);
}
#else
strcpy_s(Dst, DstSize, "/tmp"); // it'll do for now...
Status = true;
#endif
break;
}
case LSP_COMMON_APP_DATA:
{
#if defined WIN32
GAutoString f(GetWindowsFolder(CSIDL_COMMON_APPDATA));
if (f)
{
strcpy_s(Dst, DstSize, f);
Status = true;
}
#elif defined MAC && !defined COCOA
FSRef Ref;
OSErr e = FSFindFolder(kOnSystemDisk, kDomainLibraryFolderType, kDontCreateFolder, &Ref);
if (e) printf("%s:%i - FSFindFolder failed e=%i\n", __FILE__, __LINE__, e);
else
{
GAutoString u = FSRefPath(Ref);
if (u)
{
strcpy_s(Dst, DstSize, u);
Status = true;
}
}
#elif defined LINUX
strcpy_s(Dst, DstSize, "/usr");
Status = true;
#elif defined BEOS
strcpy_s(Dst, DstSize, "/boot/apps");
Status = true;
#endif
break;
}
case LSP_USER_APP_DATA:
{
#if defined WIN32
GAutoString f(GetWindowsFolder(CSIDL_APPDATA));
if (f)
{
strcpy_s(Dst, DstSize, f);
Status = true;
}
#elif defined MAC && !defined COCOA
FSRef Ref;
OSErr e = FSFindFolder(kUserDomain, kDomainLibraryFolderType, kDontCreateFolder, &Ref);
if (e) printf("%s:%i - FSFindFolder failed e=%i\n", __FILE__, __LINE__, e);
else
{
GAutoString u = FSRefPath(Ref);
if (u)
{
strcpy_s(Dst, DstSize, u);
Status = true;
}
}
#elif defined LINUX
strcpy_s(Dst, DstSize, "/usr");
Status = true;
#endif
break;
}
case LSP_LOCAL_APP_DATA:
{
#if defined WIN32
GAutoString f(GetWindowsFolder(CSIDL_LOCAL_APPDATA));
if (f)
{
strcpy_s(Dst, DstSize, f);
Status = true;
}
#else
LgiAssert(!"Impl me.");
#endif
break;
}
case LSP_DESKTOP:
{
#if defined(_WINDOWS) && defined(_MSC_VER)
GAutoString f(GetWindowsFolder(CSIDL_DESKTOPDIRECTORY));
if (f)
{
strcpy_s(Dst, DstSize, f);
Status = true;
}
#elif defined MAC && !defined COCOA
FSRef Ref;
OSErr e = FSFindFolder(kOnAppropriateDisk, kDesktopFolderType, kDontCreateFolder, &Ref);
if (e) printf("%s:%i - FSFindFolder failed e=%i\n", __FILE__, __LINE__, e);
else
{
GAutoString u = FSRefPath(Ref);
if (u)
{
strcpy_s(Dst, DstSize, u);
Status = true;
}
}
#elif defined POSIX
struct passwd *pw = getpwuid(getuid());
if (pw)
{
#ifdef LINUX
WindowManager wm = LgiGetWindowManager();
if (wm == WM_Gnome)
sprintf_s(Dst, sizeof(Dst), "%s/.gnome-desktop", pw->pw_dir);
else
#endif
sprintf_s(Dst, sizeof(Dst), "%s/Desktop", pw->pw_dir);
Status = true;
}
#elif defined BEOS
strcpy_s(Dst, DstSize, "/boot/home/Desktop");
Status = true;
#endif
break;
}
case LSP_HOME:
{
#if defined WIN32
#ifndef CSIDL_PROFILE
#define CSIDL_PROFILE 0x0028
#endif
GAutoString f(GetWindowsFolder(CSIDL_PROFILE));
if (f)
{
strcpy_s(Dst, DstSize, f);
Status = true;
}
#elif defined POSIX
struct passwd *pw = getpwuid(getuid());
if (pw)
{
strcpy_s(Dst, DstSize, pw->pw_dir);
Status = true;
}
#elif defined BEOS
strcpy_s(Dst, DstSize, "/boot/home");
Status = true;
#endif
break;
}
case LSP_EXE:
{
if (LgiGetExeFile(Dst, DstSize))
{
LgiTrimDir(Dst);
Status = true;
}
break;
}
case LSP_TRASH:
{
#if defined LINUX
switch (LgiGetWindowManager())
{
case WM_Kde:
{
static char KdeTrash[256] = "";
if (!ValidStr(KdeTrash))
{
// Ask KDE where the current trash is...
GProcess p;
GStringPipe o;
if (p.Run("kde-config", "--userpath trash", 0, true, 0, &o))
{
char *s = o.NewStr();
if (s)
{
// Store it..
strcpy_s(KdeTrash, sizeof(KdeTrash), s);
DeleteArray(s);
// Clear out any crap at the end...
char *e = KdeTrash + strlen(KdeTrash) - 1;
while (e > KdeTrash && strchr(" \r\n\t/", *e))
{
*e-- = 0;
}
}
else
{
printf("%s:%i - No output from 'kde-config'.\n", __FILE__, __LINE__);
}
}
else
{
printf("%s:%i - Run 'kde-config' failed.\n", __FILE__, __LINE__);
}
}
if (ValidStr(KdeTrash))
{
strcpy_s(Dst, DstSize, KdeTrash);
Status = true;
}
break;
}
default:
{
printf("%s:%i - Unknown window manager.\n", __FILE__, __LINE__);
break;
}
}
#elif defined MAC && !defined COCOA
FSRef Ref;
OSErr e = FSFindFolder(kUserDomain, kTrashFolderType, kDontCreateFolder, &Ref);
if (e) printf("%s:%i - FSFindFolder failed e=%i\n", __FILE__, __LINE__, e);
else
{
GAutoString u = FSRefPath(Ref);
if (u)
{
strcpy_s(Dst, DstSize, u);
Status = true;
}
}
#elif defined WIN32
// This should work but doesn't... *shrug*
// char *f = GetWin32Folder(CSIDL_BITBUCKET);
#else
#endif
break;
}
}
}
return Status;
}
bool LgiGetExeFile(char *Dst, int DstSize)
{
if (Dst)
{
#if defined WIN32
if (LgiGetOs() == LGI_OS_WIN9X)
{
char Exe[256];
if (GetModuleFileName(NULL, Exe, sizeof(Exe)) > 0)
{
char *e = LgiFromNativeCp(Exe);
if (e)
{
strlwr(e);
strcpy_s(Dst, DstSize, e);
DeleteArray(e);
return true;
}
else
{
LgiMsg(0, "LgiFromNativeCp returned 0, ANSI CodePage=%i (%s)", "LgiGetExeFile Error", MB_OK, GetACP(), LgiAnsiToLgiCp());
}
}
char m[256];
sprintf_s(m, sizeof(m), "GetModuleFileName failed err: %08.8X", GetLastError());
MessageBox(0, m, "LgiGetExeFile Error", MB_OK);
LgiExitApp();
}
else
{
char16 Exe[256];
if (GetModuleFileNameW(NULL, Exe, sizeof(Exe)) > 0)
{
char *e = LgiNewUtf16To8(Exe);
if (e)
{
strcpy_s(Dst, DstSize, e);
DeleteArray(e);
return true;
}
}
}
#elif defined BEOS
app_info Info;
if (LgiApp->GetAppInfo(&Info) == B_OK)
{
BEntry e(&Info.ref);
BPath p;
if (e.GetPath(&p) == B_OK)
{
strcpy_s(Dst, DstSize, p.Path());
return true;
}
}
#elif defined ATHEOS
os::Directory AppPath;
if (AppPath.SetTo("^/.") == 0)
{
std::string p;
if (AppPath.GetPath(&p) == 0)
{
sprintf_s(Dst, DstSize, "%s%s%s", p.c_str(), DIR_STR, LgiApp->_AppFile);
return true;
}
}
#elif defined LINUX
static char ExePathCache[256] = "";
bool Status = false;
// this is _REALLY_ lame way to do it... but hey there aren't any
// other better ways to get the full path of the running executable
if (!ExePathCache[0])
{
// First try the self method
int Len = readlink("/proc/self/exe", ExePathCache, sizeof(ExePathCache));
Status = FileExists(ExePathCache);
// printf("readlink=%i Status=%i Exe='%s'\n", Len, Status, ExePathCache);
if (!Status)
{
ExePathCache[0] = 0;
// Next try the map file method
char ProcFile[256];
sprintf_s(ProcFile, sizeof(ProcFile), "/proc/%i/maps", getpid());
int fd = open(ProcFile, O_RDONLY);
if (fd >= 0)
{
int Len = 16 << 10; // is this enough?
// no better way of determining the length of proc info?
char *Buf = new char[Len+1];
if (Buf)
{
int r = read(fd, Buf, Len);
Buf[r] = 0;
char *s = strchr(Buf, '/');
if (s)
{
char *e = strchr(s, '\n');
if (e)
{
*e = 0;
strcpy_s(ExePathCache, sizeof(ExePathCache), s);
Status = true;
}
}
DeleteArray(Buf);
}
close(fd);
}
else
{
// Non proc system (like cygwin for example)
// char Cmd[256];
// sprintf_s(Cmd, sizeof(Cmd), "ps | grep \"%i\"", getpid());
GStringPipe Ps;
GProcess p;
if (p.Run("ps", 0, 0, true, 0, &Ps))
{
char *PsOutput = Ps.NewStr();
if (PsOutput)
{
GToken n(PsOutput, "\r\n");
for (int i=0; !Status && i 7)
{
int LinePid = 0;
for (int i=0; i Ext;
GArray Files;
Ext.Add((char*)Name);
#if DEBUG_FIND_FILE
printf("%s:%i - Exe='%s'\n", __FILE__, __LINE__, Exe);
#endif
if (LgiRecursiveFileSearch(Exe, &Ext, &Files) &&
Files.Length())
{
Result = Files[0];
Files.DeleteAt(0);
}
Files.DeleteArrays();
}
return Result;
}
#if defined WIN32
static LARGE_INTEGER Freq = {0};
static bool CurTimeInit = false;
#endif
uint64 LgiCurrentTime()
{
#if defined WIN32
if (!CurTimeInit)
{
CurTimeInit = true;
if (!QueryPerformanceFrequency(&Freq))
Freq.QuadPart = 0;
}
if (Freq.QuadPart)
{
// Return performance counter in ms
LARGE_INTEGER i;
if (QueryPerformanceCounter(&i))
{
return i.QuadPart * 1000 / Freq.QuadPart;
}
// Now what?? Give up and go back to tick count I guess.
Freq.QuadPart = 0;
}
// Fall back for systems without a performance counter.
return GetTickCount();
#elif defined BEOS
return system_time() / 1000;
#elif defined MAC && !defined COCOA
UnsignedWide t;
Microseconds(&t);
uint64 i = ((uint64)t.hi << 32) | t.lo;
return i / 1000;
#else
timeval tv;
gettimeofday(&tv, 0);
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
#endif
}
uint64 LgiMicroTime()
{
#if defined WIN32
if (!CurTimeInit)
{
CurTimeInit = true;
if (!QueryPerformanceFrequency(&Freq))
Freq.QuadPart = 0;
}
if (Freq.QuadPart)
{
// Return performance counter in ms
LARGE_INTEGER i;
if (QueryPerformanceCounter(&i))
{
return i.QuadPart * 1000000 / Freq.QuadPart;
}
}
return 0;
#elif defined BEOS
LgiAssert(!"Not impl.");
return 0;
#elif defined MAC && !defined COCOA
UnsignedWide t;
Microseconds(&t);
return ((uint64)t.hi << 32) | t.lo;
#else
timeval tv;
gettimeofday(&tv, 0);
return (tv.tv_sec * 1000000) + tv.tv_usec;
#endif
}
int LgiIsReleaseBuild()
{
#ifdef _DEBUG
return 0;
#else
return 1;
#endif
}
void LgiFormatSize(char *Str, int SLen, uint64 Size)
{
int64 K = 1024;
int64 M = K * K;
int64 G = K * M;
if (Size == 1)
{
strcpy_s(Str, SLen, "1 byte");
}
else if (Size < K)
{
sprintf_s(Str, SLen, "%u bytes", (int)Size);
}
else if (Size < 10 * K)
{
double d = (double)(int64)Size;
sprintf_s(Str, SLen, "%.2f K", d / K);
}
else if (Size < M)
{
sprintf_s(Str, SLen, "%u K", (int) (Size / K));
}
else if (Size < G)
{
double d = (double)(int64)Size;
sprintf_s(Str, SLen, "%.2f M", d / M);
}
else
{
double d = (double)(int64)Size;
sprintf_s(Str, SLen, "%.2f G", d / G);
}
}
char *LgiTokStr(const char *&s)
{
char *Status = 0;
if (s && *s)
{
// Skip whitespace
static char Delim[] = ", \t\r\n";
while (*s && strchr(Delim, *s)) s++;
if (*s)
{
if (strchr("\'\"", *s))
{
char Delim = *s++;
const char *e = strchr(s, Delim);
if (!e)
{
// error, no end delimiter
e = s;
while (*e) e++;
}
Status = NewStr(s, e - s);
s = *e ? e + 1 : e;
}
else
{
const char *e = s;
while (*e && !strchr(Delim, *e)) e++;
Status = NewStr(s, e - s);
s = e;
}
}
}
return Status;
}
//////////////////////////////////////////////////////////////////////////////
DoEvery::DoEvery(int p) // p = timeout in ms
{
Init(p);
}
void DoEvery::Init(int p) // p = timeout in ms
{
LastTime = LgiCurrentTime();
if (p > 0)
{
Period = p;
}
}
bool DoEvery::DoNow()
{
int64 Now = LgiCurrentTime();
if (LastTime + Period < Now)
{
LastTime = Now;
return true;
}
return false;
}
///////////////////////////////////////////////////////////////////////////////////
#if 0
GViewFill::GViewFill(GColour c)
{
Type = Solid;
Col = c;
#ifdef WIN32
hBrush = NULL;
#endif
}
GViewFill::GViewFill(COLOUR c, int Bits)
{
Type = Solid;
Col.c32(CBit(32, c, Bits));
#ifdef WIN32
hBrush = NULL;
#endif
}
GViewFill::GViewFill(GSurface *dc, bool Copy)
{
Col.c32(0);
Type = Copy ? OwnBitmap : RefBitmap;
#ifndef LGI_STATIC
if (Copy)
pDC = new GMemDC(dc);
else
pDC = dc;
#endif
#ifdef WIN32
hBrush = NULL;
#endif
}
GViewFill::GViewFill(const GViewFill &f)
{
Col = f.GetFlat();
Type = f.Type;
if (Type == OwnBitmap)
{
#ifndef LGI_STATIC
pDC = new GMemDC(f.pDC);
#endif
}
else if (Type == RefBitmap)
{
pDC = f.pDC;
}
#ifdef WIN32
hBrush = NULL;
#endif
}
GViewFill::~GViewFill()
{
Empty();
}
void GViewFill::Empty()
{
if (Type == OwnBitmap)
DeleteObj(pDC);
Type = None;
pDC = 0;
Col.c32(0);
#ifdef WIN32
if (hBrush)
{
DeleteObject(hBrush);
hBrush = NULL;
}
#endif
}
void GViewFill::Fill(GSurface *pDC, GRect *r, GdcPt2 *Origin)
{
#ifndef LGI_STATIC
if (Type == Solid)
{
pDC->Colour(Col);
pDC->Rectangle(r);
}
else if (Type == OwnBitmap || Type == RefBitmap)
{
if (pDC)
{
GRect a;
if (!r)
{
a.ZOff(pDC->X()-1, pDC->Y()-1);
r = &a;
}
for (int y = Origin ? (Origin->y % pDC->Y()) - pDC->Y() : 0; y < r->Y(); y += pDC->Y())
{
for (int x = Origin ? (Origin->x % pDC->X()) - pDC->X() : 0; xX(); x += pDC->X())
{
pDC->Blt(r->x1 + x, r->y1 + y, pDC);
}
}
}
else
{
LgiAssert(0);
}
}
#endif
}
#ifdef WIN32
/*
HBRUSH GViewFill::GetBrush()
{
if (!hBrush)
{
LOGBRUSH LogBrush;
LogBrush.lbStyle = BS_SOLID;
LogBrush.lbColor = GetFlat().c24();
LogBrush.lbHatch = 0;
hBrush = CreateBrushIndirect(&LogBrush);
}
return hBrush;
}
*/
#endif
#endif
//////////////////////////////////////////////////////////////////////
bool GCapabilityClient::NeedsCapability(const char *Name, const char *Param)
{
for (int i=0; iNeedsCapability(Name, Param);
return Targets.Length() > 0;
}
GCapabilityClient::~GCapabilityClient()
{
for (int i=0; iClients.Delete(this);
}
void GCapabilityClient::Register(GCapabilityTarget *t)
{
if (t)
{
Targets.Add(t);
t->Clients.Add(this);
}
}
GCapabilityTarget::~GCapabilityTarget()
{
for (int i=0; iTargets.Delete(this);
}
/////////////////////////////////////////////////////////////////////
GProfile::GProfile(const char *Name)
{
MinMs = -1;
Add(Name);
}
GProfile::~GProfile()
{
Add("End");
if (MinMs > 0)
{
uint64 TotalMs = s.Last().Time - s[0].Time;
if (TotalMs < MinMs)
{
return;
}
}
for (int i=0; i