GLBasic forum

Codesnippets => Code Snippets => Topic started by: MrTAToad on 2009-Nov-27

Title: Convert ~/ to fully qualified path
Post by: MrTAToad on 2009-Nov-27
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
Title: Re: Convert ~/ to fully qualified path
Post by: bigsofty on 2009-Nov-27
Another nice snippet, many thanks!  ;)
Title: Re: Convert ~/ to fully qualified path
Post by: MrTAToad on 2009-Nov-28
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
Title: Re: Convert ~/ to fully qualified path
Post by: Kitty Hello on 2009-Nov-30
Excellent work. Will implement that instead of "~". Was a quick shot in the oven.
Title: Re: Convert ~/ to fully qualified path
Post by: MrTAToad on 2009-Nov-30
Great!  That'll be useful - especially if you can do the Music, Pictures and Shared Data areas too :)
Title: Re: Convert ~/ to fully qualified path
Post by: MrTAToad on 2009-Dec-08
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
Title: Re: Convert ~/ to fully qualified path
Post by: Kitty Hello on 2009-Dec-09
 :nw:
Title: Re: Convert ~/ to fully qualified path
Post by: MrTAToad on 2009-Dec-09
It was a nightmare getting the API parameters correct :)  But I did it!  :good: