|
Blender
V2.59
|
00001 /* 00002 * $Id: path_util.c 38523 2011-07-20 06:05:47Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 * 00029 * various string, file, list operations. 00030 */ 00031 00037 #include <ctype.h> 00038 #include <string.h> 00039 #include <stdlib.h> 00040 #include <assert.h> 00041 00042 #include "MEM_guardedalloc.h" 00043 00044 #include "DNA_userdef_types.h" 00045 00046 #include "BLI_fileops.h" 00047 #include "BLI_path_util.h" 00048 #include "BLI_string.h" 00049 #include "BLI_storage.h" 00050 #include "BLI_storage_types.h" 00051 #include "BLI_utildefines.h" 00052 00053 #include "BKE_utildefines.h" 00054 #include "BKE_blender.h" // BLENDER_VERSION 00055 00056 #include "GHOST_Path-api.h" 00057 00058 #if defined WIN32 && !defined _LIBC 00059 # include "BLI_fnmatch.h" /* use fnmatch included in blenlib */ 00060 #else 00061 # ifndef _GNU_SOURCE 00062 # define _GNU_SOURCE 00063 # endif 00064 # include <fnmatch.h> 00065 #endif 00066 00067 #ifdef WIN32 00068 #include <io.h> 00069 00070 #ifdef _WIN32_IE 00071 #undef _WIN32_IE 00072 #endif 00073 #define _WIN32_IE 0x0501 00074 #include <windows.h> 00075 #include <shlobj.h> 00076 00077 #include "BLI_winstuff.h" 00078 00079 #else /* non windows */ 00080 00081 #ifdef WITH_BINRELOC 00082 #include "binreloc.h" 00083 #endif 00084 00085 #endif /* WIN32 */ 00086 00087 /* local */ 00088 #define UNIQUE_NAME_MAX 128 00089 00090 extern char bprogname[]; 00091 00092 static int add_win32_extension(char *name); 00093 static char *blender_version_decimal(const int ver); 00094 00095 /* implementation */ 00096 00097 int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen) 00098 { 00099 unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0; 00100 short i, found = 0; 00101 char *lslash = BLI_last_slash(string); 00102 len2 = len = strlen(string); 00103 if(lslash) 00104 lenlslash= (int)(lslash - string); 00105 00106 while(len > lenlslash && string[--len] != '.') {}; 00107 if(len == lenlslash && string[len] != '.') len = len2; 00108 00109 for (i = len - 1; i >= lenlslash; i--) { 00110 if (isdigit(string[i])) { 00111 if (found){ 00112 nums = i; 00113 } 00114 else{ 00115 nume = i; 00116 nums = i; 00117 found = 1; 00118 } 00119 } 00120 else { 00121 if (found) break; 00122 } 00123 } 00124 if (found) { 00125 if (tail) strcpy(tail, &string[nume+1]); 00126 if (head) { 00127 strcpy(head,string); 00128 head[nums]=0; 00129 } 00130 if (numlen) *numlen = nume-nums+1; 00131 return ((int)atoi(&(string[nums]))); 00132 } 00133 if (tail) strcpy(tail, string + len); 00134 if (head) { 00135 strncpy(head, string, len); 00136 head[len] = '\0'; 00137 } 00138 if (numlen) *numlen=0; 00139 return 0; 00140 } 00141 00142 00143 void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic) 00144 { 00145 char fmtstr[16]=""; 00146 if(pic < 0) pic= 0; 00147 sprintf(fmtstr, "%%s%%.%dd%%s", numlen); 00148 sprintf(string, fmtstr, head, pic, tail); 00149 } 00150 00151 /* Foo.001 -> "Foo", 1 00152 * Returns the length of "Foo" */ 00153 int BLI_split_name_num(char *left, int *nr, const char *name, const char delim) 00154 { 00155 int a; 00156 00157 *nr= 0; 00158 a= strlen(name); 00159 memcpy(left, name, (a + 1) * sizeof(char)); 00160 00161 if(a>1 && name[a-1]==delim) return a; 00162 00163 while(a--) { 00164 if( name[a]==delim ) { 00165 left[a]= 0; 00166 *nr= atol(name+a+1); 00167 /* casting down to an int, can overflow for large numbers */ 00168 if(*nr < 0) 00169 *nr= 0; 00170 return a; 00171 } 00172 if( isdigit(name[a])==0 ) break; 00173 00174 left[a]= 0; 00175 } 00176 00177 for(a= 0; name[a]; a++) 00178 left[a]= name[a]; 00179 00180 return a; 00181 } 00182 00183 void BLI_newname(char *name, int add) 00184 { 00185 char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX]; 00186 int pic; 00187 unsigned short digits; 00188 00189 pic = BLI_stringdec(name, head, tail, &digits); 00190 00191 /* are we going from 100 -> 99 or from 10 -> 9 */ 00192 if (add < 0 && digits < 4 && digits > 0) { 00193 int i, exp; 00194 exp = 1; 00195 for (i = digits; i > 1; i--) exp *= 10; 00196 if (pic >= exp && (pic + add) < exp) digits--; 00197 } 00198 00199 pic += add; 00200 00201 if (digits==4 && pic<0) pic= 0; 00202 BLI_stringenc(name, head, tail, digits, pic); 00203 } 00204 00205 00206 00207 int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len) 00208 { 00209 if(name[0] == '\0') { 00210 BLI_strncpy(name, defname, name_len); 00211 } 00212 00213 if(unique_check(arg, name)) { 00214 char tempname[UNIQUE_NAME_MAX]; 00215 char left[UNIQUE_NAME_MAX]; 00216 int number; 00217 int len= BLI_split_name_num(left, &number, name, delim); 00218 do { 00219 int newlen= BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, ++number); 00220 if(newlen >= name_len) { 00221 len -= ((newlen + 1) - name_len); 00222 if(len < 0) len= number= 0; 00223 left[len]= '\0'; 00224 } 00225 } while(unique_check(arg, tempname)); 00226 00227 BLI_strncpy(name, tempname, name_len); 00228 00229 return 1; 00230 } 00231 00232 return 0; 00233 } 00234 00235 /* little helper macro for BLI_uniquename */ 00236 #ifndef GIVE_STRADDR 00237 #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset ) 00238 #endif 00239 00240 /* Generic function to set a unique name. It is only designed to be used in situations 00241 * where the name is part of the struct, and also that the name is at most UNIQUE_NAME_MAX chars long. 00242 * 00243 * For places where this is used, see constraint.c for example... 00244 * 00245 * name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h 00246 * len: maximum length of string (to prevent overflows, etc.) 00247 * defname: the name that should be used by default if none is specified already 00248 * delim: the character which acts as a delimeter between parts of the name 00249 */ 00250 static int uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs) 00251 { 00252 Link *link; 00253 00254 for (link = list->first; link; link= link->next) { 00255 if (link != vlink) { 00256 if (!strcmp(GIVE_STRADDR(link, name_offs), name)) { 00257 return 1; 00258 } 00259 } 00260 } 00261 00262 return 0; 00263 } 00264 00265 static int uniquename_unique_check(void *arg, const char *name) 00266 { 00267 struct {ListBase *lb; void *vlink; short name_offs;} *data= arg; 00268 return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs); 00269 } 00270 00271 void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short name_len) 00272 { 00273 struct {ListBase *lb; void *vlink; short name_offs;} data; 00274 data.lb= list; 00275 data.vlink= vlink; 00276 data.name_offs= name_offs; 00277 00278 assert((name_len > 1) && (name_len <= UNIQUE_NAME_MAX)); 00279 00280 /* See if we are given an empty string */ 00281 if (ELEM(NULL, vlink, defname)) 00282 return; 00283 00284 BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len); 00285 } 00286 00287 00288 00289 /* ******************** string encoding ***************** */ 00290 00291 /* This is quite an ugly function... its purpose is to 00292 * take the dir name, make it absolute, and clean it up, replacing 00293 * excess file entry stuff (like /tmp/../tmp/../) 00294 * note that dir isn't protected for max string names... 00295 * 00296 * If relbase is NULL then its ignored 00297 */ 00298 00299 void BLI_cleanup_path(const char *relabase, char *dir) 00300 { 00301 short a; 00302 char *start, *eind; 00303 if (relabase) { 00304 BLI_path_abs(dir, relabase); 00305 } else { 00306 if (dir[0]=='/' && dir[1]=='/') { 00307 if (dir[2]== '\0') { 00308 return; /* path is "//" - cant clean it */ 00309 } 00310 dir = dir+2; /* skip the first // */ 00311 } 00312 } 00313 00314 /* Note 00315 * memmove( start, eind, strlen(eind)+1 ); 00316 * is the same as 00317 * strcpy( start, eind ); 00318 * except strcpy should not be used because there is overlap, 00319 * so use memmove's slightly more obscure syntax - Campbell 00320 */ 00321 00322 #ifdef WIN32 00323 00324 /* Note, this should really be moved to the file selector, 00325 * since this function is used in many areas */ 00326 if(strcmp(dir, ".")==0) { /* happens for example in FILE_MAIN */ 00327 get_default_root(dir); 00328 return; 00329 } 00330 00331 while ( (start = strstr(dir, "\\..\\")) ) { 00332 eind = start + strlen("\\..\\") - 1; 00333 a = start-dir-1; 00334 while (a>0) { 00335 if (dir[a] == '\\') break; 00336 a--; 00337 } 00338 if (a<0) { 00339 break; 00340 } else { 00341 memmove( dir+a, eind, strlen(eind)+1 ); 00342 } 00343 } 00344 00345 while ( (start = strstr(dir,"\\.\\")) ){ 00346 eind = start + strlen("\\.\\") - 1; 00347 memmove( start, eind, strlen(eind)+1 ); 00348 } 00349 00350 while ( (start = strstr(dir,"\\\\" )) ){ 00351 eind = start + strlen("\\\\") - 1; 00352 memmove( start, eind, strlen(eind)+1 ); 00353 } 00354 #else 00355 if(dir[0]=='.') { /* happens, for example in FILE_MAIN */ 00356 dir[0]= '/'; 00357 dir[1]= 0; 00358 return; 00359 } 00360 00361 /* support for odd paths: eg /../home/me --> /home/me 00362 * this is a valid path in blender but we cant handle this the useual way below 00363 * simply strip this prefix then evaluate the path as useual. pythons os.path.normpath() does this */ 00364 while((strncmp(dir, "/../", 4)==0)) { 00365 memmove( dir, dir + 4, strlen(dir + 4) + 1 ); 00366 } 00367 00368 while ( (start = strstr(dir, "/../")) ) { 00369 eind = start + (4 - 1) /* strlen("/../") - 1 */; 00370 a = start-dir-1; 00371 while (a>0) { 00372 if (dir[a] == '/') break; 00373 a--; 00374 } 00375 if (a<0) { 00376 break; 00377 } else { 00378 memmove( dir+a, eind, strlen(eind)+1 ); 00379 } 00380 } 00381 00382 while ( (start = strstr(dir,"/./")) ){ 00383 eind = start + (3 - 1) /* strlen("/./") - 1 */; 00384 memmove( start, eind, strlen(eind)+1 ); 00385 } 00386 00387 while ( (start = strstr(dir,"//" )) ){ 00388 eind = start + (2 - 1) /* strlen("//") - 1 */; 00389 memmove( start, eind, strlen(eind)+1 ); 00390 } 00391 #endif 00392 } 00393 00394 void BLI_cleanup_dir(const char *relabase, char *dir) 00395 { 00396 BLI_cleanup_path(relabase, dir); 00397 BLI_add_slash(dir); 00398 00399 } 00400 00401 void BLI_cleanup_file(const char *relabase, char *dir) 00402 { 00403 BLI_cleanup_path(relabase, dir); 00404 BLI_del_slash(dir); 00405 } 00406 00407 void BLI_path_rel(char *file, const char *relfile) 00408 { 00409 char * lslash; 00410 char temp[FILE_MAXDIR+FILE_MAXFILE]; 00411 char res[FILE_MAXDIR+FILE_MAXFILE]; 00412 00413 /* if file is already relative, bail out */ 00414 if(file[0]=='/' && file[1]=='/') return; 00415 00416 /* also bail out if relative path is not set */ 00417 if (relfile[0] == 0) return; 00418 00419 #ifdef WIN32 00420 if (BLI_strnlen(relfile, 3) > 2 && relfile[1] != ':') { 00421 char* ptemp; 00422 /* fix missing volume name in relative base, 00423 can happen with old recent-files.txt files */ 00424 get_default_root(temp); 00425 ptemp = &temp[2]; 00426 if (relfile[0] != '\\' && relfile[0] != '/') { 00427 ptemp++; 00428 } 00429 BLI_strncpy(ptemp, relfile, FILE_MAXDIR + FILE_MAXFILE-3); 00430 } else { 00431 BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE); 00432 } 00433 00434 if (BLI_strnlen(file, 3) > 2) { 00435 if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] ) 00436 return; 00437 } 00438 #else 00439 BLI_strncpy(temp, relfile, FILE_MAX); 00440 #endif 00441 00442 BLI_char_switch(temp, '\\', '/'); 00443 BLI_char_switch(file, '\\', '/'); 00444 00445 /* remove /./ which confuse the following slash counting... */ 00446 BLI_cleanup_path(NULL, file); 00447 BLI_cleanup_path(NULL, temp); 00448 00449 /* the last slash in the file indicates where the path part ends */ 00450 lslash = BLI_last_slash(temp); 00451 00452 if (lslash) 00453 { 00454 /* find the prefix of the filename that is equal for both filenames. 00455 This is replaced by the two slashes at the beginning */ 00456 char *p= temp; 00457 char *q= file; 00458 00459 #ifdef WIN32 00460 while (tolower(*p) == tolower(*q)) 00461 #else 00462 while (*p == *q) 00463 #endif 00464 { 00465 ++p; ++q; 00466 /* dont search beyond the end of the string 00467 * in the rare case they match */ 00468 if ((*p=='\0') || (*q=='\0')) { 00469 break; 00470 } 00471 } 00472 00473 /* we might have passed the slash when the beginning of a dir matches 00474 so we rewind. Only check on the actual filename 00475 */ 00476 if (*q != '/') { 00477 while ( (q >= file) && (*q != '/') ) { --q; --p; } 00478 } 00479 else if (*p != '/') { 00480 while ( (p >= temp) && (*p != '/') ) { --p; --q; } 00481 } 00482 00483 strcpy(res, "//"); 00484 00485 /* p now points to the slash that is at the beginning of the part 00486 where the path is different from the relative path. 00487 We count the number of directories we need to go up in the 00488 hierarchy to arrive at the common 'prefix' of the path 00489 */ 00490 while (p && p < lslash) { 00491 if (*p == '/') 00492 strcat(res, "../"); 00493 ++p; 00494 } 00495 00496 strcat(res, q+1); /* don't copy the slash at the beginning */ 00497 00498 #ifdef WIN32 00499 BLI_char_switch(res+2, '/', '\\'); 00500 #endif 00501 strcpy(file, res); 00502 } 00503 } 00504 00505 int BLI_has_parent(char *path) 00506 { 00507 int len; 00508 int slashes = 0; 00509 BLI_clean(path); 00510 len = BLI_add_slash(path) - 1; 00511 00512 while (len>=0) { 00513 if ((path[len] == '\\') || (path[len] == '/')) 00514 slashes++; 00515 len--; 00516 } 00517 return slashes > 1; 00518 } 00519 00520 int BLI_parent_dir(char *path) 00521 { 00522 static char parent_dir[]= {'.', '.', SEP, '\0'}; /* "../" or "..\\" */ 00523 char tmp[FILE_MAXDIR+FILE_MAXFILE+4]; 00524 BLI_strncpy(tmp, path, sizeof(tmp)-4); 00525 BLI_add_slash(tmp); 00526 strcat(tmp, parent_dir); 00527 BLI_cleanup_dir(NULL, tmp); 00528 00529 if (!BLI_testextensie(tmp, parent_dir)) { 00530 BLI_strncpy(path, tmp, sizeof(tmp)); 00531 return 1; 00532 } else { 00533 return 0; 00534 } 00535 } 00536 00537 static int stringframe_chars(char *path, int *char_start, int *char_end) 00538 { 00539 int ch_sta, ch_end, i; 00540 /* Insert current frame: file### -> file001 */ 00541 ch_sta = ch_end = 0; 00542 for (i = 0; path[i] != '\0'; i++) { 00543 if (path[i] == '\\' || path[i] == '/') { 00544 ch_end = 0; /* this is a directory name, dont use any hashes we found */ 00545 } else if (path[i] == '#') { 00546 ch_sta = i; 00547 ch_end = ch_sta+1; 00548 while (path[ch_end] == '#') { 00549 ch_end++; 00550 } 00551 i = ch_end-1; /* keep searching */ 00552 00553 /* dont break, there may be a slash after this that invalidates the previous #'s */ 00554 } 00555 } 00556 00557 if(ch_end) { 00558 *char_start= ch_sta; 00559 *char_end= ch_end; 00560 return 1; 00561 } 00562 else { 00563 *char_start= -1; 00564 *char_end= -1; 00565 return 0; 00566 } 00567 } 00568 00569 static void ensure_digits(char *path, int digits) 00570 { 00571 char *file= BLI_last_slash(path); 00572 00573 if(file==NULL) 00574 file= path; 00575 00576 if(strrchr(file, '#') == NULL) { 00577 int len= strlen(file); 00578 00579 while(digits--) { 00580 file[len++]= '#'; 00581 } 00582 file[len]= '\0'; 00583 } 00584 } 00585 00586 int BLI_path_frame(char *path, int frame, int digits) 00587 { 00588 int ch_sta, ch_end; 00589 00590 if(digits) 00591 ensure_digits(path, digits); 00592 00593 if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */ 00594 char tmp[FILE_MAX]; 00595 sprintf(tmp, "%.*s%.*d%s", ch_sta, path, ch_end-ch_sta, frame, path+ch_end); 00596 strcpy(path, tmp); 00597 return 1; 00598 } 00599 return 0; 00600 } 00601 00602 int BLI_path_frame_range(char *path, int sta, int end, int digits) 00603 { 00604 int ch_sta, ch_end; 00605 00606 if(digits) 00607 ensure_digits(path, digits); 00608 00609 if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */ 00610 char tmp[FILE_MAX]; 00611 sprintf(tmp, "%.*s%.*d-%.*d%s", ch_sta, path, ch_end-ch_sta, sta, ch_end-ch_sta, end, path+ch_end); 00612 strcpy(path, tmp); 00613 return 1; 00614 } 00615 return 0; 00616 } 00617 00618 int BLI_path_abs(char *path, const char *basepath) 00619 { 00620 int wasrelative = (strncmp(path, "//", 2)==0); 00621 char tmp[FILE_MAX]; 00622 char base[FILE_MAX]; 00623 #ifdef WIN32 00624 char vol[3] = {'\0', '\0', '\0'}; 00625 00626 BLI_strncpy(vol, path, 3); 00627 /* we are checking here if we have an absolute path that is not in the current 00628 blend file as a lib main - we are basically checking for the case that a 00629 UNIX root '/' is passed. 00630 */ 00631 if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) { 00632 char *p = path; 00633 get_default_root(tmp); 00634 // get rid of the slashes at the beginning of the path 00635 while (*p == '\\' || *p == '/') { 00636 p++; 00637 } 00638 strcat(tmp, p); 00639 } 00640 else { 00641 BLI_strncpy(tmp, path, FILE_MAX); 00642 } 00643 #else 00644 BLI_strncpy(tmp, path, sizeof(tmp)); 00645 00646 /* Check for loading a windows path on a posix system 00647 * in this case, there is no use in trying C:/ since it 00648 * will never exist on a unix os. 00649 * 00650 * Add a / prefix and lowercase the driveletter, remove the : 00651 * C:\foo.JPG -> /c/foo.JPG */ 00652 00653 if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) { 00654 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */ 00655 tmp[0] = '/'; 00656 /* '\' the slash will be converted later */ 00657 } 00658 00659 #endif 00660 00661 BLI_strncpy(base, basepath, sizeof(base)); 00662 00663 /* file component is ignored, so dont bother with the trailing slash */ 00664 BLI_cleanup_path(NULL, base); 00665 00666 /* push slashes into unix mode - strings entering this part are 00667 potentially messed up: having both back- and forward slashes. 00668 Here we push into one conform direction, and at the end we 00669 push them into the system specific dir. This ensures uniformity 00670 of paths and solving some problems (and prevent potential future 00671 ones) -jesterKing. */ 00672 BLI_char_switch(tmp, '\\', '/'); 00673 BLI_char_switch(base, '\\', '/'); 00674 00675 /* Paths starting with // will get the blend file as their base, 00676 * this isnt standard in any os but is uesed in blender all over the place */ 00677 if (wasrelative) { 00678 char *lslash= BLI_last_slash(base); 00679 if (lslash) { 00680 int baselen= (int) (lslash-base) + 1; 00681 /* use path for temp storage here, we copy back over it right away */ 00682 BLI_strncpy(path, tmp+2, FILE_MAX); 00683 00684 memcpy(tmp, base, baselen); 00685 BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen); 00686 BLI_strncpy(path, tmp, FILE_MAX); 00687 } else { 00688 BLI_strncpy(path, tmp+2, FILE_MAX); 00689 } 00690 } else { 00691 BLI_strncpy(path, tmp, FILE_MAX); 00692 } 00693 00694 BLI_cleanup_path(NULL, path); 00695 00696 #ifdef WIN32 00697 /* skip first two chars, which in case of 00698 absolute path will be drive:/blabla and 00699 in case of relpath //blabla/. So relpath 00700 // will be retained, rest will be nice and 00701 shiny win32 backward slashes :) -jesterKing 00702 */ 00703 BLI_char_switch(path+2, '/', '\\'); 00704 #endif 00705 00706 return wasrelative; 00707 } 00708 00709 00710 /* 00711 * Should only be done with command line paths. 00712 * this is NOT somthing blenders internal paths support like the // prefix 00713 */ 00714 int BLI_path_cwd(char *path) 00715 { 00716 int wasrelative = 1; 00717 int filelen = strlen(path); 00718 00719 #ifdef WIN32 00720 if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) 00721 wasrelative = 0; 00722 #else 00723 if (filelen >= 2 && path[0] == '/') 00724 wasrelative = 0; 00725 #endif 00726 00727 if (wasrelative==1) { 00728 char cwd[FILE_MAXDIR + FILE_MAXFILE]= ""; 00729 BLI_getwdN(cwd, sizeof(cwd)); /* incase the full path to the blend isnt used */ 00730 00731 if (cwd[0] == '\0') { 00732 printf( "Could not get the current working directory - $PWD for an unknown reason."); 00733 } else { 00734 /* uses the blend path relative to cwd important for loading relative linked files. 00735 * 00736 * cwd should contain c:\ etc on win32 so the relbase can be NULL 00737 * relbase being NULL also prevents // being misunderstood as relative to the current 00738 * blend file which isnt a feature we want to use in this case since were dealing 00739 * with a path from the command line, rather than from inside Blender */ 00740 00741 char origpath[FILE_MAXDIR + FILE_MAXFILE]; 00742 BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE); 00743 00744 BLI_make_file_string(NULL, path, cwd, origpath); 00745 } 00746 } 00747 00748 return wasrelative; 00749 } 00750 00751 00752 /* 'di's filename component is moved into 'fi', di is made a dir path */ 00753 void BLI_splitdirstring(char *di, char *fi) 00754 { 00755 char *lslash= BLI_last_slash(di); 00756 00757 if (lslash) { 00758 BLI_strncpy(fi, lslash+1, FILE_MAXFILE); 00759 *(lslash+1)=0; 00760 } else { 00761 BLI_strncpy(fi, di, FILE_MAXFILE); 00762 di[0]= 0; 00763 } 00764 } 00765 00766 void BLI_getlastdir(const char* dir, char *last, const size_t maxlen) 00767 { 00768 const char *s = dir; 00769 const char *lslash = NULL; 00770 const char *prevslash = NULL; 00771 while (*s) { 00772 if ((*s == '\\') || (*s == '/')) { 00773 prevslash = lslash; 00774 lslash = s; 00775 } 00776 s++; 00777 } 00778 if (prevslash) { 00779 BLI_strncpy(last, prevslash+1, maxlen); 00780 } else { 00781 BLI_strncpy(last, dir, maxlen); 00782 } 00783 } 00784 00785 /* This is now only used to really get the user's default document folder */ 00786 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used 00787 as default location to save documents */ 00788 const char *BLI_getDefaultDocumentFolder(void) { 00789 #if !defined(WIN32) 00790 return getenv("HOME"); 00791 00792 #else /* Windows */ 00793 const char * ret; 00794 static char documentfolder[MAXPATHLEN]; 00795 HRESULT hResult; 00796 00797 /* Check for %HOME% env var */ 00798 00799 ret = getenv("HOME"); 00800 if(ret) { 00801 if (BLI_is_dir(ret)) return ret; 00802 } 00803 00804 /* add user profile support for WIN 2K / NT. 00805 * This is %APPDATA%, which translates to either 00806 * %USERPROFILE%\Application Data or since Vista 00807 * to %USERPROFILE%\AppData\Roaming 00808 */ 00809 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder); 00810 00811 if (hResult == S_OK) 00812 { 00813 if (BLI_is_dir(documentfolder)) return documentfolder; 00814 } 00815 00816 return NULL; 00817 #endif 00818 } 00819 00820 /* NEW stuff, to be cleaned up when fully migrated */ 00821 /* ************************************************************* */ 00822 /* ************************************************************* */ 00823 00824 // #define PATH_DEBUG2 00825 00826 static char *blender_version_decimal(const int ver) 00827 { 00828 static char version_str[5]; 00829 sprintf(version_str, "%d.%02d", ver/100, ver%100); 00830 return version_str; 00831 } 00832 00833 static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name) 00834 { 00835 char tmppath[FILE_MAX]; 00836 00837 if(path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep); 00838 else BLI_strncpy(tmppath, path_base, sizeof(tmppath)); 00839 00840 /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */ 00841 if(folder_name) 00842 BLI_make_file_string("/", targetpath, tmppath, folder_name); 00843 else 00844 BLI_strncpy(targetpath, tmppath, sizeof(tmppath)); 00845 00846 if (BLI_is_dir(targetpath)) { 00847 #ifdef PATH_DEBUG2 00848 printf("\tpath found: %s\n", targetpath); 00849 #endif 00850 return 1; 00851 } 00852 else { 00853 #ifdef PATH_DEBUG2 00854 printf("\tpath missing: %s\n", targetpath); 00855 #endif 00856 //targetpath[0] = '\0'; 00857 return 0; 00858 } 00859 } 00860 00861 static int test_env_path(char *path, const char *envvar) 00862 { 00863 const char *env = envvar?getenv(envvar):NULL; 00864 if (!env) return 0; 00865 00866 if (BLI_is_dir(env)) { 00867 BLI_strncpy(path, env, FILE_MAX); 00868 return 1; 00869 } else { 00870 path[0] = '\0'; 00871 return 0; 00872 } 00873 } 00874 00875 static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver) 00876 { 00877 char bprogdir[FILE_MAX]; 00878 char relfolder[FILE_MAX]; 00879 00880 #ifdef PATH_DEBUG2 00881 printf("get_path_local...\n"); 00882 #endif 00883 00884 if(folder_name) { 00885 if (subfolder_name) { 00886 BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name); 00887 } else { 00888 BLI_strncpy(relfolder, folder_name, sizeof(relfolder)); 00889 } 00890 } 00891 else { 00892 relfolder[0]= '\0'; 00893 } 00894 00895 /* use argv[0] (bprogname) to get the path to the executable */ 00896 BLI_split_dirfile(bprogname, bprogdir, NULL); 00897 00898 /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */ 00899 if(test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder)) 00900 return 1; 00901 00902 return 0; 00903 } 00904 00905 static int is_portable_install(void) 00906 { 00907 /* detect portable install by the existance of config folder */ 00908 const int ver= BLENDER_VERSION; 00909 char path[FILE_MAX]; 00910 00911 return get_path_local(path, "config", NULL, ver); 00912 } 00913 00914 static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) 00915 { 00916 char user_path[FILE_MAX]; 00917 const char *user_base_path; 00918 00919 /* for portable install, user path is always local */ 00920 if (is_portable_install()) 00921 return get_path_local(targetpath, folder_name, subfolder_name, ver); 00922 00923 user_path[0] = '\0'; 00924 00925 if (test_env_path(user_path, envvar)) { 00926 if (subfolder_name) { 00927 return test_path(targetpath, user_path, NULL, subfolder_name); 00928 } else { 00929 BLI_strncpy(targetpath, user_path, FILE_MAX); 00930 return 1; 00931 } 00932 } 00933 00934 user_base_path = (const char *)GHOST_getUserDir(); 00935 if (user_base_path) { 00936 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal(ver)); 00937 } 00938 00939 if(!user_path[0]) 00940 return 0; 00941 00942 #ifdef PATH_DEBUG2 00943 printf("get_path_user: %s\n", user_path); 00944 #endif 00945 00946 if (subfolder_name) { 00947 /* try $HOME/folder_name/subfolder_name */ 00948 return test_path(targetpath, user_path, folder_name, subfolder_name); 00949 } else { 00950 /* try $HOME/folder_name */ 00951 return test_path(targetpath, user_path, NULL, folder_name); 00952 } 00953 } 00954 00955 static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) 00956 { 00957 char system_path[FILE_MAX]; 00958 const char *system_base_path; 00959 00960 00961 /* first allow developer only overrides to the system path 00962 * these are only used when running blender from source */ 00963 char cwd[FILE_MAX]; 00964 char relfolder[FILE_MAX]; 00965 char bprogdir[FILE_MAX]; 00966 00967 /* use argv[0] (bprogname) to get the path to the executable */ 00968 BLI_split_dirfile(bprogname, bprogdir, NULL); 00969 00970 if(folder_name) { 00971 if (subfolder_name) { 00972 BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name); 00973 } else { 00974 BLI_strncpy(relfolder, folder_name, sizeof(relfolder)); 00975 } 00976 } 00977 else { 00978 relfolder[0]= '\0'; 00979 } 00980 00981 /* try CWD/release/folder_name */ 00982 if(BLI_getwdN(cwd, sizeof(cwd))) { 00983 if(test_path(targetpath, cwd, "release", relfolder)) { 00984 return 1; 00985 } 00986 } 00987 00988 /* try EXECUTABLE_DIR/release/folder_name */ 00989 if(test_path(targetpath, bprogdir, "release", relfolder)) 00990 return 1; 00991 /* end developer overrides */ 00992 00993 00994 00995 system_path[0] = '\0'; 00996 00997 if (test_env_path(system_path, envvar)) { 00998 if (subfolder_name) { 00999 return test_path(targetpath, system_path, NULL, subfolder_name); 01000 } else { 01001 BLI_strncpy(targetpath, system_path, FILE_MAX); 01002 return 1; 01003 } 01004 } 01005 01006 system_base_path = (const char *)GHOST_getSystemDir(); 01007 if (system_base_path) { 01008 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal(ver)); 01009 } 01010 01011 if(!system_path[0]) 01012 return 0; 01013 01014 #ifdef PATH_DEBUG2 01015 printf("get_path_system: %s\n", system_path); 01016 #endif 01017 01018 if (subfolder_name) { 01019 /* try $BLENDERPATH/folder_name/subfolder_name */ 01020 return test_path(targetpath, system_path, folder_name, subfolder_name); 01021 } else { 01022 /* try $BLENDERPATH/folder_name */ 01023 return test_path(targetpath, system_path, NULL, folder_name); 01024 } 01025 } 01026 01027 /* get a folder out of the 'folder_id' presets for paths */ 01028 /* returns the path if found, NULL string if not */ 01029 char *BLI_get_folder(int folder_id, const char *subfolder) 01030 { 01031 const int ver= BLENDER_VERSION; 01032 static char path[FILE_MAX] = ""; 01033 01034 switch (folder_id) { 01035 case BLENDER_DATAFILES: /* general case */ 01036 if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; 01037 if (get_path_local(path, "datafiles", subfolder, ver)) break; 01038 if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; 01039 return NULL; 01040 01041 case BLENDER_USER_DATAFILES: 01042 if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; 01043 return NULL; 01044 01045 case BLENDER_SYSTEM_DATAFILES: 01046 if (get_path_local(path, "datafiles", subfolder, ver)) break; 01047 if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; 01048 return NULL; 01049 01050 case BLENDER_USER_AUTOSAVE: 01051 if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break; 01052 return NULL; 01053 01054 case BLENDER_USER_CONFIG: 01055 if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break; 01056 return NULL; 01057 01058 case BLENDER_USER_SCRIPTS: 01059 if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break; 01060 return NULL; 01061 01062 case BLENDER_SYSTEM_SCRIPTS: 01063 if (get_path_local(path, "scripts", subfolder, ver)) break; 01064 if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break; 01065 return NULL; 01066 01067 case BLENDER_SYSTEM_PYTHON: 01068 if (get_path_local(path, "python", subfolder, ver)) break; 01069 if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break; 01070 return NULL; 01071 } 01072 01073 return path; 01074 } 01075 01076 char *BLI_get_user_folder_notest(int folder_id, const char *subfolder) 01077 { 01078 const int ver= BLENDER_VERSION; 01079 static char path[FILE_MAX] = ""; 01080 01081 switch (folder_id) { 01082 case BLENDER_USER_DATAFILES: 01083 get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver); 01084 break; 01085 case BLENDER_USER_CONFIG: 01086 get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver); 01087 break; 01088 case BLENDER_USER_AUTOSAVE: 01089 get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver); 01090 break; 01091 case BLENDER_USER_SCRIPTS: 01092 get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver); 01093 break; 01094 } 01095 if ('\0' == path[0]) { 01096 return NULL; 01097 } 01098 return path; 01099 } 01100 01101 char *BLI_get_folder_create(int folder_id, const char *subfolder) 01102 { 01103 char *path; 01104 01105 /* only for user folders */ 01106 if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE)) 01107 return NULL; 01108 01109 path = BLI_get_folder(folder_id, subfolder); 01110 01111 if (!path) { 01112 path = BLI_get_user_folder_notest(folder_id, subfolder); 01113 if (path) BLI_recurdir_fileops(path); 01114 } 01115 01116 return path; 01117 } 01118 01119 char *BLI_get_folder_version(const int id, const int ver, const int do_check) 01120 { 01121 static char path[FILE_MAX] = ""; 01122 int ok; 01123 switch(id) { 01124 case BLENDER_RESOURCE_PATH_USER: 01125 ok= get_path_user(path, NULL, NULL, NULL, ver); 01126 break; 01127 case BLENDER_RESOURCE_PATH_LOCAL: 01128 ok= get_path_local(path, NULL, NULL, ver); 01129 break; 01130 case BLENDER_RESOURCE_PATH_SYSTEM: 01131 ok= get_path_system(path, NULL, NULL, NULL, ver); 01132 break; 01133 default: 01134 path[0]= '\0'; /* incase do_check is false */ 01135 ok= FALSE; 01136 BLI_assert(!"incorrect ID"); 01137 } 01138 01139 if((ok == FALSE) && do_check) { 01140 return NULL; 01141 } 01142 01143 return path; 01144 } 01145 01146 /* End new stuff */ 01147 /* ************************************************************* */ 01148 /* ************************************************************* */ 01149 01150 01151 01152 #ifdef PATH_DEBUG 01153 #undef PATH_DEBUG 01154 #endif 01155 01156 void BLI_setenv(const char *env, const char*val) 01157 { 01158 /* SGI or free windows */ 01159 #if (defined(__sgi) || ((defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS))) 01160 char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */ 01161 01162 sprintf(envstr, "%s=%s", env, val); 01163 putenv(envstr); 01164 MEM_freeN(envstr); 01165 01166 /* non-free windows */ 01167 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */ 01168 _putenv_s(env, val); 01169 #else 01170 /* linux/osx/bsd */ 01171 setenv(env, val, 1); 01172 #endif 01173 } 01174 01175 01180 void BLI_setenv_if_new(const char *env, const char* val) 01181 { 01182 if(getenv(env) == NULL) 01183 BLI_setenv(env, val); 01184 } 01185 01186 01187 void BLI_clean(char *path) 01188 { 01189 if(path==NULL) return; 01190 01191 #ifdef WIN32 01192 if(path && BLI_strnlen(path, 3) > 2) { 01193 BLI_char_switch(path+2, '/', '\\'); 01194 } 01195 #else 01196 BLI_char_switch(path, '\\', '/'); 01197 #endif 01198 } 01199 01200 void BLI_char_switch(char *string, char from, char to) 01201 { 01202 if(string==NULL) return; 01203 while (*string != 0) { 01204 if (*string == from) *string = to; 01205 string++; 01206 } 01207 } 01208 01209 void BLI_make_exist(char *dir) { 01210 int a; 01211 01212 BLI_char_switch(dir, ALTSEP, SEP); 01213 01214 a = strlen(dir); 01215 01216 while(BLI_is_dir(dir) == 0){ 01217 a --; 01218 while(dir[a] != SEP){ 01219 a--; 01220 if (a <= 0) break; 01221 } 01222 if (a >= 0) { 01223 dir[a+1] = '\0'; 01224 } 01225 else { 01226 #ifdef WIN32 01227 get_default_root(dir); 01228 #else 01229 strcpy(dir,"/"); 01230 #endif 01231 break; 01232 } 01233 } 01234 } 01235 01236 void BLI_make_existing_file(const char *name) 01237 { 01238 char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE]; 01239 01240 BLI_strncpy(di, name, sizeof(di)); 01241 BLI_splitdirstring(di, fi); 01242 01243 /* test exist */ 01244 if (BLI_exists(di) == 0) { 01245 BLI_recurdir_fileops(di); 01246 } 01247 } 01248 01249 01250 void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file) 01251 { 01252 int sl; 01253 01254 if (!string || !dir || !file) return; /* We don't want any NULLs */ 01255 01256 string[0]= 0; /* ton */ 01257 01258 /* we first push all slashes into unix mode, just to make sure we don't get 01259 any mess with slashes later on. -jesterKing */ 01260 /* constant strings can be passed for those parameters - don't change them - elubie */ 01261 /* 01262 BLI_char_switch(relabase, '\\', '/'); 01263 BLI_char_switch(dir, '\\', '/'); 01264 BLI_char_switch(file, '\\', '/'); 01265 */ 01266 01267 /* Resolve relative references */ 01268 if (relabase && dir[0] == '/' && dir[1] == '/') { 01269 char *lslash; 01270 01271 /* Get the file name, chop everything past the last slash (ie. the filename) */ 01272 strcpy(string, relabase); 01273 01274 lslash= BLI_last_slash(string); 01275 if(lslash) *(lslash+1)= 0; 01276 01277 dir+=2; /* Skip over the relative reference */ 01278 } 01279 #ifdef WIN32 01280 else { 01281 if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':' ) { 01282 BLI_strncpy(string, dir, 3); 01283 dir += 2; 01284 } 01285 else { /* no drive specified */ 01286 /* first option: get the drive from the relabase if it has one */ 01287 if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) { 01288 BLI_strncpy(string, relabase, 3); 01289 string[2] = '\\'; 01290 string[3] = '\0'; 01291 } 01292 else { /* we're out of luck here, guessing the first valid drive, usually c:\ */ 01293 get_default_root(string); 01294 } 01295 01296 /* ignore leading slashes */ 01297 while (*dir == '/' || *dir == '\\') dir++; 01298 } 01299 } 01300 #endif 01301 01302 strcat(string, dir); 01303 01304 /* Make sure string ends in one (and only one) slash */ 01305 /* first trim all slashes from the end of the string */ 01306 sl = strlen(string); 01307 while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) { 01308 string[sl-1] = '\0'; 01309 sl--; 01310 } 01311 /* since we've now removed all slashes, put back one slash at the end. */ 01312 strcat(string, "/"); 01313 01314 while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */ 01315 file++; 01316 01317 strcat (string, file); 01318 01319 /* Push all slashes to the system preferred direction */ 01320 BLI_clean(string); 01321 } 01322 01323 int BLI_testextensie(const char *str, const char *ext) 01324 { 01325 short a, b; 01326 int retval; 01327 01328 a= strlen(str); 01329 b= strlen(ext); 01330 01331 if(a==0 || b==0 || b>=a) { 01332 retval = 0; 01333 } else if (BLI_strcasecmp(ext, str + a - b)) { 01334 retval = 0; 01335 } else { 01336 retval = 1; 01337 } 01338 01339 return (retval); 01340 } 01341 01342 int BLI_testextensie_array(const char *str, const char **ext_array) 01343 { 01344 int i=0; 01345 while(ext_array[i]) { 01346 if(BLI_testextensie(str, ext_array[i])) { 01347 return 1; 01348 } 01349 01350 i++; 01351 } 01352 return 0; 01353 } 01354 01355 /* semicolon separated wildcards, eg: 01356 * '*.zip;*.py;*.exe' */ 01357 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch) 01358 { 01359 const char *ext_step= ext_fnmatch; 01360 char pattern[16]; 01361 01362 while(ext_step[0]) { 01363 char *ext_next; 01364 int len_ext; 01365 01366 if((ext_next=strchr(ext_step, ';'))) { 01367 len_ext= (int)(ext_next - ext_step) + 1; 01368 } 01369 else { 01370 len_ext= sizeof(pattern); 01371 } 01372 01373 BLI_strncpy(pattern, ext_step, len_ext); 01374 01375 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) { 01376 return 1; 01377 } 01378 ext_step += len_ext; 01379 } 01380 01381 return 0; 01382 } 01383 01384 01385 int BLI_replace_extension(char *path, size_t maxlen, const char *ext) 01386 { 01387 size_t a; 01388 01389 for(a=strlen(path); a>0; a--) { 01390 if(path[a-1] == '.' || path[a-1] == '/' || path[a-1] == '\\') { 01391 a--; 01392 break; 01393 } 01394 } 01395 01396 if(path[a] != '.') 01397 a= strlen(path); 01398 01399 if(a + strlen(ext) >= maxlen) 01400 return 0; 01401 01402 strcpy(path+a, ext); 01403 return 1; 01404 } 01405 01406 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt" 01407 * - wont change 'string' 01408 * - wont create any directories 01409 * - dosnt use CWD, or deal with relative paths. 01410 * - Only fill's in *dir and *file when they are non NULL 01411 * */ 01412 void BLI_split_dirfile(const char *string, char *dir, char *file) 01413 { 01414 char *lslash_str = BLI_last_slash(string); 01415 int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0; 01416 01417 if (dir) { 01418 if (lslash) { 01419 BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */ 01420 } else { 01421 dir[0] = '\0'; 01422 } 01423 } 01424 01425 if (file) { 01426 strcpy( file, string+lslash); 01427 } 01428 } 01429 01430 /* simple appending of filename to dir, does not check for valid path! */ 01431 void BLI_join_dirfile(char *string, const size_t maxlen, const char *dir, const char *file) 01432 { 01433 int sl_dir; 01434 01435 if(string != dir) /* compare pointers */ 01436 BLI_strncpy(string, dir, maxlen); 01437 01438 if (!file) 01439 return; 01440 01441 sl_dir= BLI_add_slash(string); 01442 01443 if (sl_dir <FILE_MAX) { 01444 BLI_strncpy(string + sl_dir, file, maxlen - sl_dir); 01445 } 01446 } 01447 01448 /* like pythons os.path.basename( ) */ 01449 char *BLI_path_basename(char *path) 01450 { 01451 char *filename= BLI_last_slash(path); 01452 return filename ? filename + 1 : path; 01453 } 01454 01455 /* 01456 Produce image export path. 01457 01458 Fails returning 0 if image filename is empty or if destination path 01459 matches image path (i.e. both are the same file). 01460 01461 Trailing slash in dest_dir is optional. 01462 01463 Logic: 01464 01465 - if an image is "below" current .blend file directory, rebuild the 01466 same dir structure in dest_dir 01467 01468 For example //textures/foo/bar.png becomes 01469 [dest_dir]/textures/foo/bar.png. 01470 01471 - if an image is not "below" current .blend file directory, 01472 disregard it's path and copy it in the same directory where 3D file 01473 goes. 01474 01475 For example //../foo/bar.png becomes [dest_dir]/bar.png. 01476 01477 This logic will help ensure that all image paths are relative and 01478 that a user gets his images in one place. It'll also provide 01479 consistent behaviour across exporters. 01480 */ 01481 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) 01482 { 01483 char path[FILE_MAX]; 01484 char dir[FILE_MAX]; 01485 char base[FILE_MAX]; 01486 char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */ 01487 char dest_path[FILE_MAX]; 01488 char rel_dir[FILE_MAX]; 01489 int len; 01490 01491 if (abs) 01492 abs[0]= 0; 01493 01494 if (rel) 01495 rel[0]= 0; 01496 01497 BLI_split_dirfile(base_dir, blend_dir, NULL); 01498 01499 if (src_dir[0]=='\0') 01500 return 0; 01501 01502 BLI_strncpy(path, src_dir, sizeof(path)); 01503 01504 /* expand "//" in filename and get absolute path */ 01505 BLI_path_abs(path, base_dir); 01506 01507 /* get the directory part */ 01508 BLI_split_dirfile(path, dir, base); 01509 01510 len= strlen(blend_dir); 01511 01512 rel_dir[0] = 0; 01513 01514 /* if image is "below" current .blend file directory */ 01515 if (!strncmp(path, blend_dir, len)) { 01516 01517 /* if image is _in_ current .blend file directory */ 01518 if (BLI_path_cmp(dir, blend_dir) == 0) { 01519 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base); 01520 } 01521 /* "below" */ 01522 else { 01523 /* rel = image_path_dir - blend_dir */ 01524 BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir)); 01525 01526 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir); 01527 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base); 01528 } 01529 01530 } 01531 /* image is out of current directory */ 01532 else { 01533 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base); 01534 } 01535 01536 if (abs) 01537 BLI_strncpy(abs, dest_path, abs_len); 01538 01539 if (rel) { 01540 strncat(rel, rel_dir, rel_len); 01541 strncat(rel, base, rel_len); 01542 } 01543 01544 /* return 2 if src=dest */ 01545 if (BLI_path_cmp(path, dest_path) == 0) { 01546 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path); 01547 return 2; 01548 } 01549 01550 return 1; 01551 } 01552 01553 char *BLI_first_slash(char *string) { 01554 char *ffslash, *fbslash; 01555 01556 ffslash= strchr(string, '/'); 01557 fbslash= strchr(string, '\\'); 01558 01559 if (!ffslash) return fbslash; 01560 else if (!fbslash) return ffslash; 01561 01562 if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash; 01563 else return fbslash; 01564 } 01565 01566 char *BLI_last_slash(const char *string) { 01567 char *lfslash, *lbslash; 01568 01569 lfslash= strrchr(string, '/'); 01570 lbslash= strrchr(string, '\\'); 01571 01572 if (!lfslash) return lbslash; 01573 else if (!lbslash) return lfslash; 01574 01575 if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash; 01576 else return lfslash; 01577 } 01578 01579 /* adds a slash if there isnt one there already */ 01580 int BLI_add_slash(char *string) { 01581 int len = strlen(string); 01582 #ifdef WIN32 01583 if (len==0 || string[len-1]!='\\') { 01584 string[len] = '\\'; 01585 string[len+1] = '\0'; 01586 return len+1; 01587 } 01588 #else 01589 if (len==0 || string[len-1]!='/') { 01590 string[len] = '/'; 01591 string[len+1] = '\0'; 01592 return len+1; 01593 } 01594 #endif 01595 return len; 01596 } 01597 01598 /* removes a slash if there is one */ 01599 void BLI_del_slash(char *string) { 01600 int len = strlen(string); 01601 while (len) { 01602 #ifdef WIN32 01603 if (string[len-1]=='\\') { 01604 #else 01605 if (string[len-1]=='/') { 01606 #endif 01607 string[len-1] = '\0'; 01608 len--; 01609 } else { 01610 break; 01611 } 01612 } 01613 } 01614 01615 static int add_win32_extension(char *name) 01616 { 01617 int retval = 0; 01618 int type; 01619 01620 type = BLI_exist(name); 01621 if ((type == 0) || S_ISDIR(type)) { 01622 #ifdef _WIN32 01623 char filename[FILE_MAXDIR+FILE_MAXFILE]; 01624 char ext[FILE_MAXDIR+FILE_MAXFILE]; 01625 const char *extensions = getenv("PATHEXT"); 01626 if (extensions) { 01627 char *temp; 01628 do { 01629 strcpy(filename, name); 01630 temp = strstr(extensions, ";"); 01631 if (temp) { 01632 strncpy(ext, extensions, temp - extensions); 01633 ext[temp - extensions] = 0; 01634 extensions = temp + 1; 01635 strcat(filename, ext); 01636 } else { 01637 strcat(filename, extensions); 01638 } 01639 01640 type = BLI_exist(filename); 01641 if (type && (! S_ISDIR(type))) { 01642 retval = 1; 01643 strcpy(name, filename); 01644 break; 01645 } 01646 } while (temp); 01647 } 01648 #endif 01649 } else { 01650 retval = 1; 01651 } 01652 01653 return (retval); 01654 } 01655 01656 /* filename must be FILE_MAX length minimum */ 01657 void BLI_where_am_i(char *fullname, const size_t maxlen, const char *name) 01658 { 01659 char filename[FILE_MAXDIR+FILE_MAXFILE]; 01660 const char *path = NULL, *temp; 01661 01662 #ifdef _WIN32 01663 const char *separator = ";"; 01664 #else 01665 const char *separator = ":"; 01666 #endif 01667 01668 01669 #ifdef WITH_BINRELOC 01670 /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */ 01671 path = br_find_exe( NULL ); 01672 if (path) { 01673 BLI_strncpy(fullname, path, maxlen); 01674 free((void *)path); 01675 return; 01676 } 01677 #endif 01678 01679 #ifdef _WIN32 01680 if(GetModuleFileName(0, fullname, maxlen)) { 01681 if(!BLI_exists(fullname)) { 01682 printf("path can't be found: \"%.*s\"\n", maxlen, fullname); 01683 MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK); 01684 } 01685 return; 01686 } 01687 #endif 01688 01689 /* unix and non linux */ 01690 if (name && name[0]) { 01691 BLI_strncpy(fullname, name, maxlen); 01692 if (name[0] == '.') { 01693 char wdir[FILE_MAX]= ""; 01694 BLI_getwdN(wdir, sizeof(wdir)); /* backup cwd to restore after */ 01695 01696 // not needed but avoids annoying /./ in name 01697 if(name[1]==SEP) 01698 BLI_join_dirfile(fullname, maxlen, wdir, name+2); 01699 else 01700 BLI_join_dirfile(fullname, maxlen, wdir, name); 01701 01702 add_win32_extension(fullname); /* XXX, doesnt respect length */ 01703 } 01704 else if (BLI_last_slash(name)) { 01705 // full path 01706 BLI_strncpy(fullname, name, maxlen); 01707 add_win32_extension(fullname); 01708 } else { 01709 // search for binary in $PATH 01710 path = getenv("PATH"); 01711 if (path) { 01712 do { 01713 temp = strstr(path, separator); 01714 if (temp) { 01715 strncpy(filename, path, temp - path); 01716 filename[temp - path] = 0; 01717 path = temp + 1; 01718 } else { 01719 strncpy(filename, path, sizeof(filename)); 01720 } 01721 BLI_join_dirfile(fullname, maxlen, fullname, name); 01722 if (add_win32_extension(filename)) { 01723 BLI_strncpy(fullname, filename, maxlen); 01724 break; 01725 } 01726 } while (temp); 01727 } 01728 } 01729 #if defined(DEBUG) 01730 if (strcmp(name, fullname)) { 01731 printf("guessing '%s' == '%s'\n", name, fullname); 01732 } 01733 #endif 01734 } 01735 } 01736 01737 void BLI_where_is_temp(char *fullname, const size_t maxlen, int usertemp) 01738 { 01739 fullname[0] = '\0'; 01740 01741 if (usertemp && BLI_is_dir(U.tempdir)) { 01742 BLI_strncpy(fullname, U.tempdir, maxlen); 01743 } 01744 01745 01746 #ifdef WIN32 01747 if (fullname[0] == '\0') { 01748 const char *tmp = getenv("TEMP"); /* Windows */ 01749 if (tmp && BLI_is_dir(tmp)) { 01750 BLI_strncpy(fullname, tmp, maxlen); 01751 } 01752 } 01753 #else 01754 /* Other OS's - Try TMP and TMPDIR */ 01755 if (fullname[0] == '\0') { 01756 const char *tmp = getenv("TMP"); 01757 if (tmp && BLI_is_dir(tmp)) { 01758 BLI_strncpy(fullname, tmp, maxlen); 01759 } 01760 } 01761 01762 if (fullname[0] == '\0') { 01763 const char *tmp = getenv("TMPDIR"); 01764 if (tmp && BLI_is_dir(tmp)) { 01765 BLI_strncpy(fullname, tmp, maxlen); 01766 } 01767 } 01768 #endif 01769 01770 if (fullname[0] == '\0') { 01771 BLI_strncpy(fullname, "/tmp/", maxlen); 01772 } else { 01773 /* add a trailing slash if needed */ 01774 BLI_add_slash(fullname); 01775 #ifdef WIN32 01776 if(U.tempdir != fullname) { 01777 BLI_strncpy(U.tempdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */ 01778 } 01779 #endif 01780 } 01781 } 01782 01783 #ifdef WITH_ICONV 01784 01785 void BLI_string_to_utf8(char *original, char *utf_8, const char *code) 01786 { 01787 size_t inbytesleft=strlen(original); 01788 size_t outbytesleft=512; 01789 size_t rv=0; 01790 iconv_t cd; 01791 01792 if (NULL == code) { 01793 code = locale_charset(); 01794 } 01795 cd=iconv_open("UTF-8", code); 01796 01797 if (cd == (iconv_t)(-1)) { 01798 printf("iconv_open Error"); 01799 *utf_8='\0'; 01800 return ; 01801 } 01802 rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft); 01803 if (rv == (size_t) -1) { 01804 printf("iconv Error\n"); 01805 return ; 01806 } 01807 *utf_8 = '\0'; 01808 iconv_close(cd); 01809 } 01810 #endif // WITH_ICONV 01811 01812