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[];
91 extern char bprogdir[];
93 static int add_win32_extension(char *name);
94 static char *blender_version_decimal(const int ver);
98 int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
100 unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0;
102 char *lslash = BLI_last_slash(string);
103 len2 = len = strlen(string);
105 lenlslash= (int)(lslash - string);
107 while(len > lenlslash && string[--len] != '.') {};
108 if(len == lenlslash && string[len] != '.') len = len2;
110 for (i = len - 1; i >= lenlslash; i--) {
111 if (isdigit(string[i])) {
126 if (tail) strcpy(tail, &string[nume+1]);
131 if (numlen) *numlen = nume-nums+1;
132 return ((int)atoi(&(string[nums])));
134 if (tail) strcpy(tail, string + len);
136 strncpy(head, string, len);
139 if (numlen) *numlen=0;
144 void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
148 sprintf(fmtstr, "%%s%%.%dd%%s", numlen);
149 sprintf(string, fmtstr, head, pic, tail);
152 /* Foo.001 -> "Foo", 1
153 * Returns the length of "Foo" */
154 int BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
160 memcpy(left, name, (a + 1) * sizeof(char));
162 if(a>1 && name[a-1]==delim) return a;
165 if( name[a]==delim ) {
168 /* casting down to an int, can overflow for large numbers */
173 if( isdigit(name[a])==0 ) break;
178 for(a= 0; name[a]; a++)
184 void BLI_newname(char *name, int add)
186 char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX];
188 unsigned short digits;
190 pic = BLI_stringdec(name, head, tail, &digits);
192 /* are we going from 100 -> 99 or from 10 -> 9 */
193 if (add < 0 && digits < 4 && digits > 0) {
196 for (i = digits; i > 1; i--) exp *= 10;
197 if (pic >= exp && (pic + add) < exp) digits--;
202 if (digits==4 && pic<0) pic= 0;
203 BLI_stringenc(name, head, tail, digits, pic);
208 int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len)
210 if(name[0] == '\0') {
211 BLI_strncpy(name, defname, name_len);
214 if(unique_check(arg, name)) {
215 char tempname[UNIQUE_NAME_MAX];
216 char left[UNIQUE_NAME_MAX];
218 int len= BLI_split_name_num(left, &number, name, delim);
220 int newlen= BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, ++number);
221 if(newlen >= name_len) {
222 len -= ((newlen + 1) - name_len);
223 if(len < 0) len= number= 0;
226 } while(unique_check(arg, tempname));
228 BLI_strncpy(name, tempname, name_len);
236 /* little helper macro for BLI_uniquename */
238 #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset )
241 /* Generic function to set a unique name. It is only designed to be used in situations
242 * where the name is part of the struct, and also that the name is at most UNIQUE_NAME_MAX chars long.
244 * For places where this is used, see constraint.c for example...
246 * name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
247 * len: maximum length of string (to prevent overflows, etc.)
248 * defname: the name that should be used by default if none is specified already
249 * delim: the character which acts as a delimeter between parts of the name
251 static int uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs)
255 for (link = list->first; link; link= link->next) {
257 if (!strcmp(GIVE_STRADDR(link, name_offs), name)) {
266 static int uniquename_unique_check(void *arg, const char *name)
268 struct {ListBase *lb; void *vlink; short name_offs;} *data= arg;
269 return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
272 void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short name_len)
274 struct {ListBase *lb; void *vlink; short name_offs;} data;
277 data.name_offs= name_offs;
279 assert((name_len > 1) && (name_len <= UNIQUE_NAME_MAX));
281 /* See if we are given an empty string */
282 if (ELEM(NULL, vlink, defname))
285 BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
290 /* ******************** string encoding ***************** */
292 /* This is quite an ugly function... its purpose is to
293 * take the dir name, make it absolute, and clean it up, replacing
294 * excess file entry stuff (like /tmp/../tmp/../)
295 * note that dir isn't protected for max string names...
297 * If relbase is NULL then its ignored
300 void BLI_cleanup_path(const char *relabase, char *dir)
305 BLI_path_abs(dir, relabase);
307 if (dir[0]=='/' && dir[1]=='/') {
309 return; /* path is "//" - cant clean it */
311 dir = dir+2; /* skip the first // */
316 * memmove( start, eind, strlen(eind)+1 );
318 * strcpy( start, eind );
319 * except strcpy should not be used because there is overlap,
320 * so use memmove's slightly more obscure syntax - Campbell
325 /* Note, this should really be moved to the file selector,
326 * since this function is used in many areas */
327 if(strcmp(dir, ".")==0) { /* happens for example in FILE_MAIN */
328 get_default_root(dir);
332 while ( (start = strstr(dir, "\\..\\")) ) {
333 eind = start + strlen("\\..\\") - 1;
336 if (dir[a] == '\\') break;
342 memmove( dir+a, eind, strlen(eind)+1 );
346 while ( (start = strstr(dir,"\\.\\")) ){
347 eind = start + strlen("\\.\\") - 1;
348 memmove( start, eind, strlen(eind)+1 );
351 while ( (start = strstr(dir,"\\\\" )) ){
352 eind = start + strlen("\\\\") - 1;
353 memmove( start, eind, strlen(eind)+1 );
356 if(dir[0]=='.') { /* happens, for example in FILE_MAIN */
362 /* support for odd paths: eg /../home/me --> /home/me
363 * this is a valid path in blender but we cant handle this the useual way below
364 * simply strip this prefix then evaluate the path as useual. pythons os.path.normpath() does this */
365 while((strncmp(dir, "/../", 4)==0)) {
366 memmove( dir, dir + 4, strlen(dir + 4) + 1 );
369 while ( (start = strstr(dir, "/../")) ) {
370 eind = start + (4 - 1) /* strlen("/../") - 1 */;
373 if (dir[a] == '/') break;
379 memmove( dir+a, eind, strlen(eind)+1 );
383 while ( (start = strstr(dir,"/./")) ){
384 eind = start + (3 - 1) /* strlen("/./") - 1 */;
385 memmove( start, eind, strlen(eind)+1 );
388 while ( (start = strstr(dir,"//" )) ){
389 eind = start + (2 - 1) /* strlen("//") - 1 */;
390 memmove( start, eind, strlen(eind)+1 );
395 void BLI_cleanup_dir(const char *relabase, char *dir)
397 BLI_cleanup_path(relabase, dir);
402 void BLI_cleanup_file(const char *relabase, char *dir)
404 BLI_cleanup_path(relabase, dir);
408 void BLI_path_rel(char *file, const char *relfile)
411 char temp[FILE_MAXDIR+FILE_MAXFILE];
412 char res[FILE_MAXDIR+FILE_MAXFILE];
414 /* if file is already relative, bail out */
415 if(file[0]=='/' && file[1]=='/') return;
417 /* also bail out if relative path is not set */
418 if (relfile[0] == 0) return;
421 if (BLI_strnlen(relfile, 3) > 2 && relfile[1] != ':') {
423 /* fix missing volume name in relative base,
424 can happen with old recent-files.txt files */
425 get_default_root(temp);
427 if (relfile[0] != '\\' && relfile[0] != '/') {
430 BLI_strncpy(ptemp, relfile, FILE_MAXDIR + FILE_MAXFILE-3);
432 BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE);
435 if (BLI_strnlen(file, 3) > 2) {
436 if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] )
440 BLI_strncpy(temp, relfile, FILE_MAX);
443 BLI_char_switch(temp, '\\', '/');
444 BLI_char_switch(file, '\\', '/');
446 /* remove /./ which confuse the following slash counting... */
447 BLI_cleanup_path(NULL, file);
448 BLI_cleanup_path(NULL, temp);
450 /* the last slash in the file indicates where the path part ends */
451 lslash = BLI_last_slash(temp);
455 /* find the prefix of the filename that is equal for both filenames.
456 This is replaced by the two slashes at the beginning */
461 while (tolower(*p) == tolower(*q))
467 /* dont search beyond the end of the string
468 * in the rare case they match */
469 if ((*p=='\0') || (*q=='\0')) {
474 /* we might have passed the slash when the beginning of a dir matches
475 so we rewind. Only check on the actual filename
478 while ( (q >= file) && (*q != '/') ) { --q; --p; }
480 else if (*p != '/') {
481 while ( (p >= temp) && (*p != '/') ) { --p; --q; }
486 /* p now points to the slash that is at the beginning of the part
487 where the path is different from the relative path.
488 We count the number of directories we need to go up in the
489 hierarchy to arrive at the common 'prefix' of the path
491 while (p && p < lslash) {
497 strcat(res, q+1); /* don't copy the slash at the beginning */
500 BLI_char_switch(res+2, '/', '\\');
506 int BLI_has_parent(char *path)
511 len = BLI_add_slash(path) - 1;
514 if ((path[len] == '\\') || (path[len] == '/'))
521 int BLI_parent_dir(char *path)
523 static char parent_dir[]= {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
524 char tmp[FILE_MAXDIR+FILE_MAXFILE+4];
525 BLI_strncpy(tmp, path, sizeof(tmp)-4);
527 strcat(tmp, parent_dir);
528 BLI_cleanup_dir(NULL, tmp);
530 if (!BLI_testextensie(tmp, parent_dir)) {
531 BLI_strncpy(path, tmp, sizeof(tmp));
538 static int stringframe_chars(char *path, int *char_start, int *char_end)
540 int ch_sta, ch_end, i;
541 /* Insert current frame: file### -> file001 */
543 for (i = 0; path[i] != '\0'; i++) {
544 if (path[i] == '\\' || path[i] == '/') {
545 ch_end = 0; /* this is a directory name, dont use any hashes we found */
546 } else if (path[i] == '#') {
549 while (path[ch_end] == '#') {
552 i = ch_end-1; /* keep searching */
554 /* dont break, there may be a slash after this that invalidates the previous #'s */
570 static void ensure_digits(char *path, int digits)
572 char *file= BLI_last_slash(path);
577 if(strrchr(file, '#') == NULL) {
578 int len= strlen(file);
587 int BLI_path_frame(char *path, int frame, int digits)
592 ensure_digits(path, digits);
594 if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
596 sprintf(tmp, "%.*s%.*d%s", ch_sta, path, ch_end-ch_sta, frame, path+ch_end);
603 int BLI_path_frame_range(char *path, int sta, int end, int digits)
608 ensure_digits(path, digits);
610 if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
612 sprintf(tmp, "%.*s%.*d-%.*d%s", ch_sta, path, ch_end-ch_sta, sta, ch_end-ch_sta, end, path+ch_end);
619 int BLI_path_abs(char *path, const char *basepath)
621 int wasrelative = (strncmp(path, "//", 2)==0);
625 char vol[3] = {'\0', '\0', '\0'};
627 BLI_strncpy(vol, path, 3);
628 /* we are checking here if we have an absolute path that is not in the current
629 blend file as a lib main - we are basically checking for the case that a
630 UNIX root '/' is passed.
632 if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
634 get_default_root(tmp);
635 // get rid of the slashes at the beginning of the path
636 while (*p == '\\' || *p == '/') {
642 BLI_strncpy(tmp, path, FILE_MAX);
645 BLI_strncpy(tmp, path, sizeof(tmp));
647 /* Check for loading a windows path on a posix system
648 * in this case, there is no use in trying C:/ since it
649 * will never exist on a unix os.
651 * Add a / prefix and lowercase the driveletter, remove the :
652 * C:\foo.JPG -> /c/foo.JPG */
654 if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) {
655 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
657 /* '\' the slash will be converted later */
662 BLI_strncpy(base, basepath, sizeof(base));
664 /* file component is ignored, so dont bother with the trailing slash */
665 BLI_cleanup_path(NULL, base);
667 /* push slashes into unix mode - strings entering this part are
668 potentially messed up: having both back- and forward slashes.
669 Here we push into one conform direction, and at the end we
670 push them into the system specific dir. This ensures uniformity
671 of paths and solving some problems (and prevent potential future
672 ones) -jesterKing. */
673 BLI_char_switch(tmp, '\\', '/');
674 BLI_char_switch(base, '\\', '/');
676 /* Paths starting with // will get the blend file as their base,
677 * this isnt standard in any os but is uesed in blender all over the place */
679 char *lslash= BLI_last_slash(base);
681 int baselen= (int) (lslash-base) + 1;
682 /* use path for temp storage here, we copy back over it right away */
683 BLI_strncpy(path, tmp+2, FILE_MAX);
685 memcpy(tmp, base, baselen);
686 BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen);
687 BLI_strncpy(path, tmp, FILE_MAX);
689 BLI_strncpy(path, tmp+2, FILE_MAX);
692 BLI_strncpy(path, tmp, FILE_MAX);
695 BLI_cleanup_path(NULL, path);
698 /* skip first two chars, which in case of
699 absolute path will be drive:/blabla and
700 in case of relpath //blabla/. So relpath
701 // will be retained, rest will be nice and
702 shiny win32 backward slashes :) -jesterKing
704 BLI_char_switch(path+2, '/', '\\');
712 * Should only be done with command line paths.
713 * this is NOT somthing blenders internal paths support like the // prefix
715 int BLI_path_cwd(char *path)
718 int filelen = strlen(path);
721 if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
724 if (filelen >= 2 && path[0] == '/')
728 if (wasrelative==1) {
729 char cwd[FILE_MAXDIR + FILE_MAXFILE]= "";
730 BLI_getwdN(cwd, sizeof(cwd)); /* incase the full path to the blend isnt used */
732 if (cwd[0] == '\0') {
733 printf( "Could not get the current working directory - $PWD for an unknown reason.");
735 /* uses the blend path relative to cwd important for loading relative linked files.
737 * cwd should contain c:\ etc on win32 so the relbase can be NULL
738 * relbase being NULL also prevents // being misunderstood as relative to the current
739 * blend file which isnt a feature we want to use in this case since were dealing
740 * with a path from the command line, rather than from inside Blender */
742 char origpath[FILE_MAXDIR + FILE_MAXFILE];
743 BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE);
745 BLI_make_file_string(NULL, path, cwd, origpath);
753 /* 'di's filename component is moved into 'fi', di is made a dir path */
754 void BLI_splitdirstring(char *di, char *fi)
756 char *lslash= BLI_last_slash(di);
759 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
762 BLI_strncpy(fi, di, FILE_MAXFILE);
767 void BLI_getlastdir(const char* dir, char *last, const size_t maxlen)
770 const char *lslash = NULL;
771 const char *prevslash = NULL;
773 if ((*s == '\\') || (*s == '/')) {
780 BLI_strncpy(last, prevslash+1, maxlen);
782 BLI_strncpy(last, dir, maxlen);
786 /* This is now only used to really get the user's default document folder */
787 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
788 as default location to save documents */
789 const char *BLI_getDefaultDocumentFolder(void)
792 return getenv("HOME");
796 static char documentfolder[MAXPATHLEN];
799 /* Check for %HOME% env var */
801 ret = getenv("HOME");
803 if (BLI_is_dir(ret)) return ret;
806 /* add user profile support for WIN 2K / NT.
807 * This is %APPDATA%, which translates to either
808 * %USERPROFILE%\Application Data or since Vista
809 * to %USERPROFILE%\AppData\Roaming
811 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
815 if (BLI_is_dir(documentfolder)) return documentfolder;
822 /* NEW stuff, to be cleaned up when fully migrated */
823 /* ************************************************************* */
824 /* ************************************************************* */
826 // #define PATH_DEBUG2
828 static char *blender_version_decimal(const int ver)
830 static char version_str[5];
831 sprintf(version_str, "%d.%02d", ver/100, ver%100);
835 static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
837 char tmppath[FILE_MAX];
839 if(path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
840 else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
842 /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
844 BLI_make_file_string("/", targetpath, tmppath, folder_name);
846 BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
848 if (BLI_is_dir(targetpath)) {
850 printf("\tpath found: %s\n", targetpath);
856 printf("\tpath missing: %s\n", targetpath);
858 //targetpath[0] = '\0';
863 static int test_env_path(char *path, const char *envvar)
865 const char *env = envvar?getenv(envvar):NULL;
868 if (BLI_is_dir(env)) {
869 BLI_strncpy(path, env, FILE_MAX);
877 static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
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 /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
897 if(test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder))
903 static int is_portable_install(void)
905 /* detect portable install by the existance of config folder */
906 const int ver= BLENDER_VERSION;
909 return get_path_local(path, "config", NULL, ver);
912 static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
914 char user_path[FILE_MAX];
915 const char *user_base_path;
917 /* for portable install, user path is always local */
918 if (is_portable_install())
919 return get_path_local(targetpath, folder_name, subfolder_name, ver);
923 if (test_env_path(user_path, envvar)) {
924 if (subfolder_name) {
925 return test_path(targetpath, user_path, NULL, subfolder_name);
927 BLI_strncpy(targetpath, user_path, FILE_MAX);
932 user_base_path = (const char *)GHOST_getUserDir();
933 if (user_base_path) {
934 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal(ver));
941 printf("get_path_user: %s\n", user_path);
944 if (subfolder_name) {
945 /* try $HOME/folder_name/subfolder_name */
946 return test_path(targetpath, user_path, folder_name, subfolder_name);
948 /* try $HOME/folder_name */
949 return test_path(targetpath, user_path, NULL, folder_name);
953 static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
955 char system_path[FILE_MAX];
956 const char *system_base_path;
959 /* first allow developer only overrides to the system path
960 * these are only used when running blender from source */
962 char relfolder[FILE_MAX];
965 if (subfolder_name) {
966 BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
968 BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
975 /* try CWD/release/folder_name */
976 if(BLI_getwdN(cwd, sizeof(cwd))) {
977 if(test_path(targetpath, cwd, "release", relfolder)) {
982 /* try EXECUTABLE_DIR/release/folder_name */
983 if(test_path(targetpath, bprogdir, "release", relfolder))
985 /* end developer overrides */
989 system_path[0] = '\0';
991 if (test_env_path(system_path, envvar)) {
992 if (subfolder_name) {
993 return test_path(targetpath, system_path, NULL, subfolder_name);
995 BLI_strncpy(targetpath, system_path, FILE_MAX);
1000 system_base_path = (const char *)GHOST_getSystemDir();
1001 if (system_base_path) {
1002 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal(ver));
1009 printf("get_path_system: %s\n", system_path);
1012 if (subfolder_name) {
1013 /* try $BLENDERPATH/folder_name/subfolder_name */
1014 return test_path(targetpath, system_path, folder_name, subfolder_name);
1016 /* try $BLENDERPATH/folder_name */
1017 return test_path(targetpath, system_path, NULL, folder_name);
1021 /* get a folder out of the 'folder_id' presets for paths */
1022 /* returns the path if found, NULL string if not */
1023 char *BLI_get_folder(int folder_id, const char *subfolder)
1025 const int ver= BLENDER_VERSION;
1026 static char path[FILE_MAX] = "";
1028 switch (folder_id) {
1029 case BLENDER_DATAFILES: /* general case */
1030 if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1031 if (get_path_local(path, "datafiles", subfolder, ver)) break;
1032 if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
1035 case BLENDER_USER_DATAFILES:
1036 if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1039 case BLENDER_SYSTEM_DATAFILES:
1040 if (get_path_local(path, "datafiles", subfolder, ver)) break;
1041 if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
1044 case BLENDER_USER_AUTOSAVE:
1045 if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1048 case BLENDER_USER_CONFIG:
1049 if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
1052 case BLENDER_USER_SCRIPTS:
1053 if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
1056 case BLENDER_SYSTEM_SCRIPTS:
1057 if (get_path_local(path, "scripts", subfolder, ver)) break;
1058 if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
1061 case BLENDER_SYSTEM_PYTHON:
1062 if (get_path_local(path, "python", subfolder, ver)) break;
1063 if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
1070 char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
1072 const int ver= BLENDER_VERSION;
1073 static char path[FILE_MAX] = "";
1075 switch (folder_id) {
1076 case BLENDER_USER_DATAFILES:
1077 get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
1079 case BLENDER_USER_CONFIG:
1080 get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
1082 case BLENDER_USER_AUTOSAVE:
1083 get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
1085 case BLENDER_USER_SCRIPTS:
1086 get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
1089 if ('\0' == path[0]) {
1095 char *BLI_get_folder_create(int folder_id, const char *subfolder)
1099 /* only for user folders */
1100 if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1103 path = BLI_get_folder(folder_id, subfolder);
1106 path = BLI_get_user_folder_notest(folder_id, subfolder);
1107 if (path) BLI_recurdir_fileops(path);
1113 char *BLI_get_folder_version(const int id, const int ver, const int do_check)
1115 static char path[FILE_MAX] = "";
1118 case BLENDER_RESOURCE_PATH_USER:
1119 ok= get_path_user(path, NULL, NULL, NULL, ver);
1121 case BLENDER_RESOURCE_PATH_LOCAL:
1122 ok= get_path_local(path, NULL, NULL, ver);
1124 case BLENDER_RESOURCE_PATH_SYSTEM:
1125 ok= get_path_system(path, NULL, NULL, NULL, ver);
1128 path[0]= '\0'; /* incase do_check is false */
1130 BLI_assert(!"incorrect ID");
1133 if((ok == FALSE) && do_check) {
1141 /* ************************************************************* */
1142 /* ************************************************************* */
1150 void BLI_setenv(const char *env, const char*val)
1153 #if (defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)
1154 char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1156 sprintf(envstr, "%s=%s", env, val);
1160 /* non-free windows */
1161 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1162 _putenv_s(env, val);
1165 setenv(env, val, 1);
1171 Only set an env var if already not there.
1172 Like Unix setenv(env, val, 0);
1174 void BLI_setenv_if_new(const char *env, const char* val)
1176 if(getenv(env) == NULL)
1177 BLI_setenv(env, val);
1181 void BLI_clean(char *path)
1183 if(path==NULL) return;
1186 if(path && BLI_strnlen(path, 3) > 2) {
1187 BLI_char_switch(path+2, '/', '\\');
1190 BLI_char_switch(path, '\\', '/');
1194 void BLI_char_switch(char *string, char from, char to)
1196 if(string==NULL) return;
1197 while (*string != 0) {
1198 if (*string == from) *string = to;
1203 void BLI_make_exist(char *dir)
1207 BLI_char_switch(dir, ALTSEP, SEP);
1211 while(BLI_is_dir(dir) == 0){
1213 while(dir[a] != SEP){
1222 get_default_root(dir);
1231 void BLI_make_existing_file(const char *name)
1233 char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1235 BLI_strncpy(di, name, sizeof(di));
1236 BLI_splitdirstring(di, fi);
1239 if (BLI_exists(di) == 0) {
1240 BLI_recurdir_fileops(di);
1245 void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file)
1249 if (!string || !dir || !file) return; /* We don't want any NULLs */
1251 string[0]= 0; /* ton */
1253 /* we first push all slashes into unix mode, just to make sure we don't get
1254 any mess with slashes later on. -jesterKing */
1255 /* constant strings can be passed for those parameters - don't change them - elubie */
1257 BLI_char_switch(relabase, '\\', '/');
1258 BLI_char_switch(dir, '\\', '/');
1259 BLI_char_switch(file, '\\', '/');
1262 /* Resolve relative references */
1263 if (relabase && dir[0] == '/' && dir[1] == '/') {
1266 /* Get the file name, chop everything past the last slash (ie. the filename) */
1267 strcpy(string, relabase);
1269 lslash= BLI_last_slash(string);
1270 if(lslash) *(lslash+1)= 0;
1272 dir+=2; /* Skip over the relative reference */
1276 if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':' ) {
1277 BLI_strncpy(string, dir, 3);
1280 else { /* no drive specified */
1281 /* first option: get the drive from the relabase if it has one */
1282 if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1283 BLI_strncpy(string, relabase, 3);
1287 else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1288 get_default_root(string);
1291 /* ignore leading slashes */
1292 while (*dir == '/' || *dir == '\\') dir++;
1297 strcat(string, dir);
1299 /* Make sure string ends in one (and only one) slash */
1300 /* first trim all slashes from the end of the string */
1301 sl = strlen(string);
1302 while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1303 string[sl-1] = '\0';
1306 /* since we've now removed all slashes, put back one slash at the end. */
1307 strcat(string, "/");
1309 while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1312 strcat (string, file);
1314 /* Push all slashes to the system preferred direction */
1318 int BLI_testextensie(const char *str, const char *ext)
1326 if(a==0 || b==0 || b>=a) {
1328 } else if (BLI_strcasecmp(ext, str + a - b)) {
1337 int BLI_testextensie_array(const char *str, const char **ext_array)
1340 while(ext_array[i]) {
1341 if(BLI_testextensie(str, ext_array[i])) {
1350 /* semicolon separated wildcards, eg:
1351 * '*.zip;*.py;*.exe' */
1352 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1354 const char *ext_step= ext_fnmatch;
1357 while(ext_step[0]) {
1361 if((ext_next=strchr(ext_step, ';'))) {
1362 len_ext= (int)(ext_next - ext_step) + 1;
1365 len_ext= sizeof(pattern);
1368 BLI_strncpy(pattern, ext_step, len_ext);
1370 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1373 ext_step += len_ext;
1380 int BLI_replace_extension(char *path, size_t maxlen, const char *ext)
1384 for(a=strlen(path); a>0; a--) {
1385 if(path[a-1] == '.' || path[a-1] == '/' || path[a-1] == '\\') {
1394 if(a + strlen(ext) >= maxlen)
1397 strcpy(path+a, ext);
1401 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1402 * - wont change 'string'
1403 * - wont create any directories
1404 * - dosnt use CWD, or deal with relative paths.
1405 * - Only fill's in *dir and *file when they are non NULL
1407 void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
1409 char *lslash_str = BLI_last_slash(string);
1410 size_t lslash= lslash_str ? (size_t)(lslash_str - string) + 1 : 0;
1414 BLI_strncpy( dir, string, MIN2(dirlen, lslash + 1)); /* +1 to include the slash and the last char */
1422 BLI_strncpy(file, string+lslash, filelen);
1426 void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen)
1428 BLI_split_dirfile(string, dir, NULL, dirlen, 0);
1431 void BLI_split_file_part(const char *string, char *file, const size_t filelen)
1433 BLI_split_dirfile(string, NULL, file, 0, filelen);
1436 /* simple appending of filename to dir, does not check for valid path! */
1437 void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const char *file)
1439 size_t dirlen= BLI_strnlen(dir, maxlen);
1442 if(dirlen == maxlen) {
1443 memcpy(dst, dir, dirlen);
1444 dst[dirlen - 1]= '\0';
1445 return; /* dir fills the path */
1448 memcpy(dst, dir, dirlen + 1);
1452 if (dirlen + 1 >= maxlen) {
1453 return; /* fills the path */
1456 /* inline BLI_add_slash */
1457 if (dst[dirlen - 1] != SEP) {
1462 if (dirlen >= maxlen) {
1463 return; /* fills the path */
1470 BLI_strncpy(dst + dirlen, file, maxlen - dirlen);
1473 /* like pythons os.path.basename( ) */
1474 char *BLI_path_basename(char *path)
1476 char *filename= BLI_last_slash(path);
1477 return filename ? filename + 1 : path;
1481 Produce image export path.
1483 Fails returning 0 if image filename is empty or if destination path
1484 matches image path (i.e. both are the same file).
1486 Trailing slash in dest_dir is optional.
1490 - if an image is "below" current .blend file directory, rebuild the
1491 same dir structure in dest_dir
1493 For example //textures/foo/bar.png becomes
1494 [dest_dir]/textures/foo/bar.png.
1496 - if an image is not "below" current .blend file directory,
1497 disregard it's path and copy it in the same directory where 3D file
1500 For example //../foo/bar.png becomes [dest_dir]/bar.png.
1502 This logic will help ensure that all image paths are relative and
1503 that a user gets his images in one place. It'll also provide
1504 consistent behaviour across exporters.
1506 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)
1508 char path[FILE_MAX];
1510 char base[FILE_MAX];
1511 char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */
1512 char dest_path[FILE_MAX];
1513 char rel_dir[FILE_MAX];
1522 BLI_split_dir_part(base_dir, blend_dir, sizeof(blend_dir));
1524 if (src_dir[0]=='\0')
1527 BLI_strncpy(path, src_dir, sizeof(path));
1529 /* expand "//" in filename and get absolute path */
1530 BLI_path_abs(path, base_dir);
1532 /* get the directory part */
1533 BLI_split_dirfile(path, dir, base, sizeof(dir), sizeof(base));
1535 len= strlen(blend_dir);
1539 /* if image is "below" current .blend file directory */
1540 if (!strncmp(path, blend_dir, len)) {
1542 /* if image is _in_ current .blend file directory */
1543 if (BLI_path_cmp(dir, blend_dir) == 0) {
1544 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1548 /* rel = image_path_dir - blend_dir */
1549 BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1551 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir);
1552 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base);
1556 /* image is out of current directory */
1558 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1562 BLI_strncpy(abs, dest_path, abs_len);
1565 strncat(rel, rel_dir, rel_len);
1566 strncat(rel, base, rel_len);
1569 /* return 2 if src=dest */
1570 if (BLI_path_cmp(path, dest_path) == 0) {
1571 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1578 char *BLI_first_slash(char *string)
1580 char *ffslash, *fbslash;
1582 ffslash= strchr(string, '/');
1583 fbslash= strchr(string, '\\');
1585 if (!ffslash) return fbslash;
1586 else if (!fbslash) return ffslash;
1588 if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1589 else return fbslash;
1592 char *BLI_last_slash(const char *string)
1594 char *lfslash, *lbslash;
1596 lfslash= strrchr(string, '/');
1597 lbslash= strrchr(string, '\\');
1599 if (!lfslash) return lbslash;
1600 else if (!lbslash) return lfslash;
1602 if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1603 else return lfslash;
1606 /* adds a slash if there isnt one there already */
1607 int BLI_add_slash(char *string)
1609 int len = strlen(string);
1610 if (len==0 || string[len-1] != SEP) {
1612 string[len+1] = '\0';
1618 /* removes a slash if there is one */
1619 void BLI_del_slash(char *string)
1621 int len = strlen(string);
1623 if (string[len-1] == SEP) {
1624 string[len-1] = '\0';
1632 static int add_win32_extension(char *name)
1637 type = BLI_exist(name);
1638 if ((type == 0) || S_ISDIR(type)) {
1640 char filename[FILE_MAXDIR+FILE_MAXFILE];
1641 char ext[FILE_MAXDIR+FILE_MAXFILE];
1642 const char *extensions = getenv("PATHEXT");
1646 strcpy(filename, name);
1647 temp = strstr(extensions, ";");
1649 strncpy(ext, extensions, temp - extensions);
1650 ext[temp - extensions] = 0;
1651 extensions = temp + 1;
1652 strcat(filename, ext);
1654 strcat(filename, extensions);
1657 type = BLI_exist(filename);
1658 if (type && (! S_ISDIR(type))) {
1660 strcpy(name, filename);
1673 /* filename must be FILE_MAX length minimum */
1674 void BLI_where_am_i(char *fullname, const size_t maxlen, const char *name)
1676 char filename[FILE_MAXDIR+FILE_MAXFILE];
1677 const char *path = NULL, *temp;
1680 const char *separator = ";";
1682 const char *separator = ":";
1686 #ifdef WITH_BINRELOC
1687 /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
1688 path = br_find_exe( NULL );
1690 BLI_strncpy(fullname, path, maxlen);
1697 if(GetModuleFileName(0, fullname, maxlen)) {
1698 if(!BLI_exists(fullname)) {
1699 printf("path can't be found: \"%.*s\"\n", maxlen, fullname);
1700 MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
1706 /* unix and non linux */
1707 if (name && name[0]) {
1708 BLI_strncpy(fullname, name, maxlen);
1709 if (name[0] == '.') {
1710 char wdir[FILE_MAX]= "";
1711 BLI_getwdN(wdir, sizeof(wdir)); /* backup cwd to restore after */
1713 // not needed but avoids annoying /./ in name
1715 BLI_join_dirfile(fullname, maxlen, wdir, name+2);
1717 BLI_join_dirfile(fullname, maxlen, wdir, name);
1719 add_win32_extension(fullname); /* XXX, doesnt respect length */
1721 else if (BLI_last_slash(name)) {
1723 BLI_strncpy(fullname, name, maxlen);
1724 add_win32_extension(fullname);
1726 // search for binary in $PATH
1727 path = getenv("PATH");
1730 temp = strstr(path, separator);
1732 strncpy(filename, path, temp - path);
1733 filename[temp - path] = 0;
1736 strncpy(filename, path, sizeof(filename));
1738 BLI_join_dirfile(fullname, maxlen, fullname, name);
1739 if (add_win32_extension(filename)) {
1740 BLI_strncpy(fullname, filename, maxlen);
1747 if (strcmp(name, fullname)) {
1748 printf("guessing '%s' == '%s'\n", name, fullname);
1754 void BLI_where_is_temp(char *fullname, const size_t maxlen, int usertemp)
1758 if (usertemp && BLI_is_dir(U.tempdir)) {
1759 BLI_strncpy(fullname, U.tempdir, maxlen);
1764 if (fullname[0] == '\0') {
1765 const char *tmp = getenv("TEMP"); /* Windows */
1766 if (tmp && BLI_is_dir(tmp)) {
1767 BLI_strncpy(fullname, tmp, maxlen);
1771 /* Other OS's - Try TMP and TMPDIR */
1772 if (fullname[0] == '\0') {
1773 const char *tmp = getenv("TMP");
1774 if (tmp && BLI_is_dir(tmp)) {
1775 BLI_strncpy(fullname, tmp, maxlen);
1779 if (fullname[0] == '\0') {
1780 const char *tmp = getenv("TMPDIR");
1781 if (tmp && BLI_is_dir(tmp)) {
1782 BLI_strncpy(fullname, tmp, maxlen);
1787 if (fullname[0] == '\0') {
1788 BLI_strncpy(fullname, "/tmp/", maxlen);
1790 /* add a trailing slash if needed */
1791 BLI_add_slash(fullname);
1793 if(U.tempdir != fullname) {
1794 BLI_strncpy(U.tempdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1802 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1804 size_t inbytesleft=strlen(original);
1805 size_t outbytesleft=512;
1810 code = locale_charset();
1812 cd=iconv_open("UTF-8", code);
1814 if (cd == (iconv_t)(-1)) {
1815 printf("iconv_open Error");
1819 rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1820 if (rv == (size_t) -1) {
1821 printf("iconv Error\n");
1827 #endif // WITH_ICONV