4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
29 * various string, file, list operations.
32 /** \file blender/blenlib/intern/path_util.c
42 #include "MEM_guardedalloc.h"
44 #include "DNA_userdef_types.h"
46 #include "BLI_fileops.h"
47 #include "BLI_path_util.h"
48 #include "BLI_string.h"
49 #include "BLI_storage.h"
50 #include "BLI_storage_types.h"
51 #include "BLI_utildefines.h"
53 #include "BKE_utildefines.h"
54 #include "BKE_blender.h" // BLENDER_VERSION
56 #include "GHOST_Path-api.h"
58 #if defined WIN32 && !defined _LIBC
59 # include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
73 #define _WIN32_IE 0x0501
77 #include "BLI_winstuff.h"
79 #else /* non windows */
88 #define UNIQUE_NAME_MAX 128
90 extern char bprogname[];
92 static int add_win32_extension(char *name);
93 static char *blender_version_decimal(const int ver);
97 int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
99 unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0;
101 char *lslash = BLI_last_slash(string);
102 len2 = len = strlen(string);
104 lenlslash= (int)(lslash - string);
106 while(len > lenlslash && string[--len] != '.') {};
107 if(len == lenlslash && string[len] != '.') len = len2;
109 for (i = len - 1; i >= lenlslash; i--) {
110 if (isdigit(string[i])) {
125 if (tail) strcpy(tail, &string[nume+1]);
130 if (numlen) *numlen = nume-nums+1;
131 return ((int)atoi(&(string[nums])));
133 if (tail) strcpy(tail, string + len);
135 strncpy(head, string, len);
138 if (numlen) *numlen=0;
143 void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
147 sprintf(fmtstr, "%%s%%.%dd%%s", numlen);
148 sprintf(string, fmtstr, head, pic, tail);
151 /* Foo.001 -> "Foo", 1
152 * Returns the length of "Foo" */
153 int BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
159 memcpy(left, name, (a + 1) * sizeof(char));
161 if(a>1 && name[a-1]==delim) return a;
164 if( name[a]==delim ) {
167 /* casting down to an int, can overflow for large numbers */
172 if( isdigit(name[a])==0 ) break;
177 for(a= 0; name[a]; a++)
183 void BLI_newname(char *name, int add)
185 char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX];
187 unsigned short digits;
189 pic = BLI_stringdec(name, head, tail, &digits);
191 /* are we going from 100 -> 99 or from 10 -> 9 */
192 if (add < 0 && digits < 4 && digits > 0) {
195 for (i = digits; i > 1; i--) exp *= 10;
196 if (pic >= exp && (pic + add) < exp) digits--;
201 if (digits==4 && pic<0) pic= 0;
202 BLI_stringenc(name, head, tail, digits, pic);
207 int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len)
209 if(name[0] == '\0') {
210 BLI_strncpy(name, defname, name_len);
213 if(unique_check(arg, name)) {
214 char tempname[UNIQUE_NAME_MAX];
215 char left[UNIQUE_NAME_MAX];
217 int len= BLI_split_name_num(left, &number, name, delim);
219 int newlen= BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, ++number);
220 if(newlen >= name_len) {
221 len -= ((newlen + 1) - name_len);
222 if(len < 0) len= number= 0;
225 } while(unique_check(arg, tempname));
227 BLI_strncpy(name, tempname, name_len);
235 /* little helper macro for BLI_uniquename */
237 #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset )
240 /* Generic function to set a unique name. It is only designed to be used in situations
241 * where the name is part of the struct, and also that the name is at most UNIQUE_NAME_MAX chars long.
243 * For places where this is used, see constraint.c for example...
245 * name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
246 * len: maximum length of string (to prevent overflows, etc.)
247 * defname: the name that should be used by default if none is specified already
248 * delim: the character which acts as a delimeter between parts of the name
250 static int uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs)
254 for (link = list->first; link; link= link->next) {
256 if (!strcmp(GIVE_STRADDR(link, name_offs), name)) {
265 static int uniquename_unique_check(void *arg, const char *name)
267 struct {ListBase *lb; void *vlink; short name_offs;} *data= arg;
268 return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
271 void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short name_len)
273 struct {ListBase *lb; void *vlink; short name_offs;} data;
276 data.name_offs= name_offs;
278 assert((name_len > 1) && (name_len <= UNIQUE_NAME_MAX));
280 /* See if we are given an empty string */
281 if (ELEM(NULL, vlink, defname))
284 BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
289 /* ******************** string encoding ***************** */
291 /* This is quite an ugly function... its purpose is to
292 * take the dir name, make it absolute, and clean it up, replacing
293 * excess file entry stuff (like /tmp/../tmp/../)
294 * note that dir isn't protected for max string names...
296 * If relbase is NULL then its ignored
299 void BLI_cleanup_path(const char *relabase, char *dir)
304 BLI_path_abs(dir, relabase);
306 if (dir[0]=='/' && dir[1]=='/') {
308 return; /* path is "//" - cant clean it */
310 dir = dir+2; /* skip the first // */
315 * memmove( start, eind, strlen(eind)+1 );
317 * strcpy( start, eind );
318 * except strcpy should not be used because there is overlap,
319 * so use memmove's slightly more obscure syntax - Campbell
324 /* Note, this should really be moved to the file selector,
325 * since this function is used in many areas */
326 if(strcmp(dir, ".")==0) { /* happens for example in FILE_MAIN */
327 get_default_root(dir);
331 while ( (start = strstr(dir, "\\..\\")) ) {
332 eind = start + strlen("\\..\\") - 1;
335 if (dir[a] == '\\') break;
341 memmove( dir+a, eind, strlen(eind)+1 );
345 while ( (start = strstr(dir,"\\.\\")) ){
346 eind = start + strlen("\\.\\") - 1;
347 memmove( start, eind, strlen(eind)+1 );
350 while ( (start = strstr(dir,"\\\\" )) ){
351 eind = start + strlen("\\\\") - 1;
352 memmove( start, eind, strlen(eind)+1 );
355 if(dir[0]=='.') { /* happens, for example in FILE_MAIN */
361 /* support for odd paths: eg /../home/me --> /home/me
362 * this is a valid path in blender but we cant handle this the useual way below
363 * simply strip this prefix then evaluate the path as useual. pythons os.path.normpath() does this */
364 while((strncmp(dir, "/../", 4)==0)) {
365 memmove( dir, dir + 4, strlen(dir + 4) + 1 );
368 while ( (start = strstr(dir, "/../")) ) {
369 eind = start + (4 - 1) /* strlen("/../") - 1 */;
372 if (dir[a] == '/') break;
378 memmove( dir+a, eind, strlen(eind)+1 );
382 while ( (start = strstr(dir,"/./")) ){
383 eind = start + (3 - 1) /* strlen("/./") - 1 */;
384 memmove( start, eind, strlen(eind)+1 );
387 while ( (start = strstr(dir,"//" )) ){
388 eind = start + (2 - 1) /* strlen("//") - 1 */;
389 memmove( start, eind, strlen(eind)+1 );
394 void BLI_cleanup_dir(const char *relabase, char *dir)
396 BLI_cleanup_path(relabase, dir);
401 void BLI_cleanup_file(const char *relabase, char *dir)
403 BLI_cleanup_path(relabase, dir);
407 void BLI_path_rel(char *file, const char *relfile)
410 char temp[FILE_MAXDIR+FILE_MAXFILE];
411 char res[FILE_MAXDIR+FILE_MAXFILE];
413 /* if file is already relative, bail out */
414 if(file[0]=='/' && file[1]=='/') return;
416 /* also bail out if relative path is not set */
417 if (relfile[0] == 0) return;
420 if (BLI_strnlen(relfile, 3) > 2 && relfile[1] != ':') {
422 /* fix missing volume name in relative base,
423 can happen with old recent-files.txt files */
424 get_default_root(temp);
426 if (relfile[0] != '\\' && relfile[0] != '/') {
429 BLI_strncpy(ptemp, relfile, FILE_MAXDIR + FILE_MAXFILE-3);
431 BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE);
434 if (BLI_strnlen(file, 3) > 2) {
435 if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] )
439 BLI_strncpy(temp, relfile, FILE_MAX);
442 BLI_char_switch(temp, '\\', '/');
443 BLI_char_switch(file, '\\', '/');
445 /* remove /./ which confuse the following slash counting... */
446 BLI_cleanup_path(NULL, file);
447 BLI_cleanup_path(NULL, temp);
449 /* the last slash in the file indicates where the path part ends */
450 lslash = BLI_last_slash(temp);
454 /* find the prefix of the filename that is equal for both filenames.
455 This is replaced by the two slashes at the beginning */
460 while (tolower(*p) == tolower(*q))
466 /* dont search beyond the end of the string
467 * in the rare case they match */
468 if ((*p=='\0') || (*q=='\0')) {
473 /* we might have passed the slash when the beginning of a dir matches
474 so we rewind. Only check on the actual filename
477 while ( (q >= file) && (*q != '/') ) { --q; --p; }
479 else if (*p != '/') {
480 while ( (p >= temp) && (*p != '/') ) { --p; --q; }
485 /* p now points to the slash that is at the beginning of the part
486 where the path is different from the relative path.
487 We count the number of directories we need to go up in the
488 hierarchy to arrive at the common 'prefix' of the path
490 while (p && p < lslash) {
496 strcat(res, q+1); /* don't copy the slash at the beginning */
499 BLI_char_switch(res+2, '/', '\\');
505 int BLI_has_parent(char *path)
510 len = BLI_add_slash(path) - 1;
513 if ((path[len] == '\\') || (path[len] == '/'))
520 int BLI_parent_dir(char *path)
522 static char parent_dir[]= {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
523 char tmp[FILE_MAXDIR+FILE_MAXFILE+4];
524 BLI_strncpy(tmp, path, sizeof(tmp)-4);
526 strcat(tmp, parent_dir);
527 BLI_cleanup_dir(NULL, tmp);
529 if (!BLI_testextensie(tmp, parent_dir)) {
530 BLI_strncpy(path, tmp, sizeof(tmp));
537 static int stringframe_chars(char *path, int *char_start, int *char_end)
539 int ch_sta, ch_end, i;
540 /* Insert current frame: file### -> file001 */
542 for (i = 0; path[i] != '\0'; i++) {
543 if (path[i] == '\\' || path[i] == '/') {
544 ch_end = 0; /* this is a directory name, dont use any hashes we found */
545 } else if (path[i] == '#') {
548 while (path[ch_end] == '#') {
551 i = ch_end-1; /* keep searching */
553 /* dont break, there may be a slash after this that invalidates the previous #'s */
569 static void ensure_digits(char *path, int digits)
571 char *file= BLI_last_slash(path);
576 if(strrchr(file, '#') == NULL) {
577 int len= strlen(file);
586 int BLI_path_frame(char *path, int frame, int digits)
591 ensure_digits(path, digits);
593 if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
595 sprintf(tmp, "%.*s%.*d%s", ch_sta, path, ch_end-ch_sta, frame, path+ch_end);
602 int BLI_path_frame_range(char *path, int sta, int end, int digits)
607 ensure_digits(path, digits);
609 if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
611 sprintf(tmp, "%.*s%.*d-%.*d%s", ch_sta, path, ch_end-ch_sta, sta, ch_end-ch_sta, end, path+ch_end);
618 int BLI_path_abs(char *path, const char *basepath)
620 int wasrelative = (strncmp(path, "//", 2)==0);
624 char vol[3] = {'\0', '\0', '\0'};
626 BLI_strncpy(vol, path, 3);
627 /* we are checking here if we have an absolute path that is not in the current
628 blend file as a lib main - we are basically checking for the case that a
629 UNIX root '/' is passed.
631 if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
633 get_default_root(tmp);
634 // get rid of the slashes at the beginning of the path
635 while (*p == '\\' || *p == '/') {
641 BLI_strncpy(tmp, path, FILE_MAX);
644 BLI_strncpy(tmp, path, sizeof(tmp));
646 /* Check for loading a windows path on a posix system
647 * in this case, there is no use in trying C:/ since it
648 * will never exist on a unix os.
650 * Add a / prefix and lowercase the driveletter, remove the :
651 * C:\foo.JPG -> /c/foo.JPG */
653 if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) {
654 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
656 /* '\' the slash will be converted later */
661 BLI_strncpy(base, basepath, sizeof(base));
663 /* file component is ignored, so dont bother with the trailing slash */
664 BLI_cleanup_path(NULL, base);
666 /* push slashes into unix mode - strings entering this part are
667 potentially messed up: having both back- and forward slashes.
668 Here we push into one conform direction, and at the end we
669 push them into the system specific dir. This ensures uniformity
670 of paths and solving some problems (and prevent potential future
671 ones) -jesterKing. */
672 BLI_char_switch(tmp, '\\', '/');
673 BLI_char_switch(base, '\\', '/');
675 /* Paths starting with // will get the blend file as their base,
676 * this isnt standard in any os but is uesed in blender all over the place */
678 char *lslash= BLI_last_slash(base);
680 int baselen= (int) (lslash-base) + 1;
681 /* use path for temp storage here, we copy back over it right away */
682 BLI_strncpy(path, tmp+2, FILE_MAX);
684 memcpy(tmp, base, baselen);
685 BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen);
686 BLI_strncpy(path, tmp, FILE_MAX);
688 BLI_strncpy(path, tmp+2, FILE_MAX);
691 BLI_strncpy(path, tmp, FILE_MAX);
694 BLI_cleanup_path(NULL, path);
697 /* skip first two chars, which in case of
698 absolute path will be drive:/blabla and
699 in case of relpath //blabla/. So relpath
700 // will be retained, rest will be nice and
701 shiny win32 backward slashes :) -jesterKing
703 BLI_char_switch(path+2, '/', '\\');
711 * Should only be done with command line paths.
712 * this is NOT somthing blenders internal paths support like the // prefix
714 int BLI_path_cwd(char *path)
717 int filelen = strlen(path);
720 if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
723 if (filelen >= 2 && path[0] == '/')
727 if (wasrelative==1) {
728 char cwd[FILE_MAXDIR + FILE_MAXFILE]= "";
729 BLI_getwdN(cwd, sizeof(cwd)); /* incase the full path to the blend isnt used */
731 if (cwd[0] == '\0') {
732 printf( "Could not get the current working directory - $PWD for an unknown reason.");
734 /* uses the blend path relative to cwd important for loading relative linked files.
736 * cwd should contain c:\ etc on win32 so the relbase can be NULL
737 * relbase being NULL also prevents // being misunderstood as relative to the current
738 * blend file which isnt a feature we want to use in this case since were dealing
739 * with a path from the command line, rather than from inside Blender */
741 char origpath[FILE_MAXDIR + FILE_MAXFILE];
742 BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE);
744 BLI_make_file_string(NULL, path, cwd, origpath);
752 /* 'di's filename component is moved into 'fi', di is made a dir path */
753 void BLI_splitdirstring(char *di, char *fi)
755 char *lslash= BLI_last_slash(di);
758 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
761 BLI_strncpy(fi, di, FILE_MAXFILE);
766 void BLI_getlastdir(const char* dir, char *last, const size_t maxlen)
769 const char *lslash = NULL;
770 const char *prevslash = NULL;
772 if ((*s == '\\') || (*s == '/')) {
779 BLI_strncpy(last, prevslash+1, maxlen);
781 BLI_strncpy(last, dir, maxlen);
785 /* This is now only used to really get the user's default document folder */
786 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
787 as default location to save documents */
788 const char *BLI_getDefaultDocumentFolder(void)
791 return getenv("HOME");
795 static char documentfolder[MAXPATHLEN];
798 /* Check for %HOME% env var */
800 ret = getenv("HOME");
802 if (BLI_is_dir(ret)) return ret;
805 /* add user profile support for WIN 2K / NT.
806 * This is %APPDATA%, which translates to either
807 * %USERPROFILE%\Application Data or since Vista
808 * to %USERPROFILE%\AppData\Roaming
810 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
814 if (BLI_is_dir(documentfolder)) return documentfolder;
821 /* NEW stuff, to be cleaned up when fully migrated */
822 /* ************************************************************* */
823 /* ************************************************************* */
825 // #define PATH_DEBUG2
827 static char *blender_version_decimal(const int ver)
829 static char version_str[5];
830 sprintf(version_str, "%d.%02d", ver/100, ver%100);
834 static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
836 char tmppath[FILE_MAX];
838 if(path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
839 else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
841 /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
843 BLI_make_file_string("/", targetpath, tmppath, folder_name);
845 BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
847 if (BLI_is_dir(targetpath)) {
849 printf("\tpath found: %s\n", targetpath);
855 printf("\tpath missing: %s\n", targetpath);
857 //targetpath[0] = '\0';
862 static int test_env_path(char *path, const char *envvar)
864 const char *env = envvar?getenv(envvar):NULL;
867 if (BLI_is_dir(env)) {
868 BLI_strncpy(path, env, FILE_MAX);
876 static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
878 char bprogdir[FILE_MAX];
879 char relfolder[FILE_MAX];
882 printf("get_path_local...\n");
886 if (subfolder_name) {
887 BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
889 BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
896 /* use argv[0] (bprogname) to get the path to the executable */
897 BLI_split_dirfile(bprogname, bprogdir, NULL);
899 /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
900 if(test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder))
906 static int is_portable_install(void)
908 /* detect portable install by the existance of config folder */
909 const int ver= BLENDER_VERSION;
912 return get_path_local(path, "config", NULL, ver);
915 static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
917 char user_path[FILE_MAX];
918 const char *user_base_path;
920 /* for portable install, user path is always local */
921 if (is_portable_install())
922 return get_path_local(targetpath, folder_name, subfolder_name, ver);
926 if (test_env_path(user_path, envvar)) {
927 if (subfolder_name) {
928 return test_path(targetpath, user_path, NULL, subfolder_name);
930 BLI_strncpy(targetpath, user_path, FILE_MAX);
935 user_base_path = (const char *)GHOST_getUserDir();
936 if (user_base_path) {
937 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal(ver));
944 printf("get_path_user: %s\n", user_path);
947 if (subfolder_name) {
948 /* try $HOME/folder_name/subfolder_name */
949 return test_path(targetpath, user_path, folder_name, subfolder_name);
951 /* try $HOME/folder_name */
952 return test_path(targetpath, user_path, NULL, folder_name);
956 static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
958 char system_path[FILE_MAX];
959 const char *system_base_path;
962 /* first allow developer only overrides to the system path
963 * these are only used when running blender from source */
965 char relfolder[FILE_MAX];
966 char bprogdir[FILE_MAX];
968 /* use argv[0] (bprogname) to get the path to the executable */
969 BLI_split_dirfile(bprogname, bprogdir, NULL);
972 if (subfolder_name) {
973 BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
975 BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
982 /* try CWD/release/folder_name */
983 if(BLI_getwdN(cwd, sizeof(cwd))) {
984 if(test_path(targetpath, cwd, "release", relfolder)) {
989 /* try EXECUTABLE_DIR/release/folder_name */
990 if(test_path(targetpath, bprogdir, "release", relfolder))
992 /* end developer overrides */
996 system_path[0] = '\0';
998 if (test_env_path(system_path, envvar)) {
999 if (subfolder_name) {
1000 return test_path(targetpath, system_path, NULL, subfolder_name);
1002 BLI_strncpy(targetpath, system_path, FILE_MAX);
1007 system_base_path = (const char *)GHOST_getSystemDir();
1008 if (system_base_path) {
1009 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal(ver));
1016 printf("get_path_system: %s\n", system_path);
1019 if (subfolder_name) {
1020 /* try $BLENDERPATH/folder_name/subfolder_name */
1021 return test_path(targetpath, system_path, folder_name, subfolder_name);
1023 /* try $BLENDERPATH/folder_name */
1024 return test_path(targetpath, system_path, NULL, folder_name);
1028 /* get a folder out of the 'folder_id' presets for paths */
1029 /* returns the path if found, NULL string if not */
1030 char *BLI_get_folder(int folder_id, const char *subfolder)
1032 const int ver= BLENDER_VERSION;
1033 static char path[FILE_MAX] = "";
1035 switch (folder_id) {
1036 case BLENDER_DATAFILES: /* general case */
1037 if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1038 if (get_path_local(path, "datafiles", subfolder, ver)) break;
1039 if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
1042 case BLENDER_USER_DATAFILES:
1043 if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1046 case BLENDER_SYSTEM_DATAFILES:
1047 if (get_path_local(path, "datafiles", subfolder, ver)) break;
1048 if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
1051 case BLENDER_USER_AUTOSAVE:
1052 if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1055 case BLENDER_USER_CONFIG:
1056 if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
1059 case BLENDER_USER_SCRIPTS:
1060 if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
1063 case BLENDER_SYSTEM_SCRIPTS:
1064 if (get_path_local(path, "scripts", subfolder, ver)) break;
1065 if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
1068 case BLENDER_SYSTEM_PYTHON:
1069 if (get_path_local(path, "python", subfolder, ver)) break;
1070 if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
1077 char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
1079 const int ver= BLENDER_VERSION;
1080 static char path[FILE_MAX] = "";
1082 switch (folder_id) {
1083 case BLENDER_USER_DATAFILES:
1084 get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
1086 case BLENDER_USER_CONFIG:
1087 get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
1089 case BLENDER_USER_AUTOSAVE:
1090 get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
1092 case BLENDER_USER_SCRIPTS:
1093 get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
1096 if ('\0' == path[0]) {
1102 char *BLI_get_folder_create(int folder_id, const char *subfolder)
1106 /* only for user folders */
1107 if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1110 path = BLI_get_folder(folder_id, subfolder);
1113 path = BLI_get_user_folder_notest(folder_id, subfolder);
1114 if (path) BLI_recurdir_fileops(path);
1120 char *BLI_get_folder_version(const int id, const int ver, const int do_check)
1122 static char path[FILE_MAX] = "";
1125 case BLENDER_RESOURCE_PATH_USER:
1126 ok= get_path_user(path, NULL, NULL, NULL, ver);
1128 case BLENDER_RESOURCE_PATH_LOCAL:
1129 ok= get_path_local(path, NULL, NULL, ver);
1131 case BLENDER_RESOURCE_PATH_SYSTEM:
1132 ok= get_path_system(path, NULL, NULL, NULL, ver);
1135 path[0]= '\0'; /* incase do_check is false */
1137 BLI_assert(!"incorrect ID");
1140 if((ok == FALSE) && do_check) {
1148 /* ************************************************************* */
1149 /* ************************************************************* */
1157 void BLI_setenv(const char *env, const char*val)
1160 #if (defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)
1161 char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1163 sprintf(envstr, "%s=%s", env, val);
1167 /* non-free windows */
1168 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1169 _putenv_s(env, val);
1172 setenv(env, val, 1);
1178 Only set an env var if already not there.
1179 Like Unix setenv(env, val, 0);
1181 void BLI_setenv_if_new(const char *env, const char* val)
1183 if(getenv(env) == NULL)
1184 BLI_setenv(env, val);
1188 void BLI_clean(char *path)
1190 if(path==NULL) return;
1193 if(path && BLI_strnlen(path, 3) > 2) {
1194 BLI_char_switch(path+2, '/', '\\');
1197 BLI_char_switch(path, '\\', '/');
1201 void BLI_char_switch(char *string, char from, char to)
1203 if(string==NULL) return;
1204 while (*string != 0) {
1205 if (*string == from) *string = to;
1210 void BLI_make_exist(char *dir)
1214 BLI_char_switch(dir, ALTSEP, SEP);
1218 while(BLI_is_dir(dir) == 0){
1220 while(dir[a] != SEP){
1229 get_default_root(dir);
1238 void BLI_make_existing_file(const char *name)
1240 char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1242 BLI_strncpy(di, name, sizeof(di));
1243 BLI_splitdirstring(di, fi);
1246 if (BLI_exists(di) == 0) {
1247 BLI_recurdir_fileops(di);
1252 void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file)
1256 if (!string || !dir || !file) return; /* We don't want any NULLs */
1258 string[0]= 0; /* ton */
1260 /* we first push all slashes into unix mode, just to make sure we don't get
1261 any mess with slashes later on. -jesterKing */
1262 /* constant strings can be passed for those parameters - don't change them - elubie */
1264 BLI_char_switch(relabase, '\\', '/');
1265 BLI_char_switch(dir, '\\', '/');
1266 BLI_char_switch(file, '\\', '/');
1269 /* Resolve relative references */
1270 if (relabase && dir[0] == '/' && dir[1] == '/') {
1273 /* Get the file name, chop everything past the last slash (ie. the filename) */
1274 strcpy(string, relabase);
1276 lslash= BLI_last_slash(string);
1277 if(lslash) *(lslash+1)= 0;
1279 dir+=2; /* Skip over the relative reference */
1283 if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':' ) {
1284 BLI_strncpy(string, dir, 3);
1287 else { /* no drive specified */
1288 /* first option: get the drive from the relabase if it has one */
1289 if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1290 BLI_strncpy(string, relabase, 3);
1294 else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1295 get_default_root(string);
1298 /* ignore leading slashes */
1299 while (*dir == '/' || *dir == '\\') dir++;
1304 strcat(string, dir);
1306 /* Make sure string ends in one (and only one) slash */
1307 /* first trim all slashes from the end of the string */
1308 sl = strlen(string);
1309 while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1310 string[sl-1] = '\0';
1313 /* since we've now removed all slashes, put back one slash at the end. */
1314 strcat(string, "/");
1316 while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1319 strcat (string, file);
1321 /* Push all slashes to the system preferred direction */
1325 int BLI_testextensie(const char *str, const char *ext)
1333 if(a==0 || b==0 || b>=a) {
1335 } else if (BLI_strcasecmp(ext, str + a - b)) {
1344 int BLI_testextensie_array(const char *str, const char **ext_array)
1347 while(ext_array[i]) {
1348 if(BLI_testextensie(str, ext_array[i])) {
1357 /* semicolon separated wildcards, eg:
1358 * '*.zip;*.py;*.exe' */
1359 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1361 const char *ext_step= ext_fnmatch;
1364 while(ext_step[0]) {
1368 if((ext_next=strchr(ext_step, ';'))) {
1369 len_ext= (int)(ext_next - ext_step) + 1;
1372 len_ext= sizeof(pattern);
1375 BLI_strncpy(pattern, ext_step, len_ext);
1377 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1380 ext_step += len_ext;
1387 int BLI_replace_extension(char *path, size_t maxlen, const char *ext)
1391 for(a=strlen(path); a>0; a--) {
1392 if(path[a-1] == '.' || path[a-1] == '/' || path[a-1] == '\\') {
1401 if(a + strlen(ext) >= maxlen)
1404 strcpy(path+a, ext);
1408 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1409 * - wont change 'string'
1410 * - wont create any directories
1411 * - dosnt use CWD, or deal with relative paths.
1412 * - Only fill's in *dir and *file when they are non NULL
1414 void BLI_split_dirfile(const char *string, char *dir, char *file)
1416 char *lslash_str = BLI_last_slash(string);
1417 int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0;
1421 BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */
1428 strcpy( file, string+lslash);
1432 /* simple appending of filename to dir, does not check for valid path! */
1433 void BLI_join_dirfile(char *string, const size_t maxlen, const char *dir, const char *file)
1437 if(string != dir) /* compare pointers */
1438 BLI_strncpy(string, dir, maxlen -(file ? 1 : 0));
1443 sl_dir= BLI_add_slash(string);
1445 if (sl_dir < maxlen) {
1446 BLI_strncpy(string + sl_dir, file, maxlen - sl_dir);
1450 /* like pythons os.path.basename( ) */
1451 char *BLI_path_basename(char *path)
1453 char *filename= BLI_last_slash(path);
1454 return filename ? filename + 1 : path;
1458 Produce image export path.
1460 Fails returning 0 if image filename is empty or if destination path
1461 matches image path (i.e. both are the same file).
1463 Trailing slash in dest_dir is optional.
1467 - if an image is "below" current .blend file directory, rebuild the
1468 same dir structure in dest_dir
1470 For example //textures/foo/bar.png becomes
1471 [dest_dir]/textures/foo/bar.png.
1473 - if an image is not "below" current .blend file directory,
1474 disregard it's path and copy it in the same directory where 3D file
1477 For example //../foo/bar.png becomes [dest_dir]/bar.png.
1479 This logic will help ensure that all image paths are relative and
1480 that a user gets his images in one place. It'll also provide
1481 consistent behaviour across exporters.
1483 int BKE_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const char *base_dir, const char *src_dir, const char *dest_dir)
1485 char path[FILE_MAX];
1487 char base[FILE_MAX];
1488 char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */
1489 char dest_path[FILE_MAX];
1490 char rel_dir[FILE_MAX];
1499 BLI_split_dirfile(base_dir, blend_dir, NULL);
1501 if (src_dir[0]=='\0')
1504 BLI_strncpy(path, src_dir, sizeof(path));
1506 /* expand "//" in filename and get absolute path */
1507 BLI_path_abs(path, base_dir);
1509 /* get the directory part */
1510 BLI_split_dirfile(path, dir, base);
1512 len= strlen(blend_dir);
1516 /* if image is "below" current .blend file directory */
1517 if (!strncmp(path, blend_dir, len)) {
1519 /* if image is _in_ current .blend file directory */
1520 if (BLI_path_cmp(dir, blend_dir) == 0) {
1521 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1525 /* rel = image_path_dir - blend_dir */
1526 BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1528 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir);
1529 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base);
1533 /* image is out of current directory */
1535 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1539 BLI_strncpy(abs, dest_path, abs_len);
1542 strncat(rel, rel_dir, rel_len);
1543 strncat(rel, base, rel_len);
1546 /* return 2 if src=dest */
1547 if (BLI_path_cmp(path, dest_path) == 0) {
1548 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1555 char *BLI_first_slash(char *string)
1557 char *ffslash, *fbslash;
1559 ffslash= strchr(string, '/');
1560 fbslash= strchr(string, '\\');
1562 if (!ffslash) return fbslash;
1563 else if (!fbslash) return ffslash;
1565 if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1566 else return fbslash;
1569 char *BLI_last_slash(const char *string)
1571 char *lfslash, *lbslash;
1573 lfslash= strrchr(string, '/');
1574 lbslash= strrchr(string, '\\');
1576 if (!lfslash) return lbslash;
1577 else if (!lbslash) return lfslash;
1579 if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1580 else return lfslash;
1583 /* adds a slash if there isnt one there already */
1584 int BLI_add_slash(char *string)
1586 int len = strlen(string);
1587 if (len==0 || string[len-1] != SEP) {
1589 string[len+1] = '\0';
1595 /* removes a slash if there is one */
1596 void BLI_del_slash(char *string)
1598 int len = strlen(string);
1600 if (string[len-1] == SEP) {
1601 string[len-1] = '\0';
1609 static int add_win32_extension(char *name)
1614 type = BLI_exist(name);
1615 if ((type == 0) || S_ISDIR(type)) {
1617 char filename[FILE_MAXDIR+FILE_MAXFILE];
1618 char ext[FILE_MAXDIR+FILE_MAXFILE];
1619 const char *extensions = getenv("PATHEXT");
1623 strcpy(filename, name);
1624 temp = strstr(extensions, ";");
1626 strncpy(ext, extensions, temp - extensions);
1627 ext[temp - extensions] = 0;
1628 extensions = temp + 1;
1629 strcat(filename, ext);
1631 strcat(filename, extensions);
1634 type = BLI_exist(filename);
1635 if (type && (! S_ISDIR(type))) {
1637 strcpy(name, filename);
1650 /* filename must be FILE_MAX length minimum */
1651 void BLI_where_am_i(char *fullname, const size_t maxlen, const char *name)
1653 char filename[FILE_MAXDIR+FILE_MAXFILE];
1654 const char *path = NULL, *temp;
1657 const char *separator = ";";
1659 const char *separator = ":";
1663 #ifdef WITH_BINRELOC
1664 /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1665 path = br_find_exe( NULL );
1667 BLI_strncpy(fullname, path, maxlen);
1674 if(GetModuleFileName(0, fullname, maxlen)) {
1675 if(!BLI_exists(fullname)) {
1676 printf("path can't be found: \"%.*s\"\n", maxlen, fullname);
1677 MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
1683 /* unix and non linux */
1684 if (name && name[0]) {
1685 BLI_strncpy(fullname, name, maxlen);
1686 if (name[0] == '.') {
1687 char wdir[FILE_MAX]= "";
1688 BLI_getwdN(wdir, sizeof(wdir)); /* backup cwd to restore after */
1690 // not needed but avoids annoying /./ in name
1692 BLI_join_dirfile(fullname, maxlen, wdir, name+2);
1694 BLI_join_dirfile(fullname, maxlen, wdir, name);
1696 add_win32_extension(fullname); /* XXX, doesnt respect length */
1698 else if (BLI_last_slash(name)) {
1700 BLI_strncpy(fullname, name, maxlen);
1701 add_win32_extension(fullname);
1703 // search for binary in $PATH
1704 path = getenv("PATH");
1707 temp = strstr(path, separator);
1709 strncpy(filename, path, temp - path);
1710 filename[temp - path] = 0;
1713 strncpy(filename, path, sizeof(filename));
1715 BLI_join_dirfile(fullname, maxlen, fullname, name);
1716 if (add_win32_extension(filename)) {
1717 BLI_strncpy(fullname, filename, maxlen);
1724 if (strcmp(name, fullname)) {
1725 printf("guessing '%s' == '%s'\n", name, fullname);
1731 void BLI_where_is_temp(char *fullname, const size_t maxlen, int usertemp)
1735 if (usertemp && BLI_is_dir(U.tempdir)) {
1736 BLI_strncpy(fullname, U.tempdir, maxlen);
1741 if (fullname[0] == '\0') {
1742 const char *tmp = getenv("TEMP"); /* Windows */
1743 if (tmp && BLI_is_dir(tmp)) {
1744 BLI_strncpy(fullname, tmp, maxlen);
1748 /* Other OS's - Try TMP and TMPDIR */
1749 if (fullname[0] == '\0') {
1750 const char *tmp = getenv("TMP");
1751 if (tmp && BLI_is_dir(tmp)) {
1752 BLI_strncpy(fullname, tmp, maxlen);
1756 if (fullname[0] == '\0') {
1757 const char *tmp = getenv("TMPDIR");
1758 if (tmp && BLI_is_dir(tmp)) {
1759 BLI_strncpy(fullname, tmp, maxlen);
1764 if (fullname[0] == '\0') {
1765 BLI_strncpy(fullname, "/tmp/", maxlen);
1767 /* add a trailing slash if needed */
1768 BLI_add_slash(fullname);
1770 if(U.tempdir != fullname) {
1771 BLI_strncpy(U.tempdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1779 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1781 size_t inbytesleft=strlen(original);
1782 size_t outbytesleft=512;
1787 code = locale_charset();
1789 cd=iconv_open("UTF-8", code);
1791 if (cd == (iconv_t)(-1)) {
1792 printf("iconv_open Error");
1796 rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1797 if (rv == (size_t) -1) {
1798 printf("iconv Error\n");
1804 #endif // WITH_ICONV