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.
37 #include "MEM_guardedalloc.h"
39 #include "DNA_userdef_types.h"
41 #include "BLI_fileops.h"
42 #include "BLI_path_util.h"
43 #include "BLI_string.h"
44 #include "BLI_storage.h"
45 #include "BLI_storage_types.h"
46 #include "BLI_utildefines.h"
48 #include "BKE_utildefines.h"
49 #include "BKE_blender.h" // BLENDER_VERSION
51 #include "GHOST_Path-api.h"
53 #if defined WIN32 && !defined _LIBC
54 # include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
66 #define _WIN32_IE 0x0501
70 #include "BLI_winstuff.h"
72 #else /* non windows */
81 #define UNIQUE_NAME_MAX 128
83 extern char bprogname[];
85 static int add_win32_extension(char *name);
86 static char *blender_version_decimal(void);
90 int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
92 unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0;
94 char *lslash = BLI_last_slash(string);
95 len2 = len = strlen(string);
97 lenlslash= (int)(lslash - string);
99 while(len > lenlslash && string[--len] != '.') {};
100 if(len == lenlslash && string[len] != '.') len = len2;
102 for (i = len - 1; i >= lenlslash; i--) {
103 if (isdigit(string[i])) {
118 if (tail) strcpy(tail, &string[nume+1]);
123 if (numlen) *numlen = nume-nums+1;
124 return ((int)atoi(&(string[nums])));
126 if (tail) strcpy(tail, string + len);
128 strncpy(head, string, len);
131 if (numlen) *numlen=0;
136 void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
140 sprintf(fmtstr, "%%s%%.%dd%%s", numlen);
141 sprintf(string, fmtstr, head, pic, tail);
144 /* Foo.001 -> "Foo", 1
145 * Returns the length of "Foo" */
146 int BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
152 memcpy(left, name, (a + 1) * sizeof(char));
154 if(a>1 && name[a-1]==delim) return a;
157 if( name[a]==delim ) {
160 /* casting down to an int, can overflow for large numbers */
165 if( isdigit(name[a])==0 ) break;
170 for(a= 0; name[a]; a++)
176 void BLI_newname(char *name, int add)
178 char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX];
180 unsigned short digits;
182 pic = BLI_stringdec(name, head, tail, &digits);
184 /* are we going from 100 -> 99 or from 10 -> 9 */
185 if (add < 0 && digits < 4 && digits > 0) {
188 for (i = digits; i > 1; i--) exp *= 10;
189 if (pic >= exp && (pic + add) < exp) digits--;
194 if (digits==4 && pic<0) pic= 0;
195 BLI_stringenc(name, head, tail, digits, pic);
200 int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len)
203 BLI_strncpy(name, defname, name_len);
206 if(unique_check(arg, name)) {
207 char tempname[UNIQUE_NAME_MAX];
208 char left[UNIQUE_NAME_MAX];
210 int len= BLI_split_name_num(left, &number, name, delim);
212 int newlen= BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, number);
213 if(newlen >= name_len) {
214 len -= ((newlen + 1) - name_len);
215 if(len < 0) len= number= 0;
218 } while(number++, unique_check(arg, tempname));
220 BLI_strncpy(name, tempname, name_len);
228 /* little helper macro for BLI_uniquename */
230 #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset )
233 /* Generic function to set a unique name. It is only designed to be used in situations
234 * where the name is part of the struct, and also that the name is at most UNIQUE_NAME_MAX chars long.
236 * For places where this is used, see constraint.c for example...
238 * name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
239 * len: maximum length of string (to prevent overflows, etc.)
240 * defname: the name that should be used by default if none is specified already
241 * delim: the character which acts as a delimeter between parts of the name
243 static int uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs)
247 for (link = list->first; link; link= link->next) {
249 if (!strcmp(GIVE_STRADDR(link, name_offs), name)) {
258 static int uniquename_unique_check(void *arg, const char *name)
260 struct {ListBase *lb; void *vlink; short name_offs;} *data= arg;
261 return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
264 void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short name_len)
266 struct {ListBase *lb; void *vlink; short name_offs;} data;
269 data.name_offs= name_offs;
271 assert((name_len > 1) && (name_len <= UNIQUE_NAME_MAX));
273 /* See if we are given an empty string */
274 if (ELEM(NULL, vlink, defname))
277 BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
282 /* ******************** string encoding ***************** */
284 /* This is quite an ugly function... its purpose is to
285 * take the dir name, make it absolute, and clean it up, replacing
286 * excess file entry stuff (like /tmp/../tmp/../)
287 * note that dir isn't protected for max string names...
289 * If relbase is NULL then its ignored
292 void BLI_cleanup_dir(const char *relabase, char *dir)
294 BLI_cleanup_file(relabase, dir);
299 void BLI_cleanup_file(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((a = strlen(dir))){ /* remove the '\\' at the end */
356 while(a>0 && dir[a-1] == '\\'){
362 if(dir[0]=='.') { /* happens, for example in FILE_MAIN */
368 /* support for odd paths: eg /../home/me --> /home/me
369 * this is a valid path in blender but we cant handle this the useual way below
370 * simply strip this prefix then evaluate the path as useual. pythons os.path.normpath() does this */
371 while((strncmp(dir, "/../", 4)==0)) {
372 memmove( dir, dir + 4, strlen(dir + 4) + 1 );
375 while ( (start = strstr(dir, "/../")) ) {
376 eind = start + (4 - 1) /* strlen("/../") - 1 */;
379 if (dir[a] == '/') break;
385 memmove( dir+a, eind, strlen(eind)+1 );
389 while ( (start = strstr(dir,"/./")) ){
390 eind = start + (3 - 1) /* strlen("/./") - 1 */;
391 memmove( start, eind, strlen(eind)+1 );
394 while ( (start = strstr(dir,"//" )) ){
395 eind = start + (2 - 1) /* strlen("//") - 1 */;
396 memmove( start, eind, strlen(eind)+1 );
399 if( (a = strlen(dir)) ){ /* remove all '/' at the end */
400 while(dir[a-1] == '/'){
410 void BLI_path_rel(char *file, const char *relfile)
413 char temp[FILE_MAXDIR+FILE_MAXFILE];
414 char res[FILE_MAXDIR+FILE_MAXFILE];
416 /* if file is already relative, bail out */
417 if(file[0]=='/' && file[1]=='/') return;
419 /* also bail out if relative path is not set */
420 if (relfile[0] == 0) return;
423 if (BLI_strnlen(relfile, 3) > 2 && relfile[1] != ':') {
425 /* fix missing volume name in relative base,
426 can happen with old recent-files.txt files */
427 get_default_root(temp);
429 if (relfile[0] != '\\' && relfile[0] != '/') {
432 BLI_strncpy(ptemp, relfile, FILE_MAXDIR + FILE_MAXFILE-3);
434 BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE);
437 if (BLI_strnlen(file, 3) > 2) {
438 if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] )
442 BLI_strncpy(temp, relfile, FILE_MAX);
445 BLI_char_switch(temp, '\\', '/');
446 BLI_char_switch(file, '\\', '/');
448 /* remove /./ which confuse the following slash counting... */
449 BLI_cleanup_file(NULL, file);
450 BLI_cleanup_file(NULL, temp);
452 /* the last slash in the file indicates where the path part ends */
453 lslash = BLI_last_slash(temp);
457 /* find the prefix of the filename that is equal for both filenames.
458 This is replaced by the two slashes at the beginning */
464 /* dont search beyond the end of the string
465 * in the rare case they match */
466 if ((*p=='\0') || (*q=='\0')) {
471 /* we might have passed the slash when the beginning of a dir matches
472 so we rewind. Only check on the actual filename
475 while ( (q >= file) && (*q != '/') ) { --q; --p; }
477 else if (*p != '/') {
478 while ( (p >= temp) && (*p != '/') ) { --p; --q; }
483 /* p now points to the slash that is at the beginning of the part
484 where the path is different from the relative path.
485 We count the number of directories we need to go up in the
486 hierarchy to arrive at the common 'prefix' of the path
488 while (p && p < lslash) {
494 strcat(res, q+1); /* don't copy the slash at the beginning */
497 BLI_char_switch(res+2, '/', '\\');
503 int BLI_has_parent(char *path)
508 len = BLI_add_slash(path) - 1;
511 if ((path[len] == '\\') || (path[len] == '/'))
518 int BLI_parent_dir(char *path)
520 static char parent_dir[]= {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
521 char tmp[FILE_MAXDIR+FILE_MAXFILE+4];
522 BLI_strncpy(tmp, path, sizeof(tmp)-4);
524 strcat(tmp, parent_dir);
525 BLI_cleanup_dir(NULL, tmp);
527 if (!BLI_testextensie(tmp, parent_dir)) {
528 BLI_strncpy(path, tmp, sizeof(tmp));
535 static int stringframe_chars(char *path, int *char_start, int *char_end)
537 int ch_sta, ch_end, i;
538 /* Insert current frame: file### -> file001 */
540 for (i = 0; path[i] != '\0'; i++) {
541 if (path[i] == '\\' || path[i] == '/') {
542 ch_end = 0; /* this is a directory name, dont use any hashes we found */
543 } else if (path[i] == '#') {
546 while (path[ch_end] == '#') {
549 i = ch_end-1; /* keep searching */
551 /* dont break, there may be a slash after this that invalidates the previous #'s */
567 static void ensure_digits(char *path, int digits)
569 char *file= BLI_last_slash(path);
574 if(strrchr(file, '#') == NULL) {
575 int len= strlen(file);
584 int BLI_path_frame(char *path, int frame, int digits)
589 ensure_digits(path, digits);
591 if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
593 #if 0 // neat but breaks on non ascii strings.
595 sprintf(format, "%%.%ds%%.%dd%%s", ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d%s" */
596 sprintf(tmp, format, path, frame, path+ch_end);
600 sprintf(format, "%%.%dd", ch_end-ch_sta); /* example result: "%.5d" */
601 memcpy(tmp, path, sizeof(char) * ch_sta);
603 p += sprintf(p, format, frame);
604 memcpy(p, path + ch_end, strlen(path + ch_end));
612 int BLI_path_frame_range(char *path, int sta, int end, int digits)
617 ensure_digits(path, digits);
619 if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
620 char tmp[FILE_MAX], format[64];
621 #if 0 // neat but breaks on non ascii strings.
622 sprintf(format, "%%.%ds%%.%dd_%%.%dd%%s", ch_sta, ch_end-ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d-%.5d%s" */
623 sprintf(tmp, format, path, sta, end, path+ch_end);
627 BLI_snprintf(format, sizeof(format), "%%.%dd-%%.%dd%%s", digits, digits);
628 memcpy(tmp, path, ch_sta * sizeof(char));
629 tmp_pt = &tmp[ch_sta];
630 tmp_pt += BLI_snprintf(tmp_pt, sizeof(tmp)-ch_sta, format, sta, end, &path[ch_end]);
631 memcpy(path, tmp, (int)(tmp_pt - tmp) + 1);
638 int BLI_path_abs(char *path, const char *basepath)
640 int wasrelative = (strncmp(path, "//", 2)==0);
644 char vol[3] = {'\0', '\0', '\0'};
646 BLI_strncpy(vol, path, 3);
647 /* we are checking here if we have an absolute path that is not in the current
648 blend file as a lib main - we are basically checking for the case that a
649 UNIX root '/' is passed.
651 if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
653 get_default_root(tmp);
654 // get rid of the slashes at the beginning of the path
655 while (*p == '\\' || *p == '/') {
661 BLI_strncpy(tmp, path, FILE_MAX);
664 BLI_strncpy(tmp, path, sizeof(tmp));
666 /* Check for loading a windows path on a posix system
667 * in this case, there is no use in trying C:/ since it
668 * will never exist on a unix os.
670 * Add a / prefix and lowercase the driveletter, remove the :
671 * C:\foo.JPG -> /c/foo.JPG */
673 if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) {
674 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
676 /* '\' the slash will be converted later */
681 BLI_strncpy(base, basepath, sizeof(base));
683 BLI_cleanup_file(NULL, base);
685 /* push slashes into unix mode - strings entering this part are
686 potentially messed up: having both back- and forward slashes.
687 Here we push into one conform direction, and at the end we
688 push them into the system specific dir. This ensures uniformity
689 of paths and solving some problems (and prevent potential future
690 ones) -jesterKing. */
691 BLI_char_switch(tmp, '\\', '/');
692 BLI_char_switch(base, '\\', '/');
694 /* Paths starting with // will get the blend file as their base,
695 * this isnt standard in any os but is uesed in blender all over the place */
697 char *lslash= BLI_last_slash(base);
699 int baselen= (int) (lslash-base) + 1;
700 /* use path for temp storage here, we copy back over it right away */
701 BLI_strncpy(path, tmp+2, FILE_MAX);
703 memcpy(tmp, base, baselen);
704 BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen);
705 BLI_strncpy(path, tmp, FILE_MAX);
707 BLI_strncpy(path, tmp+2, FILE_MAX);
710 BLI_strncpy(path, tmp, FILE_MAX);
714 if ( path[strlen(path)-1]=='/') {
715 /* remove the '/' so we avoid BLI_cleanup_dir adding an extra \ in WIN32 */
716 path[strlen(path)-1] = '\0';
717 BLI_cleanup_dir(NULL, path);
719 BLI_cleanup_file(NULL, path);
724 /* skip first two chars, which in case of
725 absolute path will be drive:/blabla and
726 in case of relpath //blabla/. So relpath
727 // will be retained, rest will be nice and
728 shiny win32 backward slashes :) -jesterKing
730 BLI_char_switch(path+2, '/', '\\');
738 * Should only be done with command line paths.
739 * this is NOT somthing blenders internal paths support like the // prefix
741 int BLI_path_cwd(char *path)
744 int filelen = strlen(path);
747 if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
750 if (filelen >= 2 && path[0] == '/')
754 if (wasrelative==1) {
755 char cwd[FILE_MAXDIR + FILE_MAXFILE]= "";
756 BLI_getwdN(cwd, sizeof(cwd)); /* incase the full path to the blend isnt used */
758 if (cwd[0] == '\0') {
759 printf( "Could not get the current working directory - $PWD for an unknown reason.");
761 /* uses the blend path relative to cwd important for loading relative linked files.
763 * cwd should contain c:\ etc on win32 so the relbase can be NULL
764 * relbase being NULL also prevents // being misunderstood as relative to the current
765 * blend file which isnt a feature we want to use in this case since were dealing
766 * with a path from the command line, rather then from inside Blender */
768 char origpath[FILE_MAXDIR + FILE_MAXFILE];
769 BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE);
771 BLI_make_file_string(NULL, path, cwd, origpath);
779 /* 'di's filename component is moved into 'fi', di is made a dir path */
780 void BLI_splitdirstring(char *di, char *fi)
782 char *lslash= BLI_last_slash(di);
785 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
788 BLI_strncpy(fi, di, FILE_MAXFILE);
793 void BLI_getlastdir(const char* dir, char *last, int maxlen)
796 const char *lslash = NULL;
797 const char *prevslash = NULL;
799 if ((*s == '\\') || (*s == '/')) {
806 BLI_strncpy(last, prevslash+1, maxlen);
808 BLI_strncpy(last, dir, maxlen);
812 /* This is now only used to really get the user's default document folder */
813 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
814 as default location to save documents */
815 char *BLI_getDefaultDocumentFolder(void) {
817 return getenv("HOME");
821 static char documentfolder[MAXPATHLEN];
824 /* Check for %HOME% env var */
826 ret = getenv("HOME");
828 if (BLI_is_dir(ret)) return ret;
831 /* add user profile support for WIN 2K / NT.
832 * This is %APPDATA%, which translates to either
833 * %USERPROFILE%\Application Data or since Vista
834 * to %USERPROFILE%\AppData\Roaming
836 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
840 if (BLI_is_dir(documentfolder)) return documentfolder;
847 /* NEW stuff, to be cleaned up when fully migrated */
848 /* ************************************************************* */
849 /* ************************************************************* */
851 // #define PATH_DEBUG2
853 static char *blender_version_decimal(void)
855 static char version_str[5];
856 sprintf(version_str, "%d.%02d", BLENDER_VERSION/100, BLENDER_VERSION%100);
860 static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
862 char tmppath[FILE_MAX];
864 if(path_sep) BLI_join_dirfile(tmppath, path_base, path_sep);
865 else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
867 BLI_make_file_string("/", targetpath, tmppath, folder_name);
869 if (BLI_is_dir(targetpath)) {
871 printf("\tpath found: %s\n", targetpath);
877 printf("\tpath missing: %s\n", targetpath);
879 //targetpath[0] = '\0';
884 static int test_env_path(char *path, const char *envvar)
886 char *env = envvar?getenv(envvar):NULL;
889 if (BLI_is_dir(env)) {
890 BLI_strncpy(path, env, FILE_MAX);
898 static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name)
900 char bprogdir[FILE_MAX];
901 char relfolder[FILE_MAX];
904 printf("get_path_local...\n");
907 if (subfolder_name) {
908 BLI_join_dirfile(relfolder, folder_name, subfolder_name);
910 BLI_strncpy(relfolder, folder_name, FILE_MAX);
913 /* use argv[0] (bprogname) to get the path to the executable */
914 BLI_split_dirfile(bprogname, bprogdir, NULL);
916 /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
917 if(test_path(targetpath, bprogdir, blender_version_decimal(), relfolder))
923 static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar)
925 char user_path[FILE_MAX];
926 const char *user_base_path;
930 if (test_env_path(user_path, envvar)) {
931 if (subfolder_name) {
932 return test_path(targetpath, user_path, NULL, subfolder_name);
934 BLI_strncpy(targetpath, user_path, FILE_MAX);
939 user_base_path = (const char *)GHOST_getUserDir();
940 if (user_base_path) {
941 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal());
948 printf("get_path_user: %s\n", user_path);
951 if (subfolder_name) {
952 /* try $HOME/folder_name/subfolder_name */
953 return test_path(targetpath, user_path, folder_name, subfolder_name);
955 /* try $HOME/folder_name */
956 return test_path(targetpath, user_path, NULL, folder_name);
960 static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar)
962 char system_path[FILE_MAX];
963 const char *system_base_path;
966 /* first allow developer only overrides to the system path
967 * these are only used when running blender from source */
969 char relfolder[FILE_MAX];
970 char bprogdir[FILE_MAX];
972 /* use argv[0] (bprogname) to get the path to the executable */
973 BLI_split_dirfile(bprogname, bprogdir, NULL);
975 if (subfolder_name) {
976 BLI_join_dirfile(relfolder, folder_name, subfolder_name);
978 BLI_strncpy(relfolder, folder_name, FILE_MAX);
981 /* try CWD/release/folder_name */
982 if(test_path(targetpath, BLI_getwdN(cwd, sizeof(cwd)), "release", relfolder))
985 /* try EXECUTABLE_DIR/release/folder_name */
986 if(test_path(targetpath, bprogdir, "release", relfolder))
988 /* end developer overrides */
992 system_path[0] = '\0';
994 if (test_env_path(system_path, envvar)) {
995 if (subfolder_name) {
996 return test_path(targetpath, system_path, NULL, subfolder_name);
998 BLI_strncpy(targetpath, system_path, FILE_MAX);
1003 system_base_path = (const char *)GHOST_getSystemDir();
1004 if (system_base_path) {
1005 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal());
1012 printf("get_path_system: %s\n", system_path);
1015 if (subfolder_name) {
1016 /* try $BLENDERPATH/folder_name/subfolder_name */
1017 return test_path(targetpath, system_path, folder_name, subfolder_name);
1019 /* try $BLENDERPATH/folder_name */
1020 return test_path(targetpath, system_path, NULL, folder_name);
1024 /* get a folder out of the 'folder_id' presets for paths */
1025 /* returns the path if found, NULL string if not */
1026 char *BLI_get_folder(int folder_id, const char *subfolder)
1028 static char path[FILE_MAX] = "";
1030 switch (folder_id) {
1031 case BLENDER_DATAFILES: /* general case */
1032 if (get_path_local(path, "datafiles", subfolder)) break;
1033 if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES")) break;
1034 if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES")) break;
1037 case BLENDER_USER_DATAFILES:
1038 if (get_path_local(path, "datafiles", subfolder)) break;
1039 if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES")) break;
1042 case BLENDER_SYSTEM_DATAFILES:
1043 if (get_path_local(path, "datafiles", subfolder)) break;
1044 if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES")) break;
1047 case BLENDER_USER_AUTOSAVE:
1048 if (get_path_local(path, "autosave", subfolder)) break;
1049 if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES")) break;
1052 case BLENDER_CONFIG: /* general case */
1053 if (get_path_local(path, "config", subfolder)) break;
1054 if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
1055 if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
1058 case BLENDER_USER_CONFIG:
1059 if (get_path_local(path, "config", subfolder)) break;
1060 if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
1063 case BLENDER_SYSTEM_CONFIG:
1064 if (get_path_local(path, "config", subfolder)) break;
1065 if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
1068 case BLENDER_SCRIPTS: /* general case */
1069 if (get_path_local(path, "scripts", subfolder)) break;
1070 if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;
1071 if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1074 case BLENDER_USER_SCRIPTS:
1075 if (get_path_local(path, "scripts", subfolder)) break;
1076 if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;
1079 case BLENDER_SYSTEM_SCRIPTS:
1080 if (get_path_local(path, "scripts", subfolder)) break;
1081 if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1084 case BLENDER_PYTHON: /* general case */
1085 if (get_path_local(path, "python", subfolder)) break;
1086 if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1089 case BLENDER_SYSTEM_PYTHON:
1090 if (get_path_local(path, "python", subfolder)) break;
1091 if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1098 char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
1100 static char path[FILE_MAX] = "";
1102 switch (folder_id) {
1103 case BLENDER_USER_DATAFILES:
1104 get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES");
1106 case BLENDER_USER_CONFIG:
1107 get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG");
1109 case BLENDER_USER_AUTOSAVE:
1110 get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE");
1112 case BLENDER_USER_SCRIPTS:
1113 get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS");
1116 if ('\0' == path[0]) {
1122 char *BLI_get_folder_create(int folder_id, const char *subfolder)
1126 /* only for user folders */
1127 if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1130 path = BLI_get_folder(folder_id, subfolder);
1133 path = BLI_get_user_folder_notest(folder_id, subfolder);
1134 if (path) BLI_recurdir_fileops(path);
1142 /* ************************************************************* */
1143 /* ************************************************************* */
1151 void BLI_setenv(const char *env, const char*val)
1153 /* SGI or free windows */
1154 #if (defined(__sgi) || ((defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)))
1155 char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1157 sprintf(envstr, "%s=%s", env, val);
1161 /* non-free windows */
1162 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1163 _putenv_s(env, val);
1166 setenv(env, val, 1);
1172 Only set an env var if already not there.
1173 Like Unix setenv(env, val, 0);
1175 void BLI_setenv_if_new(const char *env, const char* val)
1177 if(getenv(env) == NULL)
1178 BLI_setenv(env, val);
1182 void BLI_clean(char *path)
1187 if(path && BLI_strnlen(path, 3) > 2) {
1188 BLI_char_switch(path+2, '/', '\\');
1191 BLI_char_switch(path, '\\', '/');
1195 void BLI_char_switch(char *string, char from, char to)
1197 if(string==0) return;
1198 while (*string != 0) {
1199 if (*string == from) *string = to;
1204 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, int maxlen, const char *ext)
1384 for(a=strlen(path)-1; a>=0; a--)
1385 if(path[a] == '.' || path[a] == '/' || path[a] == '\\')
1391 if(a + strlen(ext) >= maxlen)
1394 strcpy(path+a, ext);
1398 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1399 * - wont change 'string'
1400 * - wont create any directories
1401 * - dosnt use CWD, or deal with relative paths.
1402 * - Only fill's in *dir and *file when they are non NULL
1404 void BLI_split_dirfile(const char *string, char *dir, char *file)
1406 char *lslash_str = BLI_last_slash(string);
1407 int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0;
1411 BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */
1418 strcpy( file, string+lslash);
1422 /* simple appending of filename to dir, does not check for valid path! */
1423 void BLI_join_dirfile(char *string, const char *dir, const char *file)
1427 if(string != dir) /* compare pointers */
1428 BLI_strncpy(string, dir, FILE_MAX);
1433 sl_dir= BLI_add_slash(string);
1435 if (sl_dir <FILE_MAX) {
1436 BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
1440 /* like pythons os.path.basename( ) */
1441 char *BLI_path_basename(char *path)
1443 char *filename= BLI_last_slash(path);
1444 return filename ? filename + 1 : path;
1448 Produce image export path.
1450 Fails returning 0 if image filename is empty or if destination path
1451 matches image path (i.e. both are the same file).
1453 Trailing slash in dest_dir is optional.
1457 - if an image is "below" current .blend file directory, rebuild the
1458 same dir structure in dest_dir
1460 For example //textures/foo/bar.png becomes
1461 [dest_dir]/textures/foo/bar.png.
1463 - if an image is not "below" current .blend file directory,
1464 disregard it's path and copy it in the same directory where 3D file
1467 For example //../foo/bar.png becomes [dest_dir]/bar.png.
1469 This logic will help ensure that all image paths are relative and
1470 that a user gets his images in one place. It'll also provide
1471 consistent behaviour across exporters.
1473 int BKE_rebase_path(char *abs, int abs_size, char *rel, int rel_size, const char *base_dir, const char *src_dir, const char *dest_dir)
1475 char path[FILE_MAX];
1477 char base[FILE_MAX];
1478 char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */
1479 char dest_path[FILE_MAX];
1480 char rel_dir[FILE_MAX];
1489 BLI_split_dirfile(base_dir, blend_dir, NULL);
1491 if (src_dir[0]=='\0')
1494 BLI_strncpy(path, src_dir, sizeof(path));
1496 /* expand "//" in filename and get absolute path */
1497 BLI_path_abs(path, base_dir);
1499 /* get the directory part */
1500 BLI_split_dirfile(path, dir, base);
1502 len= strlen(blend_dir);
1506 /* if image is "below" current .blend file directory */
1507 if (!strncmp(path, blend_dir, len)) {
1509 /* if image is _in_ current .blend file directory */
1510 if (!strcmp(dir, blend_dir)) {
1511 BLI_join_dirfile(dest_path, dest_dir, base);
1515 /* rel = image_path_dir - blend_dir */
1516 BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1518 BLI_join_dirfile(dest_path, dest_dir, rel_dir);
1519 BLI_join_dirfile(dest_path, dest_path, base);
1523 /* image is out of current directory */
1525 BLI_join_dirfile(dest_path, dest_dir, base);
1529 BLI_strncpy(abs, dest_path, abs_size);
1532 strncat(rel, rel_dir, rel_size);
1533 strncat(rel, base, rel_size);
1536 /* return 2 if src=dest */
1537 if (!strcmp(path, dest_path)) {
1538 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1545 char *BLI_first_slash(char *string) {
1546 char *ffslash, *fbslash;
1548 ffslash= strchr(string, '/');
1549 fbslash= strchr(string, '\\');
1551 if (!ffslash) return fbslash;
1552 else if (!fbslash) return ffslash;
1554 if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1555 else return fbslash;
1558 char *BLI_last_slash(const char *string) {
1559 char *lfslash, *lbslash;
1561 lfslash= strrchr(string, '/');
1562 lbslash= strrchr(string, '\\');
1564 if (!lfslash) return lbslash;
1565 else if (!lbslash) return lfslash;
1567 if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1568 else return lfslash;
1571 /* adds a slash if there isnt one there already */
1572 int BLI_add_slash(char *string) {
1573 int len = strlen(string);
1575 if (len==0 || string[len-1]!='\\') {
1577 string[len+1] = '\0';
1581 if (len==0 || string[len-1]!='/') {
1583 string[len+1] = '\0';
1590 /* removes a slash if there is one */
1591 void BLI_del_slash(char *string) {
1592 int len = strlen(string);
1595 if (string[len-1]=='\\') {
1597 if (string[len-1]=='/') {
1599 string[len-1] = '\0';
1607 static int add_win32_extension(char *name)
1612 type = BLI_exist(name);
1613 if ((type == 0) || S_ISDIR(type)) {
1615 char filename[FILE_MAXDIR+FILE_MAXFILE];
1616 char ext[FILE_MAXDIR+FILE_MAXFILE];
1617 char *extensions = getenv("PATHEXT");
1621 strcpy(filename, name);
1622 temp = strstr(extensions, ";");
1624 strncpy(ext, extensions, temp - extensions);
1625 ext[temp - extensions] = 0;
1626 extensions = temp + 1;
1627 strcat(filename, ext);
1629 strcat(filename, extensions);
1632 type = BLI_exist(filename);
1633 if (type && (! S_ISDIR(type))) {
1635 strcpy(name, filename);
1648 /* filename must be FILE_MAX length minimum */
1649 void BLI_where_am_i(char *fullname, const char *name)
1651 char filename[FILE_MAXDIR+FILE_MAXFILE];
1652 char *path = NULL, *temp;
1655 const char *separator = ";";
1658 const char *separator = ":";
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, FILE_MAXDIR+FILE_MAXFILE);
1674 if(GetModuleFileName(0, fullname, FILE_MAXDIR+FILE_MAXFILE)) {
1675 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1680 /* unix and non linux */
1681 if (name && fullname && strlen(name)) {
1682 strcpy(fullname, name);
1683 if (name[0] == '.') {
1684 // relative path, prepend cwd
1685 BLI_getwdN(fullname, FILE_MAX);
1687 // not needed but avoids annoying /./ in name
1688 if(name && name[0]=='.' && name[1]==slash)
1689 BLI_join_dirfile(fullname, fullname, name+2);
1691 BLI_join_dirfile(fullname, fullname, name);
1693 add_win32_extension(fullname);
1694 } else if (BLI_last_slash(name)) {
1696 strcpy(fullname, name);
1697 add_win32_extension(fullname);
1699 // search for binary in $PATH
1700 path = getenv("PATH");
1703 temp = strstr(path, separator);
1705 strncpy(filename, path, temp - path);
1706 filename[temp - path] = 0;
1709 strncpy(filename, path, sizeof(filename));
1711 BLI_join_dirfile(fullname, fullname, name);
1712 if (add_win32_extension(filename)) {
1713 strcpy(fullname, filename);
1720 if (strcmp(name, fullname)) {
1721 printf("guessing '%s' == '%s'\n", name, fullname);
1726 // in windows change long filename to short filename because
1727 // win2k doesn't know how to parse a commandline with lots of
1728 // spaces and double-quotes. There's another solution to this
1729 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1730 // that's even uglier
1731 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1733 printf("Shortname = '%s'\n", fullname);
1739 void BLI_where_is_temp(char *fullname, int usertemp)
1743 if (usertemp && BLI_is_dir(U.tempdir)) {
1744 strcpy(fullname, U.tempdir);
1749 if (fullname[0] == '\0') {
1750 char *tmp = getenv("TEMP"); /* Windows */
1751 if (tmp && BLI_is_dir(tmp)) {
1752 strcpy(fullname, tmp);
1756 /* Other OS's - Try TMP and TMPDIR */
1757 if (fullname[0] == '\0') {
1758 char *tmp = getenv("TMP");
1759 if (tmp && BLI_is_dir(tmp)) {
1760 strcpy(fullname, tmp);
1764 if (fullname[0] == '\0') {
1765 char *tmp = getenv("TMPDIR");
1766 if (tmp && BLI_is_dir(tmp)) {
1767 strcpy(fullname, tmp);
1772 if (fullname[0] == '\0') {
1773 strcpy(fullname, "/tmp/");
1775 /* add a trailing slash if needed */
1776 BLI_add_slash(fullname);
1778 strcpy(U.tempdir, fullname); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1783 char *get_install_dir(void) {
1784 char *tmpname = BLI_strdup(bprogname);
1788 cut = strstr(tmpname, ".app");
1789 if (cut) cut[0] = 0;
1792 cut = BLI_last_slash(tmpname);
1805 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1807 size_t inbytesleft=strlen(original);
1808 size_t outbytesleft=512;
1813 code = locale_charset();
1815 cd=iconv_open("UTF-8", code);
1817 if (cd == (iconv_t)(-1)) {
1818 printf("iconv_open Error");
1822 rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1823 if (rv == (size_t) -1) {
1824 printf("iconv Error\n");
1830 #endif // WITH_ICONV