Convert ~/ to fully qualified path

Previous topic - Next topic

MrTAToad

As I recently found out, Mac and Linux wont allow programs to use ~/ when creating directories in the home path - it has to be changed to a fully qualified path instead (eg /home/user).

I'm hoping Gernot will change PLATFORMINFO$("DOCUMENTS") to this, but if not, here is a routine for doing the conversion :

Code (glbasic) Select
// --------------------------------- //
// Project: The Grid_Mac
// Start: Wednesday, November 25, 2009
// IDE Version: 7.181

INLINE
#ifdef WIN32
// No need to do anything for Windows
#elif LINUX
typedef struct __password {
char *pw_name; // user name
char *pw_passwd; // user password
int pw_uid; // user id
int pw_gid; // group id
char *pw_gecos; // real name
char *pw_dir; // home directory
char *pw_shell; // shell program
} __password;

extern "C" char *getenv(char *);
extern "C" struct __password *getpwuid(int uid);
extern "C" int getuid(void);
#elif OSXUNI
extern "C" int FSFindFolder(int vRefNum,int folderType,int createFolder,char *foundRef);
extern "C" int FSRefMakePath(char *ref,char *path,int maxPathSize);
#endif
ENDINLINE

FUNCTION GetHomeDir$:
LOCAL temp$

temp$=""

INLINE
#if LINUX
char *ptr;
ptr=getenv("$HOME");
if (!ptr)
{
struct __password *password;

password=getpwuid(getuid());
if (password)
{
if (password->pw_dir)
{
temp_Str.assign(password->pw_dir);
}
}
}
else
{
temp_Str.assign(ptr);
}
#elif OSXUNI
char buffer[1024]={0};
char ref[80]={0};
int kUserDomain=-32763;
int kVolumeRootFolderType=('r'<<24)|('o'<<16)|('o'<<8)|('t');

if (!FSFindFolder(kUserDomain,kVolumeRootFolderType,FALSE,(char *) &ref))
{
if (!FSRefMakePath((char *) &ref,(char *) &buffer,sizeof(buffer)-1))
{
temp_Str.assign((char *) &buffer);
}

}
#else
temp_Str.assign(PLATFORMINFO_Str("DOCUMENTS"));
#endif
ENDINLINE

RETURN temp$
ENDFUNCTION

bigsofty

Another nice snippet, many thanks!  ;)
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

MrTAToad

Vastly updated to allow the program to find the users Music directory, Picture directory and Shared Data directory :

Code (glbasic) Select
// --------------------------------- //
// Project: The Grid_Mac
// Start: Wednesday, November 25, 2009
// IDE Version: 7.181

INLINE
#ifdef WIN32
// No need to do anything for Windows
DECLARE(SHGetFolderPathA,"shell32.dll",(HWND,int,HANDLE,DWORD,LPSTR),int);
const int CSIDL_APPDATA = 0x001A;
const int CSIDL_MYPICTURES = 0x0027;
const int CSIDL_MYMUSIC =   0x000D;
const int SHGFP_TYPE_CURRENT= 0;

#elif LINUX
typedef struct __password {
char *pw_name; // user name
char *pw_passwd; // user password
int pw_uid; // user id
int pw_gid; // group id
char *pw_gecos; // real name
char *pw_dir; // home directory
char *pw_shell; // shell program
} __password;

typedef int size_t;

extern "C" char *getenv(char *);
extern "C" struct __password *getpwuid(int uid);
extern "C" int getuid(void);
extern "C" void * malloc ( size_t size );
extern "C" int open(const char *filename,int oflag,int pmode);
extern "C" int close(int fd);
extern "C" size_t strlen ( const char * str );
extern "C" char * strcpy ( char * destination, const char * source );
extern "C" char * strcat ( char * destination, const char * source );
extern "C" void free ( void * ptr );
extern "C" int read(int fd,void *buffer,unsigned int count);
extern "C" char *strdup(const char *s1);
extern "C" int strcmp ( const char * str1, const char * str2 );
extern "C" int strncmp ( const char * str1, const char * str2, size_t num );
extern "C" int sprintf ( char * str, const char * format, ... );
extern "C" void *memset(void *s, int c, size_t n);

#define O_RDONLY 0
#define O_TEXT 0x4000


#elif OSXUNI
extern "C" int FSFindFolder(int vRefNum,int folderType,int createFolder,char *foundRef);
extern "C" int FSRefMakePath(char *ref,char *path,int maxPathSize);

const int kVolumeRootFolderType = ('r'<<24)|('o'<<16)|('o'<<8)|('t');
const int kMusicDocumentsFolderType = 0xB5646F63;
const int kPictureDocumentsFolderType = ('p'<<24)|('d'<<16)|('o'<<8)|('c');
const int kSharedUserDataFolderType = ('s'<<24)|('d'<<16)|('a'<<8)|('t');


int specificCode(int kind,char *store,int size);


#endif
ENDINLINE

INLINE
#ifdef OSXUNI
int specificCode(int kind,char *store,int size)
{
char ref[80]={0};
int kUserDomain=-32763;

if (!FSFindFolder(kUserDomain,kind,FALSE,(char *) &ref))
{
if (!FSRefMakePath((char *) &ref,store,size-1))
{
return true;
}

}

return false;
}
#elif LINUX
// This is needed so that a line can be read properly (as read reads up to a given number of characters)
int readALine(int handle,char *store,int size)
{
char one;
int index;

index=0;
memset(store,(char) 0,size);
while (read(handle,(char *) &one,sizeof(one))>0)
{
if (index<size)
{
*(store+index)=one;
index++;
if (one=='\n')
{
break;
}
}
else
{
break;
}
}

return (strlen(store));
}

//  This file is not licenced under the GPL like the rest of the code.
//  Its is under the MIT license, to encourage reuse by cut-and-paste.

//  Copyright (c) 2007 Red Hat, inc

//  Permission is hereby granted, free of charge, to any person
//  obtaining a copy of this software and associated documentation files
//  (the "Software"), to deal in the Software without restriction,
//  including without limitation the rights to use, copy, modify, merge,
//  publish, distribute, sublicense, and/or sell copies of the Software,
//  and to permit persons to whom the Software is furnished to do so,
//  subject to the following conditions:

//  The above copyright notice and this permission notice shall be
//  included in all copies or substantial portions of the Software.

//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
//  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
//  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
//  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//  SOFTWARE.

// * xdg_user_dir_lookup_with_fallback:
// * @type: a string specifying the type of directory
// * @fallback: value to use if the directory isn't specified by the user
// * @returns: a newly allocated absolute pathname
// *
// * Looks up a XDG user directory of the specified type.
// * Example of types are "DESKTOP" and "DOWNLOAD".
// *
// * In case the user hasn't specified any directory for the specified
// * type the value returned is @fallback.
// *
// * The return value is newly allocated and must be freed with
// * free(). The return value is never NULL if @fallback != NULL, unless
// * out of memory.
// **/
static char *
xdg_user_dir_lookup_with_fallback (const char *type, const char *fallback)
{
  int file;
  char *home_dir, *config_home, *config_file;
  char buffer[512]={0};
  char *user_dir;
  char *p, *d;
  int len;
  int relative;
 
  home_dir = getenv ("HOME");

  if (home_dir == NULL)
    goto error;

  config_home = getenv ("XDG_CONFIG_HOME");
  if (config_home == NULL || config_home[0] == 0)
    {
      config_file = (char*) malloc (strlen (home_dir) + strlen ("/.config/user-dirs.dirs") + 1);
      if (config_file == NULL)
        goto error;

      strcpy (config_file, home_dir);
      strcat (config_file, "/.config/user-dirs.dirs");
    }
  else
    {
      config_file = (char*) malloc (strlen (config_home) + strlen ("/user-dirs.dirs") + 1);
      if (config_file == NULL)
        goto error;

      strcpy (config_file, config_home);
      strcat (config_file, "/user-dirs.dirs");
    }

  file=open(config_file,O_RDONLY,0);  
  free (config_file);
  if (file<0)
  {
    goto error;
  }
 
  user_dir = NULL;
 
  // Original version used fgets, which isn't availiable here, so I had to use read...
  while (readALine(file,(char *) &buffer,sizeof(buffer))>0)
  {
      /* Remove newline at end */
      len = strlen (buffer);
      if (len > 0 && buffer[len-1] == '\n')
buffer[len-1] = 0;
     
      p = buffer;
      while (*p == ' ' || *p == '\t')
p++;
     
      if (strncmp (p, "XDG_", 4) != 0)
continue;
      p += 4;
      if (strncmp (p, type, strlen (type)) != 0)
continue;
      p += strlen (type);
      if (strncmp (p, "_DIR", 4) != 0)
continue;
      p += 4;

      while (*p == ' ' || *p == '\t')
p++;

      if (*p != '=')
continue;
      p++;
     
      while (*p == ' ' || *p == '\t')
p++;

      if (*p != '"')
continue;
      p++;
     
      relative = 0;
      if (strncmp (p, "$HOME/", 6) == 0)
{
  p += 6;
  relative = 1;
}
      else if (*p != '/')
continue;
     
      if (relative)
{
  user_dir = (char*) malloc (strlen (home_dir) + 1 + strlen (p) + 1);
          if (user_dir == NULL)
            goto error2;

  strcpy (user_dir, home_dir);
  strcat (user_dir, "/");
}
      else
{
  user_dir = (char*) malloc (strlen (p) + 1);
          if (user_dir == NULL)
            goto error2;

  *user_dir = 0;
}
     
      d = user_dir + strlen (user_dir);
      while (*p && *p != '"')
{
  if ((*p == '\\') && (*(p+1) != 0))
    p++;
  *d++ = *p++;
}
      *d = 0;
  }
error2:
  close (file);

  if (user_dir)
    return user_dir;

error:
  if (fallback)
    return strdup (fallback);
  return NULL;
}

/**
* xdg_user_dir_lookup:
* @type: a string specifying the type of directory
* @returns: a newly allocated absolute pathname
*
* Looks up a XDG user directory of the specified type.
* Example of types are "DESKTOP" and "DOWNLOAD".
*
* The return value is always != NULL (unless out of memory),
* and if a directory
* for the type is not specified by the user the default
* is the home directory. Except for DESKTOP which defaults
* to ~/Desktop.
*
* The return value is newly allocated and must be freed with
* free().
**/
static char *
xdg_user_dir_lookup (const char *type)
{
  char *dir, *home_dir, *user_dir;
 
  dir = xdg_user_dir_lookup_with_fallback (type, NULL);
  if (dir != NULL)
    return dir;
 
  home_dir = getenv("HOME");
 
  if (home_dir == NULL)
    return strdup ("/tmp");
 
  /* Special case desktop for historical compatibility */
  if (strcmp (type, "DESKTOP") == 0)
    {
      user_dir = (char*) malloc (strlen (home_dir) + strlen ("/Desktop") + 1);
      if (user_dir == NULL)
        return NULL;

      strcpy (user_dir, home_dir);
      strcat (user_dir, "/Desktop");
      return user_dir;
    }
 
  return strdup (home_dir);
}

#ifdef STANDALONE_XDG_USER_DIR_LOOKUP
int
main (int argc, char *argv[])
{
  if (argc != 2)
    {
      fprintf (stderr, "Usage %s <dir-type>\n", argv[0]);
      exit (1);
    }
 
  printf ("%s\n", xdg_user_dir_lookup (argv[1]));
  return 0;
}
#endif
#endif
ENDINLINE

FUNCTION GetHomeDir$:
LOCAL temp$

temp$=""

INLINE
#if WIN32
temp_Str.assign(PLATFORMINFO_Str("DOCUMENTS"));
#elif LINUX
char *ptr;
ptr=getenv("$HOME");
if (!ptr)
{
struct __password *password;

password=getpwuid(getuid());
if (password)
{
if (password->pw_dir)
{
temp_Str.assign(password->pw_dir);
}
}
}
else
{
temp_Str.assign(ptr);
}
#elif OSXUNI
char buffer[1024]={0};
char ref[80]={0};
int kUserDomain=-32763;

if (!FSFindFolder(kUserDomain,kVolumeRootFolderType,FALSE,(char *) &ref))
{
if (!FSRefMakePath((char *) &ref,(char *) &buffer,sizeof(buffer)-1))
{
temp_Str.assign((char *) &buffer);
}

}
#else
temp_Str.assign(PLATFORMINFO_Str("DOCUMENTS"));
#endif
ENDINLINE

RETURN temp$
ENDFUNCTION

FUNCTION getPicturesDir$:
LOCAL temp$

temp$=""

INLINE
#ifdef WIN32
char path[261]={0};

if (SHGetFolderPathA(NULL,CSIDL_MYPICTURES,NULL,SHGFP_TYPE_CURRENT,(char *) &path)==0)
{
temp_Str.assign((char *) &path);
}
#elif OSXUNI
char buffer[1024];

if (specificCode(kPictureDocumentsFolderType,(char *) &buffer,sizeof(buffer)))
{
temp_Str.assign((char *) &buffer);
}
#elif LINUX
char *ptr;

ptr=xdg_user_dir_lookup("PICTURES");
if (ptr)
{
temp_Str.assign(ptr);
}
#endif
ENDINLINE

RETURN temp$
ENDFUNCTION

FUNCTION GetMusicDir$:
LOCAL temp$

temp$=""

INLINE
#ifdef WIN32
char path[261]={0};

if (SHGetFolderPathA(NULL,CSIDL_MYMUSIC,NULL,SHGFP_TYPE_CURRENT,(char *) &path)==0)
{
temp_Str.assign((char *) &path);
}
#elif OSXUNI
char buffer[1024];

if (specificCode(kMusicDocumentsFolderType,(char *) &buffer,sizeof(buffer)))
{
temp_Str.assign((char *) &buffer);
}
#elif LINUX
char *ptr;

ptr=xdg_user_dir_lookup("MUSIC");
if (ptr)
{
temp_Str.assign(ptr);
}
#endif
ENDINLINE

RETURN temp$
ENDFUNCTION

FUNCTION GetSharedDataDir$:
LOCAL temp$

temp$=""

INLINE
#ifdef WIN32
char path[261]={0};

if (SHGetFolderPathA(NULL,CSIDL_APPDATA,NULL,SHGFP_TYPE_CURRENT,(char *) &path)==0)
{
temp_Str.assign((char *) &path);
}
#elif OSXUNI
char buffer[1024];

if (specificCode(kSharedUserDataFolderType,(char *) &buffer,sizeof(buffer)))
{
temp_Str.assign((char *) &buffer);
}
#elif LINUX
char *ptr;

ptr=xdg_user_dir_lookup("PUBLICSHARE");
if (ptr)
{
temp_Str.assign(ptr);
}
#endif
ENDINLINE


   RETURN temp$
ENDFUNCTION

Kitty Hello

Excellent work. Will implement that instead of "~". Was a quick shot in the oven.

MrTAToad

Great!  That'll be useful - especially if you can do the Music, Pictures and Shared Data areas too :)

MrTAToad

#5
Its now been updated for Windows CE :

Code (glbasic) Select
// --------------------------------- //
// Project: Get Application Directories
// Start: Wednesday, November 25, 2009
// IDE Version: 7.181

INLINE
#ifdef _WIN32_WCE
typedef int size_t;

typedef int BOOL;
typedef int LPBOOL;
typedef unsigned int   UINT;
typedef char *LPCSTR;
typedef const wchar_t  *LPTSTR;
typedef wchar_t  WCHAR;

extern "C" BOOL SHGetSpecialFolderPath(HWND hwndOwner,LPTSTR lpszPath,int nFolder,BOOL fCreate);
extern "C" int WideCharToMultiByte(UINT CodePage,DWORD dwFlags,LPCWSTR lpWideCharStr,int cchWideChar,LPSTR lpMultiByteStr,
int cbMultiByte,LPCSTR lpDefaultChar,LPBOOL lpUsedDefaultChar);
extern "C" void * calloc ( size_t num, size_t size );
extern "C" void free ( void * ptr );
extern "C" int sprintf ( char * str, const char * format, ... );
extern "C" size_t wcslen(const wchar_t *str);
const int CSIDL_APPDATA = 0x001A;
const int CSIDL_MYPICTURES = 0x0027;
const int CSIDL_MYMUSIC = 0x000d;

#define MAX_PATH 260
#define CP_ACP 0
#elif WIN32
// No need to do anything for Windows
DECLARE(SHGetFolderPathA,"shell32.dll",(HWND,int,HANDLE,DWORD,LPSTR),int);
const int CSIDL_APPDATA = 0x001A;
const int CSIDL_MYPICTURES = 0x0027;
const int CSIDL_MYMUSIC =   0x000D;
const int SHGFP_TYPE_CURRENT= 0;

#define MAX_PATH 260
#elif LINUX
typedef struct __password {
char *pw_name; // user name
char *pw_passwd; // user password
int pw_uid; // user id
int pw_gid; // group id
char *pw_gecos; // real name
char *pw_dir; // home directory
char *pw_shell; // shell program
} __password;

typedef int size_t;

extern "C" char *getenv(char *);
extern "C" struct __password *getpwuid(int uid);
extern "C" int getuid(void);
extern "C" void * malloc ( size_t size );
extern "C" int open(const char *filename,int oflag,int pmode);
extern "C" int close(int fd);
extern "C" size_t strlen ( const char * str );
extern "C" char * strcpy ( char * destination, const char * source );
extern "C" char * strcat ( char * destination, const char * source );
extern "C" void free ( void * ptr );
extern "C" int READ(int fd,void *buffer,unsigned int count);
extern "C" char *strdup(const char *s1);
extern "C" int strcmp ( const char * str1, const char * str2 );
extern "C" int strncmp ( const char * str1, const char * str2, size_t num );
extern "C" int sprintf ( char * str, const char * format, ... );
extern "C" void *memset(void *s, int c, size_t n);

#define O_RDONLY 0
#define O_TEXT 0x4000
#elif OSXUNI
extern "C" int FSFindFolder(int vRefNum,int folderType,int createFolder,char *foundRef);
extern "C" int FSRefMakePath(char *ref,char *path,int maxPathSize);

const int kVolumeRootFolderType = ('r'<<24)|('o'<<16)|('o'<<8)|('t');
const int kMusicDocumentsFolderType = 0xB5646F63;
const int kPictureDocumentsFolderType = ('p'<<24)|('d'<<16)|('o'<<8)|('c');
const int kSharedUserDataFolderType = ('s'<<24)|('d'<<16)|('a'<<8)|('t');


int specificCode(int kind,char *store,int size);

#define BUFFER_SIZE 1024
#endif
ENDINLINE

INLINE
#ifdef OSXUNI
int specificCode(int kind,char *store,int size)
{
char ref[80]={0};
int kUserDomain=-32763;

if (!FSFindFolder(kUserDomain,kind,FALSE,(char *) &ref))
{
if (!FSRefMakePath((char *) &ref,store,size-1))
{
return true;
}

}

return false;
}
#elif LINUX
// This is needed so that a line can be read properly (as read reads up to a given number of characters)
int readALine(int handle,char *store,int size)
{
char one;
int index;

index=0;
memset(store,(char) 0,size);
WHILE (READ(handle,(char *) &one,sizeof(one))>0)
{
IF (index<size)
{
*(store+index)=one;
index++;
IF (one=='\n')
{
BREAK;
}
}
ELSE
{
BREAK;
}
}

RETURN (strlen(store));
}

//  This file is not licenced under the GPL like the rest of the code.
//  Its is under the MIT license, to encourage reuse by cut-and-paste.

//  Copyright (c) 2007 Red Hat, inc

//  Permission is hereby granted, free of charge, to any person
//  obtaining a copy of this software and associated documentation files
//  (the "Software"), to deal in the Software without restriction,
//  including without limitation the rights to use, copy, modify, merge,
//  publish, distribute, sublicense, and/or sell copies of the Software,
//  and to permit persons to whom the Software is furnished to do so,
//  subject to the following conditions:

//  The above copyright notice and this permission notice shall be
//  included in all copies or substantial portions of the Software.

//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
//  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
//  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
//  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//  SOFTWARE.

// * xdg_user_dir_lookup_with_fallback:
// * @type: a string specifying the type of directory
// * @fallback: value to use if the directory isn't specified by the user
// * @returns: a newly allocated absolute pathname
// *
// * Looks up a XDG user directory of the specified type.
// * Example of types are "DESKTOP" and "DOWNLOAD".
// *
// * In case the user hasn't specified any directory for the specified
// * type the value returned is @fallback.
// *
// * The return value is newly allocated and must be freed with
// * free(). The return value is never NULL if @fallback != NULL, unless
// * out of memory.
// **/
static char *
xdg_user_dir_lookup_with_fallback (const char *type, const char *fallback)
{
  int file;
  char *home_dir, *config_home, *config_file;
  char buffer[512]={0};
  char *user_dir;
  char *p, *d;
  int len;
  int relative;

  home_dir = getenv ("HOME");

  if (home_dir == NULL)
    goto error;

  config_home = getenv ("XDG_CONFIG_HOME");
  if (config_home == NULL || config_home[0] == 0)
    {
      config_file = (char*) malloc (strlen (home_dir) + strlen ("/.config/user-dirs.dirs") + 1);
      if (config_file == NULL)
        goto error;

      strcpy (config_file, home_dir);
      strcat (config_file, "/.config/user-dirs.dirs");
    }
  else
    {
      config_file = (char*) malloc (strlen (config_home) + strlen ("/user-dirs.dirs") + 1);
      if (config_file == NULL)
        goto error;

      strcpy (config_file, config_home);
      strcat (config_file, "/user-dirs.dirs");
    }

  file=open(config_file,O_RDONLY,0);
  free (config_file);
  if (file<0)
  {
    goto error;
  }

  user_dir = NULL;

  // Original version used fgets, which isn't availiable here, so I had to use read...
  while (readALine(file,(char *) &buffer,sizeof(buffer))>0)
  {
      /* Remove newline at end */
      len = strlen (buffer);
      if (len > 0 && buffer[len-1] == '\n')
buffer[len-1] = 0;

      p = buffer;
      while (*p == ' ' || *p == '\t')
p++;

      if (strncmp (p, "XDG_", 4) != 0)
continue;
      p += 4;
      if (strncmp (p, type, strlen (type)) != 0)
continue;
      p += strlen (type);
      if (strncmp (p, "_DIR", 4) != 0)
continue;
      p += 4;

      while (*p == ' ' || *p == '\t')
p++;

      if (*p != '=')
continue;
      p++;

      while (*p == ' ' || *p == '\t')
p++;

      if (*p != '"')
continue;
      p++;

      relative = 0;
      if (strncmp (p, "$HOME/", 6) == 0)
{
  p += 6;
  relative = 1;
}
      else if (*p != '/')
continue;

      if (relative)
{
  user_dir = (char*) malloc (strlen (home_dir) + 1 + strlen (p) + 1);
          if (user_dir == NULL)
            goto error2;

  strcpy (user_dir, home_dir);
  strcat (user_dir, "/");
}
      else
{
  user_dir = (char*) malloc (strlen (p) + 1);
          if (user_dir == NULL)
            goto error2;

  *user_dir = 0;
}

      d = user_dir + strlen (user_dir);
      while (*p && *p != '"')
{
  if ((*p == '\\') && (*(p+1) != 0))
    p++;
  *d++ = *p++;
}
      *d = 0;
  }
error2:
  close (file);

  if (user_dir)
    return user_dir;

error:
  if (fallback)
    return strdup (fallback);
  return NULL;
}

/**
* xdg_user_dir_lookup:
* @type: a string specifying the type of directory
* @returns: a newly allocated absolute pathname
*
* Looks up a XDG user directory of the specified type.
* Example of types are "DESKTOP" and "DOWNLOAD".
*
* The return value is always != NULL (unless out of memory),
* and if a directory
* for the type is not specified by the user the default
* is the home directory. Except for DESKTOP which defaults
* to ~/Desktop.
*
* The return value is newly allocated and must be freed with
* free().
**/
static char *
xdg_user_dir_lookup (const char *type)
{
  char *dir, *home_dir, *user_dir;

  dir = xdg_user_dir_lookup_with_fallback (type, NULL);
  if (dir != NULL)
    return dir;

  home_dir = getenv("HOME");

  if (home_dir == NULL)
    return strdup ("/tmp");

  /* Special case desktop for historical compatibility */
  if (strcmp (type, "DESKTOP") == 0)
    {
      user_dir = (char*) malloc (strlen (home_dir) + strlen ("/Desktop") + 1);
      if (user_dir == NULL)
        return NULL;

      strcpy (user_dir, home_dir);
      strcat (user_dir, "/Desktop");
      return user_dir;
    }

  return strdup (home_dir);
}

#ifdef STANDALONE_XDG_USER_DIR_LOOKUP
int
main (int argc, char *argv[])
{
  if (argc != 2)
    {
      fprintf (stderr, "Usage %s <dir-type>\n", argv[0]);
      exit (1);
    }

  printf ("%s\n", xdg_user_dir_lookup (argv[1]));
  return 0;
}
#endif
#elif _WIN32_WCE
char *convertCSIDLToMultiByte(int which)
{
WCHAR path[MAX_PATH+1];
int size;
char *ptr;
char t[256];

SHGetSpecialFolderPath((HWND) GLBASIC_HWND(),path,which,FALSE);
if (wcslen(path))
{
size=WideCharToMultiByte(0, 0, (LPCWSTR) path, -1, NULL, 0,  NULL, NULL);
if (size)
{
ptr=(char *) calloc(1,size+1);
if (ptr)
{
WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) path, -1, (LPSTR) ptr, size,NULL,NULL);
return ptr;
}
}
}

return NULL;
}
#endif
ENDINLINE

FUNCTION GetHomeDir$:
LOCAL temp$

temp$=""

INLINE
#if _WIN32_WCE
temp_Str.assign(PLATFORMINFO_Str("DOCUMENTS"));
#elif WIN32
temp_Str.assign(PLATFORMINFO_Str("DOCUMENTS"));
#elif LINUX
char *ptr;
ptr=getenv("HOME");
if (!ptr)
{
struct __password *password;

password=getpwuid(getuid());
if (password)
{
if (password->pw_dir)
{
temp_Str.assign(password->pw_dir);
}
}
}
else
{
temp_Str.assign(ptr);
}
#elif OSXUNI
char buffer[BUFFER_SIZE]={0};

if (specificCode(kVolumeRootFolderType,(char *) &buffer,sizeof(buffer)-1))
{
temp_Str.assign((char *) &buffer);
}
#else
temp_Str.assign(PLATFORMINFO_Str("DOCUMENTS"));
#endif
ENDINLINE

RETURN temp$
ENDFUNCTION

FUNCTION getPicturesDir$:
LOCAL temp$

temp$=""

INLINE
#ifdef _WIN32_WCE
char *ptr;

ptr=convertCSIDLToMultiByte(CSIDL_MYPICTURES);
if (ptr)
{
temp_Str.assign(ptr);
free(ptr);
}
#elif WIN32
char path[MAX_PATH+1]={0};

if (SHGetFolderPathA(NULL,CSIDL_MYPICTURES,NULL,SHGFP_TYPE_CURRENT,(char *) &path)==0)
{
temp_Str.assign((char *) &path);
}
#elif OSXUNI
char buffer[BUFFER_SIZE]={0};

if (specificCode(kPictureDocumentsFolderType,(char *) &buffer,sizeof(buffer)-1))
{
temp_Str.assign((char *) &buffer);
}
#elif LINUX
char *ptr;

ptr=xdg_user_dir_lookup("PICTURES");
if (ptr)
{
temp_Str.assign(ptr);
}
#endif
ENDINLINE

RETURN temp$
ENDFUNCTION

FUNCTION GetMusicDir$:
LOCAL temp$

temp$=""

INLINE
#ifdef _WIN32_WCE
char *ptr;

ptr=convertCSIDLToMultiByte(CSIDL_MYMUSIC);
if (ptr)
{
temp_Str.assign(ptr);
free(ptr);
}

#elif WIN32
char path[MAX_PATH+1]={0};

if (SHGetFolderPathA(NULL,CSIDL_MYMUSIC,NULL,SHGFP_TYPE_CURRENT,(char *) &path)==0)
{
temp_Str.assign((char *) &path);
}
#elif OSXUNI
char buffer[BUFFER_SIZE];

if (specificCode(kMusicDocumentsFolderType,(char *) &buffer,sizeof(buffer)-1))
{
temp_Str.assign((char *) &buffer);
}
#elif LINUX
char *ptr;

ptr=xdg_user_dir_lookup("MUSIC");
if (ptr)
{
temp_Str.assign(ptr);
}
#endif
ENDINLINE

RETURN temp$
ENDFUNCTION

FUNCTION GetSharedDataDir$:
LOCAL temp$

temp$=""

INLINE
#ifdef _WIN32_WCE
char *ptr;

ptr=convertCSIDLToMultiByte(CSIDL_APPDATA);
if (ptr)
{
temp_Str.assign(ptr);
free(ptr);
}
#elif WIN32
char path[MAX_PATH+1]={0};

if (SHGetFolderPathA(NULL,CSIDL_APPDATA,NULL,SHGFP_TYPE_CURRENT,(char *) &path)==0)
{
temp_Str.assign((char *) &path);
}
#elif OSXUNI
char buffer[BUFFER_SIZE]={0};

if (specificCode(kSharedUserDataFolderType,(char *) &buffer,sizeof(buffer)-1))
{
temp_Str.assign((char *) &buffer);
}
#elif LINUX
char *ptr;

ptr=xdg_user_dir_lookup("PUBLICSHARE");
IF (ptr)
{
temp_Str.assign(ptr);
}
#endif
ENDINLINE

RETURN temp$
ENDFUNCTION

Kitty Hello


MrTAToad

It was a nightmare getting the API parameters correct :)  But I did it!  :good: