use BLI_strnlen rather then strlen when comparing against fixed lengths.
[blender.git] / source / blender / blenlib / intern / path_util.c
1 /**
2  *  $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
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.
10  *
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.
15  *
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.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  * various string, file, list operations.
30  */
31
32 #include <ctype.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <assert.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_userdef_types.h"
40
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
47 #include "BKE_utildefines.h"
48 #include "BKE_blender.h"        // BLENDER_VERSION
49
50 #include "GHOST_Path-api.h"
51
52 #if defined WIN32 && !defined _LIBC
53 # include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
54 #else
55 # define _GNU_SOURCE
56 # include <fnmatch.h>
57 #endif
58
59 #ifdef WIN32
60 #include <io.h>
61
62 #ifdef _WIN32_IE
63 #undef _WIN32_IE
64 #endif
65 #define _WIN32_IE 0x0501
66 #include <windows.h>
67 #include <shlobj.h>
68
69 #include "BLI_winstuff.h"
70
71 #else /* non windows */
72
73 #ifdef __linux__
74 #include "binreloc.h"
75 #endif
76
77 #endif /* WIN32 */
78
79 /* local */
80 #define UNIQUE_NAME_MAX 128
81
82 extern char bprogname[];
83
84 static int add_win32_extension(char *name);
85 static char *blender_version_decimal(void);
86
87 /* implementation */
88
89 int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
90 {
91         unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0;
92         short i, found = 0;
93         char *lslash = BLI_last_slash(string);
94         len2 = len = strlen(string);
95         if(lslash)
96                 lenlslash= (int)(lslash - string);
97
98         while(len > lenlslash && string[--len] != '.') {};
99         if(len == lenlslash && string[len] != '.') len = len2;
100
101         for (i = len - 1; i >= lenlslash; i--) {
102                 if (isdigit(string[i])) {
103                         if (found){
104                                 nums = i;
105                         }
106                         else{
107                                 nume = i;
108                                 nums = i;
109                                 found = 1;
110                         }
111                 }
112                 else {
113                         if (found) break;
114                 }
115         }
116         if (found) {
117                 if (tail) strcpy(tail, &string[nume+1]);
118                 if (head) {
119                         strcpy(head,string);
120                         head[nums]=0;
121                 }
122                 if (numlen) *numlen = nume-nums+1;
123                 return ((int)atoi(&(string[nums])));
124         }
125         if (tail) strcpy(tail, string + len);
126         if (head) {
127                 strncpy(head, string, len);
128                 head[len] = '\0';
129         }
130         if (numlen) *numlen=0;
131         return 0;
132 }
133
134
135 void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
136 {
137         char fmtstr[16]="";
138         if(pic < 0) pic= 0;
139         sprintf(fmtstr, "%%s%%.%dd%%s", numlen);
140         sprintf(string, fmtstr, head, pic, tail);
141 }
142
143 /* Foo.001 -> "Foo", 1
144  * Returns the length of "Foo" */
145 int BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
146 {
147         int a;
148         
149         *nr= 0;
150         a= strlen(name);
151         memcpy(left, name, (a + 1) * sizeof(char));
152
153         if(a>1 && name[a-1]==delim) return a;
154         
155         while(a--) {
156                 if( name[a]==delim ) {
157                         left[a]= 0;
158                         *nr= atol(name+a+1);
159                         /* casting down to an int, can overflow for large numbers */
160                         if(*nr < 0)
161                                 *nr= 0;
162                         return a;
163                 }
164                 if( isdigit(name[a])==0 ) break;
165                 
166                 left[a]= 0;
167         }
168
169         for(a= 0; name[a]; a++)
170                 left[a]= name[a];
171
172         return a;
173 }
174
175 void BLI_newname(char *name, int add)
176 {
177         char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX];
178         int pic;
179         unsigned short digits;
180         
181         pic = BLI_stringdec(name, head, tail, &digits);
182         
183         /* are we going from 100 -> 99 or from 10 -> 9 */
184         if (add < 0 && digits < 4 && digits > 0) {
185                 int i, exp;
186                 exp = 1;
187                 for (i = digits; i > 1; i--) exp *= 10;
188                 if (pic >= exp && (pic + add) < exp) digits--;
189         }
190         
191         pic += add;
192         
193         if (digits==4 && pic<0) pic= 0;
194         BLI_stringenc(name, head, tail, digits, pic);
195 }
196
197
198
199 int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len)
200 {
201         if(name == '\0') {
202                 BLI_strncpy(name, defname, name_len);
203         }
204
205         if(unique_check(arg, name)) {
206                 char    tempname[UNIQUE_NAME_MAX];
207                 char    left[UNIQUE_NAME_MAX];
208                 int             number;
209                 int             len= BLI_split_name_num(left, &number, name, delim);
210                 do {
211                         int newlen= BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, number);
212                         if(newlen >= name_len) {
213                                 len -= ((newlen + 1) - name_len);
214                                 if(len < 0) len= number= 0;
215                                 left[len]= '\0';
216                         }
217                 } while(number++, unique_check(arg, tempname));
218
219                 BLI_strncpy(name, tempname, name_len);
220                 
221                 return 1;
222         }
223         
224         return 0;
225 }
226
227 /* little helper macro for BLI_uniquename */
228 #ifndef GIVE_STRADDR
229         #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset )
230 #endif
231
232 /* Generic function to set a unique name. It is only designed to be used in situations
233  * where the name is part of the struct, and also that the name is at most UNIQUE_NAME_MAX chars long.
234  * 
235  * For places where this is used, see constraint.c for example...
236  *
237  *      name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
238  *      len: maximum length of string (to prevent overflows, etc.)
239  *      defname: the name that should be used by default if none is specified already
240  *      delim: the character which acts as a delimeter between parts of the name
241  */
242 static int uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs)
243 {
244         Link *link;
245
246         for (link = list->first; link; link= link->next) {
247                 if (link != vlink) {
248                         if (!strcmp(GIVE_STRADDR(link, name_offs), name)) {
249                                 return 1;
250                         }
251                 }
252         }
253
254         return 0;
255 }
256
257 static int uniquename_unique_check(void *arg, const char *name)
258 {
259         struct {ListBase *lb; void *vlink; short name_offs;} *data= arg;
260         return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
261 }
262
263 void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short name_len)
264 {
265         struct {ListBase *lb; void *vlink; short name_offs;} data;
266         data.lb= list;
267         data.vlink= vlink;
268         data.name_offs= name_offs;
269
270         assert((name_len > 1) && (name_len <= UNIQUE_NAME_MAX));
271
272         /* See if we are given an empty string */
273         if (ELEM(NULL, vlink, defname))
274                 return;
275
276         BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
277 }
278
279
280
281 /* ******************** string encoding ***************** */
282
283 /* This is quite an ugly function... its purpose is to
284  * take the dir name, make it absolute, and clean it up, replacing
285  * excess file entry stuff (like /tmp/../tmp/../)
286  * note that dir isn't protected for max string names... 
287  * 
288  * If relbase is NULL then its ignored
289  */
290
291 void BLI_cleanup_dir(const char *relabase, char *dir)
292 {
293         BLI_cleanup_file(relabase, dir);
294         BLI_add_slash(dir);
295
296 }
297
298 void BLI_cleanup_file(const char *relabase, char *dir)
299 {
300         short a;
301         char *start, *eind;
302         if (relabase) {
303                 BLI_path_abs(dir, relabase);
304         } else {
305                 if (dir[0]=='/' && dir[1]=='/') {
306                         if (dir[2]== '\0') {
307                                 return; /* path is "//" - cant clean it */
308                         }
309                         dir = dir+2; /* skip the first // */
310                 }
311         }
312         
313         /* Note
314          *   memmove( start, eind, strlen(eind)+1 );
315          * is the same as
316          *   strcpy( start, eind ); 
317          * except strcpy should not be used because there is overlap,
318           * so use memmove's slightly more obscure syntax - Campbell
319          */
320         
321 #ifdef WIN32
322         
323         /* Note, this should really be moved to the file selector,
324          * since this function is used in many areas */
325         if(strcmp(dir, ".")==0) {       /* happens for example in FILE_MAIN */
326            get_default_root(dir);
327            return;
328         }       
329
330         while ( (start = strstr(dir, "\\..\\")) ) {
331                 eind = start + strlen("\\..\\") - 1;
332                 a = start-dir-1;
333                 while (a>0) {
334                         if (dir[a] == '\\') break;
335                         a--;
336                 }
337                 if (a<0) {
338                         break;
339                 } else {
340                         memmove( dir+a, eind, strlen(eind)+1 );
341                 }
342         }
343
344         while ( (start = strstr(dir,"\\.\\")) ){
345                 eind = start + strlen("\\.\\") - 1;
346                 memmove( start, eind, strlen(eind)+1 );
347         }
348
349         while ( (start = strstr(dir,"\\\\" )) ){
350                 eind = start + strlen("\\\\") - 1;
351                 memmove( start, eind, strlen(eind)+1 );
352         }
353
354         if((a = strlen(dir))){                          /* remove the '\\' at the end */
355                 while(a>0 && dir[a-1] == '\\'){
356                         a--;
357                         dir[a] = 0;
358                 }
359         }
360 #else
361         if(dir[0]=='.') {       /* happens, for example in FILE_MAIN */
362            dir[0]= '/';
363            dir[1]= 0;
364            return;
365         }
366
367         /* support for odd paths: eg /../home/me --> /home/me
368          * this is a valid path in blender but we cant handle this the useual way below
369          * simply strip this prefix then evaluate the path as useual. pythons os.path.normpath() does this */
370         while((strncmp(dir, "/../", 4)==0)) {
371                 memmove( dir, dir + 4, strlen(dir + 4) + 1 );
372         }
373
374         while ( (start = strstr(dir, "/../")) ) {
375                 eind = start + (4 - 1) /* strlen("/../") - 1 */;
376                 a = start-dir-1;
377                 while (a>0) {
378                         if (dir[a] == '/') break;
379                         a--;
380                 }
381                 if (a<0) {
382                         break;
383                 } else {
384                         memmove( dir+a, eind, strlen(eind)+1 );
385                 }
386         }
387
388         while ( (start = strstr(dir,"/./")) ){
389                 eind = start + (3 - 1) /* strlen("/./") - 1 */;
390                 memmove( start, eind, strlen(eind)+1 );
391         }
392
393         while ( (start = strstr(dir,"//" )) ){
394                 eind = start + (2 - 1) /* strlen("//") - 1 */;
395                 memmove( start, eind, strlen(eind)+1 );
396         }
397
398         if( (a = strlen(dir)) ){                                /* remove all '/' at the end */
399                 while(dir[a-1] == '/'){
400                         a--;
401                         dir[a] = 0;
402                         if (a<=0) break;
403                 }
404         }
405 #endif
406 }
407
408
409 void BLI_path_rel(char *file, const char *relfile)
410 {
411         char * lslash;
412         char temp[FILE_MAXDIR+FILE_MAXFILE];
413         char res[FILE_MAXDIR+FILE_MAXFILE];
414         
415         /* if file is already relative, bail out */
416         if(file[0]=='/' && file[1]=='/') return;
417         
418         /* also bail out if relative path is not set */
419         if (relfile[0] == 0) return;
420
421 #ifdef WIN32
422         if (BLI_strnlen(relfile, 3) > 2 && relfile[1] != ':') {
423                 char* ptemp;
424                 /* fix missing volume name in relative base,
425                    can happen with old recent-files.txt files */
426                 get_default_root(temp);
427                 ptemp = &temp[2];
428                 if (relfile[0] != '\\' && relfile[0] != '/') {
429                         ptemp++;
430                 }
431                 BLI_strncpy(ptemp, relfile, FILE_MAXDIR + FILE_MAXFILE-3);
432         } else {
433                 BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE);
434         }
435
436         if (BLI_strnlen(file, 3) > 2) {
437                 if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] )
438                         return;
439         }
440 #else
441         BLI_strncpy(temp, relfile, FILE_MAX);
442 #endif
443
444         BLI_char_switch(temp, '\\', '/');
445         BLI_char_switch(file, '\\', '/');
446         
447         /* remove /./ which confuse the following slash counting... */
448         BLI_cleanup_file(NULL, file);
449         BLI_cleanup_file(NULL, temp);
450         
451         /* the last slash in the file indicates where the path part ends */
452         lslash = BLI_last_slash(temp);
453
454         if (lslash) 
455         {       
456                 /* find the prefix of the filename that is equal for both filenames.
457                    This is replaced by the two slashes at the beginning */
458                 char *p= temp;
459                 char *q= file;
460
461                 while ((*p == *q)) {
462                         ++p; ++q;
463                         /* dont search beyond the end of the string
464                          * in the rare case they match */
465                         if ((*p=='\0') || (*q=='\0')) {
466                                 break;
467                         }
468                 }
469
470                 /* we might have passed the slash when the beginning of a dir matches 
471                    so we rewind. Only check on the actual filename
472                 */
473                 if (*q != '/') {
474                         while ( (q >= file) && (*q != '/') ) { --q; --p; }
475                 } 
476                 else if (*p != '/') {
477                         while ( (p >= temp) && (*p != '/') ) { --p; --q; }
478                 }
479                 
480                 strcpy(res,     "//");
481
482                 /* p now points to the slash that is at the beginning of the part
483                    where the path is different from the relative path. 
484                    We count the number of directories we need to go up in the
485                    hierarchy to arrive at the common 'prefix' of the path
486                 */                      
487                 while (p && p < lslash) {
488                         if (*p == '/') 
489                                 strcat(res,     "../");
490                         ++p;
491                 }
492
493                 strcat(res, q+1); /* don't copy the slash at the beginning */
494                 
495 #ifdef  WIN32
496                 BLI_char_switch(res+2, '/', '\\');
497 #endif
498                 strcpy(file, res);
499         }
500 }
501
502 int BLI_has_parent(char *path)
503 {
504         int len;
505         int slashes = 0;
506         BLI_clean(path);
507         len = BLI_add_slash(path) - 1;
508
509         while (len>=0) {
510                 if ((path[len] == '\\') || (path[len] == '/'))
511                         slashes++;
512                 len--;
513         }
514         return slashes > 1;
515 }
516
517 int BLI_parent_dir(char *path)
518 {
519         static char parent_dir[]= {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
520         char tmp[FILE_MAXDIR+FILE_MAXFILE+4];
521         BLI_strncpy(tmp, path, sizeof(tmp)-4);
522         BLI_add_slash(tmp);
523         strcat(tmp, parent_dir);
524         BLI_cleanup_dir(NULL, tmp);
525         
526         if (!BLI_testextensie(tmp, parent_dir)) {
527                 BLI_strncpy(path, tmp, sizeof(tmp));    
528                 return 1;
529         } else {
530                 return 0;
531         }
532 }
533
534 static int stringframe_chars(char *path, int *char_start, int *char_end)
535 {
536         int ch_sta, ch_end, i;
537         /* Insert current frame: file### -> file001 */
538         ch_sta = ch_end = 0;
539         for (i = 0; path[i] != '\0'; i++) {
540                 if (path[i] == '\\' || path[i] == '/') {
541                         ch_end = 0; /* this is a directory name, dont use any hashes we found */
542                 } else if (path[i] == '#') {
543                         ch_sta = i;
544                         ch_end = ch_sta+1;
545                         while (path[ch_end] == '#') {
546                                 ch_end++;
547                         }
548                         i = ch_end-1; /* keep searching */
549                         
550                         /* dont break, there may be a slash after this that invalidates the previous #'s */
551                 }
552         }
553
554         if(ch_end) {
555                 *char_start= ch_sta;
556                 *char_end= ch_end;
557                 return 1;
558         }
559         else {
560                 *char_start= -1;
561                 *char_end= -1;
562                 return 0;
563         }
564 }
565
566 static void ensure_digits(char *path, int digits)
567 {
568         char *file= BLI_last_slash(path);
569
570         if(file==NULL)
571                 file= path;
572
573         if(strrchr(file, '#') == NULL) {
574                 int len= strlen(file);
575
576                 while(digits--) {
577                         file[len++]= '#';
578                 }
579                 file[len]= '\0';
580         }
581 }
582
583 int BLI_path_frame(char *path, int frame, int digits)
584 {
585         int ch_sta, ch_end;
586
587         if(digits)
588                 ensure_digits(path, digits);
589
590         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
591                 char tmp[FILE_MAX];
592 #if 0   // neat but breaks on non ascii strings.
593                 char format[64];
594                 sprintf(format, "%%.%ds%%.%dd%%s", ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d%s" */
595                 sprintf(tmp, format, path, frame, path+ch_end);
596 #else
597                 char format[8];
598                 char *p;
599                 sprintf(format, "%%.%dd", ch_end-ch_sta); /* example result: "%.5d" */
600                 memcpy(tmp, path, sizeof(char) * ch_sta);
601                 p= tmp + ch_sta;
602                 p += sprintf(p, format, frame);
603                 memcpy(p, path + ch_end, strlen(path + ch_end));
604 #endif
605                 strcpy(path, tmp);
606                 return 1;
607         }
608         return 0;
609 }
610
611 int BLI_path_frame_range(char *path, int sta, int end, int digits)
612 {
613         int ch_sta, ch_end;
614
615         if(digits)
616                 ensure_digits(path, digits);
617
618         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
619                 char tmp[FILE_MAX], format[64];
620 #if 0   // neat but breaks on non ascii strings.
621                 sprintf(format, "%%.%ds%%.%dd_%%.%dd%%s", ch_sta, ch_end-ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d-%.5d%s" */
622                 sprintf(tmp, format, path, sta, end, path+ch_end);
623                 strcpy(path, tmp);
624 #else
625                 char *tmp_pt;
626                 BLI_snprintf(format, sizeof(format), "%%.%dd-%%.%dd%%s", digits, digits);
627                 memcpy(tmp, path, ch_sta * sizeof(char));
628                 tmp_pt = &tmp[ch_sta];
629                 tmp_pt += BLI_snprintf(tmp_pt, sizeof(tmp)-ch_sta, format, sta, end, &path[ch_end]);
630                 memcpy(path, tmp, (int)(tmp_pt - tmp) + 1);
631 #endif
632                 return 1;
633         }
634         return 0;
635 }
636
637 int BLI_path_abs(char *path, const char *basepath)
638 {
639         int wasrelative = (strncmp(path, "//", 2)==0);
640         char tmp[FILE_MAX];
641         char base[FILE_MAX];
642 #ifdef WIN32
643         char vol[3] = {'\0', '\0', '\0'};
644
645         BLI_strncpy(vol, path, 3);
646         /* we are checking here if we have an absolute path that is not in the current
647            blend file as a lib main - we are basically checking for the case that a 
648            UNIX root '/' is passed.
649         */
650         if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
651                 char *p = path;
652                 get_default_root(tmp);
653                 // get rid of the slashes at the beginning of the path
654                 while (*p == '\\' || *p == '/') {
655                         p++;
656                 }
657                 strcat(tmp, p);
658         }
659         else {
660                 BLI_strncpy(tmp, path, FILE_MAX);
661         }
662 #else
663         BLI_strncpy(tmp, path, sizeof(tmp));
664         
665         /* Check for loading a windows path on a posix system
666          * in this case, there is no use in trying C:/ since it 
667          * will never exist on a unix os.
668          * 
669          * Add a / prefix and lowercase the driveletter, remove the :
670          * C:\foo.JPG -> /c/foo.JPG */
671         
672         if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) {
673                 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
674                 tmp[0] = '/'; 
675                 /* '\' the slash will be converted later */
676         }
677         
678 #endif
679
680         BLI_strncpy(base, basepath, sizeof(base));
681         
682         BLI_cleanup_file(NULL, base);
683         
684         /* push slashes into unix mode - strings entering this part are
685            potentially messed up: having both back- and forward slashes.
686            Here we push into one conform direction, and at the end we
687            push them into the system specific dir. This ensures uniformity
688            of paths and solving some problems (and prevent potential future
689            ones) -jesterKing. */
690         BLI_char_switch(tmp, '\\', '/');
691         BLI_char_switch(base, '\\', '/');       
692
693         /* Paths starting with // will get the blend file as their base,
694          * this isnt standard in any os but is uesed in blender all over the place */
695         if (wasrelative) {
696                 char *lslash= BLI_last_slash(base);
697                 if (lslash) {
698                         int baselen= (int) (lslash-base) + 1;
699                         /* use path for temp storage here, we copy back over it right away */
700                         BLI_strncpy(path, tmp+2, FILE_MAX);
701                         
702                         memcpy(tmp, base, baselen);
703                         BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen);
704                         BLI_strncpy(path, tmp, FILE_MAX);
705                 } else {
706                         BLI_strncpy(path, tmp+2, FILE_MAX);
707                 }
708         } else {
709                 BLI_strncpy(path, tmp, FILE_MAX);
710         }
711         
712         if (path[0]!='\0') {
713                 if ( path[strlen(path)-1]=='/') {
714                         /* remove the '/' so we avoid BLI_cleanup_dir adding an extra \ in WIN32 */
715                         path[strlen(path)-1] = '\0';
716                         BLI_cleanup_dir(NULL, path);
717                 } else {
718                         BLI_cleanup_file(NULL, path);
719                 }
720         }
721         
722 #ifdef WIN32
723         /* skip first two chars, which in case of
724            absolute path will be drive:/blabla and
725            in case of relpath //blabla/. So relpath
726            // will be retained, rest will be nice and
727            shiny win32 backward slashes :) -jesterKing
728         */
729         BLI_char_switch(path+2, '/', '\\');
730 #endif
731         
732         return wasrelative;
733 }
734
735
736 /*
737  * Should only be done with command line paths.
738  * this is NOT somthing blenders internal paths support like the // prefix
739  */
740 int BLI_path_cwd(char *path)
741 {
742         int wasrelative = 1;
743         int filelen = strlen(path);
744         
745 #ifdef WIN32
746         if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
747                 wasrelative = 0;
748 #else
749         if (filelen >= 2 && path[0] == '/')
750                 wasrelative = 0;
751 #endif
752         
753         if (wasrelative==1) {
754                 char cwd[FILE_MAXDIR + FILE_MAXFILE];
755                 BLI_getwdN(cwd); /* incase the full path to the blend isnt used */
756                 
757                 if (cwd[0] == '\0') {
758                         printf( "Could not get the current working directory - $PWD for an unknown reason.");
759                 } else {
760                         /* uses the blend path relative to cwd important for loading relative linked files.
761                         *
762                         * cwd should contain c:\ etc on win32 so the relbase can be NULL
763                         * relbase being NULL also prevents // being misunderstood as relative to the current
764                         * blend file which isnt a feature we want to use in this case since were dealing
765                         * with a path from the command line, rather then from inside Blender */
766                         
767                         char origpath[FILE_MAXDIR + FILE_MAXFILE];
768                         BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE);
769                         
770                         BLI_make_file_string(NULL, path, cwd, origpath); 
771                 }
772         }
773         
774         return wasrelative;
775 }
776
777
778 /* 'di's filename component is moved into 'fi', di is made a dir path */
779 void BLI_splitdirstring(char *di, char *fi)
780 {
781         char *lslash= BLI_last_slash(di);
782
783         if (lslash) {
784                 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
785                 *(lslash+1)=0;
786         } else {
787                 BLI_strncpy(fi, di, FILE_MAXFILE);
788                 di[0]= 0;
789         }
790 }
791
792 void BLI_getlastdir(const char* dir, char *last, int maxlen)
793 {
794         const char *s = dir;
795         const char *lslash = NULL;
796         const char *prevslash = NULL;
797         while (*s) {
798                 if ((*s == '\\') || (*s == '/')) {
799                         prevslash = lslash;
800                         lslash = s;
801                 }
802                 s++;
803         }
804         if (prevslash) {
805                 BLI_strncpy(last, prevslash+1, maxlen);
806         } else {
807                 BLI_strncpy(last, dir, maxlen);
808         }
809 }
810
811 /* This is now only used to really get the user's default document folder */
812 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
813    as default location to save documents */
814 char *BLI_getDefaultDocumentFolder(void) {
815         #if !defined(WIN32)
816                 return getenv("HOME");
817
818         #else /* Windows */
819                 char * ret;
820                 static char documentfolder[MAXPATHLEN];
821                 HRESULT hResult;
822
823                 /* Check for %HOME% env var */
824
825                 ret = getenv("HOME");
826                 if(ret) {
827                         if (BLI_is_dir(ret)) return ret;
828                 }
829                                 
830                 /* add user profile support for WIN 2K / NT.
831                  * This is %APPDATA%, which translates to either
832                  * %USERPROFILE%\Application Data or since Vista
833                  * to %USERPROFILE%\AppData\Roaming
834                  */
835                 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
836                 
837                 if (hResult == S_OK)
838                 {
839                         if (BLI_is_dir(documentfolder)) return documentfolder;
840                 }
841                 
842                 return NULL;
843         #endif
844 }
845
846 /* NEW stuff, to be cleaned up when fully migrated */
847 /* ************************************************************* */
848 /* ************************************************************* */
849
850 // #define PATH_DEBUG2
851
852 static char *blender_version_decimal(void)
853 {
854         static char version_str[5];
855         sprintf(version_str, "%d.%02d", BLENDER_VERSION/100, BLENDER_VERSION%100);
856         return version_str;
857 }
858
859 static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
860 {
861         char tmppath[FILE_MAX];
862         
863         if(path_sep)    BLI_join_dirfile(tmppath, path_base, path_sep);
864         else                    BLI_strncpy(tmppath, path_base, sizeof(tmppath));
865         
866         BLI_make_file_string("/", targetpath, tmppath, folder_name);
867         
868         if (BLI_is_dir(targetpath)) {
869 #ifdef PATH_DEBUG2
870                 printf("\tpath found: %s\n", targetpath);
871 #endif
872                 return 1;
873         }
874         else {
875 #ifdef PATH_DEBUG2
876                 printf("\tpath missing: %s\n", targetpath);
877 #endif
878                 //targetpath[0] = '\0';
879                 return 0;
880         }
881 }
882
883 static int test_env_path(char *path, const char *envvar)
884 {
885         char *env = envvar?getenv(envvar):NULL;
886         if (!env) return 0;
887         
888         if (BLI_is_dir(env)) {
889                 BLI_strncpy(path, env, FILE_MAX);
890                 return 1;
891         } else {
892                 path[0] = '\0';
893                 return 0;
894         }
895 }
896
897 static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name)
898 {
899         char bprogdir[FILE_MAX];
900         char relfolder[FILE_MAX];
901         
902 #ifdef PATH_DEBUG2
903         printf("get_path_local...\n");
904 #endif
905         
906         if (subfolder_name) {
907                 BLI_join_dirfile(relfolder, folder_name, subfolder_name);
908         } else {
909                 BLI_strncpy(relfolder, folder_name, FILE_MAX);
910         }
911         
912         /* use argv[0] (bprogname) to get the path to the executable */
913         BLI_split_dirfile(bprogname, bprogdir, NULL);
914         
915         /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
916         if(test_path(targetpath, bprogdir, blender_version_decimal(), relfolder))
917                 return 1;
918
919         return 0;
920 }
921
922 static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar)
923 {
924         char user_path[FILE_MAX];
925         const char *user_base_path;
926         
927         user_path[0] = '\0';
928
929         if (test_env_path(user_path, envvar)) {
930                 if (subfolder_name) {
931                         return test_path(targetpath, user_path, NULL, subfolder_name);
932                 } else {
933                         BLI_strncpy(targetpath, user_path, FILE_MAX);
934                         return 1;
935                 }
936         }
937
938         user_base_path = (const char *)GHOST_getUserDir();
939         if (user_base_path) {
940                 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal());
941         }
942
943         if(!user_path[0])
944                 return 0;
945         
946 #ifdef PATH_DEBUG2
947         printf("get_path_user: %s\n", user_path);
948 #endif
949         
950         if (subfolder_name) {
951                 /* try $HOME/folder_name/subfolder_name */
952                 return test_path(targetpath, user_path, folder_name, subfolder_name);
953         } else {
954                 /* try $HOME/folder_name */
955                 return test_path(targetpath, user_path, NULL, folder_name);
956         }
957 }
958
959 static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar)
960 {
961         char system_path[FILE_MAX];
962         const char *system_base_path;
963
964
965         /* first allow developer only overrides to the system path
966          * these are only used when running blender from source */
967         char cwd[FILE_MAX];
968         char relfolder[FILE_MAX];
969         char bprogdir[FILE_MAX];
970
971         /* use argv[0] (bprogname) to get the path to the executable */
972         BLI_split_dirfile(bprogname, bprogdir, NULL);
973
974         if (subfolder_name) {
975                 BLI_join_dirfile(relfolder, folder_name, subfolder_name);
976         } else {
977                 BLI_strncpy(relfolder, folder_name, FILE_MAX);
978         }
979
980         /* try CWD/release/folder_name */
981         if(test_path(targetpath, BLI_getwdN(cwd), "release", relfolder))
982                 return 1;
983         
984         /* try EXECUTABLE_DIR/release/folder_name */
985         if(test_path(targetpath, bprogdir, "release", relfolder))
986                 return 1;
987         /* end developer overrides */
988
989
990
991         system_path[0] = '\0';
992
993         if (test_env_path(system_path, envvar)) {
994                 if (subfolder_name) {
995                         return test_path(targetpath, system_path, NULL, subfolder_name);
996                 } else {
997                         BLI_strncpy(targetpath, system_path, FILE_MAX);
998                         return 1;
999                 }
1000         }
1001
1002         system_base_path = (const char *)GHOST_getSystemDir();
1003         if (system_base_path) {
1004                 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal());
1005         }
1006         
1007         if(!system_path[0])
1008                 return 0;
1009         
1010 #ifdef PATH_DEBUG2
1011         printf("get_path_system: %s\n", system_path);
1012 #endif
1013         
1014         if (subfolder_name) {
1015                 /* try $BLENDERPATH/folder_name/subfolder_name */
1016                 return test_path(targetpath, system_path, folder_name, subfolder_name);
1017         } else {
1018                 /* try $BLENDERPATH/folder_name */
1019                 return test_path(targetpath, system_path, NULL, folder_name);
1020         }
1021 }
1022
1023 /* get a folder out of the 'folder_id' presets for paths */
1024 /* returns the path if found, NULL string if not */
1025 char *BLI_get_folder(int folder_id, const char *subfolder)
1026 {
1027         static char path[FILE_MAX] = "";
1028         
1029         switch (folder_id) {
1030                 case BLENDER_DATAFILES:         /* general case */
1031                         if (get_path_local(path, "datafiles", subfolder)) break;
1032                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
1033                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES")) break;
1034                         return NULL;
1035                         
1036                 case BLENDER_USER_DATAFILES:
1037                         if (get_path_local(path, "datafiles", subfolder)) break;
1038                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
1039                         return NULL;
1040                         
1041                 case BLENDER_SYSTEM_DATAFILES:
1042                         if (get_path_local(path, "datafiles", subfolder)) break;
1043                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES"))  break;
1044                         return NULL;
1045                         
1046                 case BLENDER_USER_AUTOSAVE:
1047                         if (get_path_local(path, "autosave", subfolder)) break;
1048                         if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES"))       break;
1049                         return NULL;
1050
1051                 case BLENDER_CONFIG:            /* general case */
1052                         if (get_path_local(path, "config", subfolder)) break;
1053                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
1054                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
1055                         return NULL;
1056                         
1057                 case BLENDER_USER_CONFIG:
1058                         if (get_path_local(path, "config", subfolder)) break;
1059                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
1060                         return NULL;
1061                         
1062                 case BLENDER_SYSTEM_CONFIG:
1063                         if (get_path_local(path, "config", subfolder)) break;
1064                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
1065                         return NULL;
1066                         
1067                 case BLENDER_SCRIPTS:           /* general case */
1068                         if (get_path_local(path, "scripts", subfolder)) break;
1069                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;           
1070                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1071                         return NULL;
1072                         
1073                 case BLENDER_USER_SCRIPTS:
1074                         if (get_path_local(path, "scripts", subfolder)) break;
1075                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;
1076                         return NULL;
1077                         
1078                 case BLENDER_SYSTEM_SCRIPTS:
1079                         if (get_path_local(path, "scripts", subfolder)) break;
1080                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1081                         return NULL;
1082                         
1083                 case BLENDER_PYTHON:            /* general case */
1084                         if (get_path_local(path, "python", subfolder)) break;
1085                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1086                         return NULL;
1087                         
1088                 case BLENDER_SYSTEM_PYTHON:
1089                         if (get_path_local(path, "python", subfolder)) break;
1090                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1091                         return NULL;
1092         }
1093         
1094         return path;
1095 }
1096
1097 char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
1098 {
1099         static char path[FILE_MAX] = "";
1100
1101         switch (folder_id) {
1102                 case BLENDER_USER_DATAFILES:
1103                         get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES");
1104                         break;
1105                 case BLENDER_USER_CONFIG:
1106                         get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG");
1107                         break;
1108                 case BLENDER_USER_AUTOSAVE:
1109                         get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE");
1110                         break;
1111                 case BLENDER_USER_SCRIPTS:
1112                         get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS");
1113                         break;
1114         }
1115         if ('\0' == path[0]) {
1116                 return NULL;
1117         }
1118         return path;
1119 }
1120
1121 char *BLI_get_folder_create(int folder_id, const char *subfolder)
1122 {
1123         char *path;
1124
1125         /* only for user folders */
1126         if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1127                 return NULL;
1128         
1129         path = BLI_get_folder(folder_id, subfolder);
1130         
1131         if (!path) {
1132                 path = BLI_get_user_folder_notest(folder_id, subfolder);
1133                 if (path) BLI_recurdir_fileops(path);
1134         }
1135         
1136         return path;
1137 }
1138
1139
1140 /* End new stuff */
1141 /* ************************************************************* */
1142 /* ************************************************************* */
1143
1144
1145
1146 #ifdef PATH_DEBUG
1147 #undef PATH_DEBUG
1148 #endif
1149
1150 void BLI_setenv(const char *env, const char*val)
1151 {
1152         /* SGI or free windows */
1153 #if (defined(__sgi) || ((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 */
1155
1156         sprintf(envstr, "%s=%s", env, val);
1157         putenv(envstr);
1158         MEM_freeN(envstr);
1159
1160         /* non-free windows */
1161 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1162         _putenv_s(env, val);
1163 #else
1164         /* linux/osx/bsd */
1165         setenv(env, val, 1);
1166 #endif
1167 }
1168
1169
1170 /**
1171  Only set an env var if already not there.
1172  Like Unix setenv(env, val, 0);
1173  */
1174 void BLI_setenv_if_new(const char *env, const char* val)
1175 {
1176         if(getenv(env) == NULL)
1177                 BLI_setenv(env, val);
1178 }
1179
1180
1181 void BLI_clean(char *path)
1182 {
1183         if(path==0) return;
1184
1185 #ifdef WIN32
1186         if(path && BLI_strnlen(path, 3) > 2) {
1187                 BLI_char_switch(path+2, '/', '\\');
1188         }
1189 #else
1190         BLI_char_switch(path, '\\', '/');
1191 #endif
1192 }
1193
1194 void BLI_char_switch(char *string, char from, char to) 
1195 {
1196         if(string==0) return;
1197         while (*string != 0) {
1198                 if (*string == from) *string = to;
1199                 string++;
1200         }
1201 }
1202
1203 void BLI_make_exist(char *dir) {
1204         int a;
1205
1206         BLI_char_switch(dir, ALTSEP, SEP);
1207
1208         a = strlen(dir);
1209
1210         while(BLI_is_dir(dir) == 0){
1211                 a --;
1212                 while(dir[a] != SEP){
1213                         a--;
1214                         if (a <= 0) break;
1215                 }
1216                 if (a >= 0) {
1217                         dir[a+1] = '\0';
1218                 }
1219                 else {
1220 #ifdef WIN32
1221                         get_default_root(dir);
1222 #else
1223                         strcpy(dir,"/");
1224 #endif
1225                         break;
1226                 }
1227         }
1228 }
1229
1230 void BLI_make_existing_file(const char *name)
1231 {
1232         char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1233
1234         BLI_strncpy(di, name, sizeof(di));
1235         BLI_splitdirstring(di, fi);
1236         
1237         /* test exist */
1238         if (BLI_exists(di) == 0) {
1239                 BLI_recurdir_fileops(di);
1240         }
1241 }
1242
1243
1244 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1245 {
1246         int sl;
1247
1248         if (!string || !dir || !file) return; /* We don't want any NULLs */
1249         
1250         string[0]= 0; /* ton */
1251
1252         /* we first push all slashes into unix mode, just to make sure we don't get
1253            any mess with slashes later on. -jesterKing */
1254         /* constant strings can be passed for those parameters - don't change them - elubie */
1255         /*
1256         BLI_char_switch(relabase, '\\', '/');
1257         BLI_char_switch(dir, '\\', '/');
1258         BLI_char_switch(file, '\\', '/');
1259         */
1260
1261         /* Resolve relative references */       
1262         if (relabase && dir[0] == '/' && dir[1] == '/') {
1263                 char *lslash;
1264                 
1265                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1266                 strcpy(string, relabase);
1267                 
1268                 lslash= BLI_last_slash(string);
1269                 if(lslash) *(lslash+1)= 0;
1270
1271                 dir+=2; /* Skip over the relative reference */
1272         }
1273 #ifdef WIN32
1274         else {
1275                 if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':' ) {
1276                         BLI_strncpy(string, dir, 3);
1277                         dir += 2;
1278                 }
1279                 else { /* no drive specified */
1280                         /* first option: get the drive from the relabase if it has one */
1281                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1282                                 BLI_strncpy(string, relabase, 3);       
1283                                 string[2] = '\\';
1284                                 string[3] = '\0';
1285                         }
1286                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1287                                 get_default_root(string);
1288                         }
1289                         
1290                         /* ignore leading slashes */
1291                         while (*dir == '/' || *dir == '\\') dir++;
1292                 }
1293         }
1294 #endif
1295
1296         strcat(string, dir);
1297
1298         /* Make sure string ends in one (and only one) slash */ 
1299         /* first trim all slashes from the end of the string */
1300         sl = strlen(string);
1301         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1302                 string[sl-1] = '\0';
1303                 sl--;
1304         }
1305         /* since we've now removed all slashes, put back one slash at the end. */
1306         strcat(string, "/");
1307         
1308         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1309                 file++;
1310                 
1311         strcat (string, file);
1312         
1313         /* Push all slashes to the system preferred direction */
1314         BLI_clean(string);
1315 }
1316
1317 int BLI_testextensie(const char *str, const char *ext)
1318 {
1319         short a, b;
1320         int retval;
1321
1322         a= strlen(str);
1323         b= strlen(ext);
1324
1325         if(a==0 || b==0 || b>=a) {
1326                 retval = 0;
1327         } else if (BLI_strcasecmp(ext, str + a - b)) {
1328                 retval = 0;     
1329         } else {
1330                 retval = 1;
1331         }
1332
1333         return (retval);
1334 }
1335
1336 int BLI_testextensie_array(const char *str, const char **ext_array)
1337 {
1338         int i=0;
1339         while(ext_array[i]) {
1340                 if(BLI_testextensie(str, ext_array[i])) {
1341                         return 1;
1342                 }
1343
1344                 i++;
1345         }
1346         return 0;
1347 }
1348
1349 /* semicolon separated wildcards, eg:
1350  *  '*.zip;*.py;*.exe' */
1351 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1352 {
1353         const char *ext_step= ext_fnmatch;
1354         char pattern[16];
1355
1356         while(ext_step[0]) {
1357                 char *ext_next;
1358                 int len_ext;
1359
1360                 if((ext_next=strchr(ext_step, ';'))) {
1361                         len_ext= (int)(ext_next - ext_step) + 1;
1362                 }
1363                 else {
1364                         len_ext= sizeof(pattern);
1365                 }
1366
1367                 BLI_strncpy(pattern, ext_step, len_ext);
1368
1369                 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1370                         return 1;
1371                 }
1372                 ext_step += len_ext;
1373         }
1374
1375         return 0;
1376 }
1377
1378
1379 int BLI_replace_extension(char *path, int maxlen, const char *ext)
1380 {
1381         int a;
1382
1383         for(a=strlen(path)-1; a>=0; a--)
1384                 if(path[a] == '.' || path[a] == '/' || path[a] == '\\')
1385                         break;
1386         
1387         if(path[a] != '.')
1388                 a= strlen(path);
1389
1390         if(a + strlen(ext) >= maxlen)
1391                 return 0;
1392
1393         strcpy(path+a, ext);
1394         return 1;
1395 }
1396
1397 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1398  * - wont change 'string'
1399  * - wont create any directories
1400  * - dosnt use CWD, or deal with relative paths.
1401  * - Only fill's in *dir and *file when they are non NULL
1402  * */
1403 void BLI_split_dirfile(const char *string, char *dir, char *file)
1404 {
1405         char *lslash_str = BLI_last_slash(string);
1406         int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0;
1407
1408         if (dir) {
1409                 if (lslash) {
1410                         BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */
1411                 } else {
1412                         dir[0] = '\0';
1413                 }
1414         }
1415         
1416         if (file) {
1417                 strcpy( file, string+lslash);
1418         }
1419 }
1420
1421 /* simple appending of filename to dir, does not check for valid path! */
1422 void BLI_join_dirfile(char *string, const char *dir, const char *file)
1423 {
1424         int sl_dir;
1425         
1426         if(string != dir) /* compare pointers */
1427                 BLI_strncpy(string, dir, FILE_MAX);
1428
1429         if (!file)
1430                 return;
1431         
1432         sl_dir= BLI_add_slash(string);
1433         
1434         if (sl_dir <FILE_MAX) {
1435                 BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
1436         }
1437 }
1438
1439 /* like pythons os.path.basename( ) */
1440 char *BLI_path_basename(char *path)
1441 {
1442         char *filename= BLI_last_slash(path);
1443         return filename ? filename + 1 : path;
1444 }
1445
1446 /*
1447   Produce image export path.
1448
1449   Fails returning 0 if image filename is empty or if destination path
1450   matches image path (i.e. both are the same file).
1451
1452   Trailing slash in dest_dir is optional.
1453
1454   Logic:
1455
1456   - if an image is "below" current .blend file directory, rebuild the
1457         same dir structure in dest_dir
1458
1459   For example //textures/foo/bar.png becomes
1460   [dest_dir]/textures/foo/bar.png.
1461
1462   - if an image is not "below" current .blend file directory,
1463   disregard it's path and copy it in the same directory where 3D file
1464   goes.
1465
1466   For example //../foo/bar.png becomes [dest_dir]/bar.png.
1467
1468   This logic will help ensure that all image paths are relative and
1469   that a user gets his images in one place. It'll also provide
1470   consistent behaviour across exporters.
1471  */
1472 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)
1473 {
1474         char path[FILE_MAX];
1475         char dir[FILE_MAX];
1476         char base[FILE_MAX];
1477         char blend_dir[FILE_MAX];       /* directory, where current .blend file resides */
1478         char dest_path[FILE_MAX];
1479         char rel_dir[FILE_MAX];
1480         int len;
1481
1482         if (abs)
1483                 abs[0]= 0;
1484
1485         if (rel)
1486                 rel[0]= 0;
1487
1488         BLI_split_dirfile(base_dir, blend_dir, NULL);
1489
1490         if (src_dir[0]=='\0')
1491                 return 0;
1492
1493         BLI_strncpy(path, src_dir, sizeof(path));
1494
1495         /* expand "//" in filename and get absolute path */
1496         BLI_path_abs(path, base_dir);
1497
1498         /* get the directory part */
1499         BLI_split_dirfile(path, dir, base);
1500
1501         len= strlen(blend_dir);
1502
1503         rel_dir[0] = 0;
1504
1505         /* if image is "below" current .blend file directory */
1506         if (!strncmp(path, blend_dir, len)) {
1507
1508                 /* if image is _in_ current .blend file directory */
1509                 if (!strcmp(dir, blend_dir)) {
1510                         BLI_join_dirfile(dest_path, dest_dir, base);
1511                 }
1512                 /* "below" */
1513                 else {
1514                         /* rel = image_path_dir - blend_dir */
1515                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1516
1517                         BLI_join_dirfile(dest_path, dest_dir, rel_dir);
1518                         BLI_join_dirfile(dest_path, dest_path, base);
1519                 }
1520
1521         }
1522         /* image is out of current directory */
1523         else {
1524                 BLI_join_dirfile(dest_path, dest_dir, base);
1525         }
1526
1527         if (abs)
1528                 BLI_strncpy(abs, dest_path, abs_size);
1529
1530         if (rel) {
1531                 strncat(rel, rel_dir, rel_size);
1532                 strncat(rel, base, rel_size);
1533         }
1534
1535         /* return 2 if src=dest */
1536         if (!strcmp(path, dest_path)) {
1537                 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1538                 return 2;
1539         }
1540
1541         return 1;
1542 }
1543
1544 char *BLI_first_slash(char *string) {
1545         char *ffslash, *fbslash;
1546         
1547         ffslash= strchr(string, '/');   
1548         fbslash= strchr(string, '\\');
1549         
1550         if (!ffslash) return fbslash;
1551         else if (!fbslash) return ffslash;
1552         
1553         if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1554         else return fbslash;
1555 }
1556
1557 char *BLI_last_slash(const char *string) {
1558         char *lfslash, *lbslash;
1559         
1560         lfslash= strrchr(string, '/');  
1561         lbslash= strrchr(string, '\\');
1562
1563         if (!lfslash) return lbslash; 
1564         else if (!lbslash) return lfslash;
1565         
1566         if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1567         else return lfslash;
1568 }
1569
1570 /* adds a slash if there isnt one there already */
1571 int BLI_add_slash(char *string) {
1572         int len = strlen(string);
1573 #ifdef WIN32
1574         if (len==0 || string[len-1]!='\\') {
1575                 string[len] = '\\';
1576                 string[len+1] = '\0';
1577                 return len+1;
1578         }
1579 #else
1580         if (len==0 || string[len-1]!='/') {
1581                 string[len] = '/';
1582                 string[len+1] = '\0';
1583                 return len+1;
1584         }
1585 #endif
1586         return len;
1587 }
1588
1589 /* removes a slash if there is one */
1590 void BLI_del_slash(char *string) {
1591         int len = strlen(string);
1592         while (len) {
1593 #ifdef WIN32
1594                 if (string[len-1]=='\\') {
1595 #else
1596                 if (string[len-1]=='/') {
1597 #endif
1598                         string[len-1] = '\0';
1599                         len--;
1600                 } else {
1601                         break;
1602                 }
1603         }
1604 }
1605
1606 static int add_win32_extension(char *name)
1607 {
1608         int retval = 0;
1609         int type;
1610
1611         type = BLI_exist(name);
1612         if ((type == 0) || S_ISDIR(type)) {
1613 #ifdef _WIN32
1614                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1615                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1616                 char *extensions = getenv("PATHEXT");
1617                 if (extensions) {
1618                         char *temp;
1619                         do {
1620                                 strcpy(filename, name);
1621                                 temp = strstr(extensions, ";");
1622                                 if (temp) {
1623                                         strncpy(ext, extensions, temp - extensions);
1624                                         ext[temp - extensions] = 0;
1625                                         extensions = temp + 1;
1626                                         strcat(filename, ext);
1627                                 } else {
1628                                         strcat(filename, extensions);
1629                                 }
1630
1631                                 type = BLI_exist(filename);
1632                                 if (type && (! S_ISDIR(type))) {
1633                                         retval = 1;
1634                                         strcpy(name, filename);
1635                                         break;
1636                                 }
1637                         } while (temp);
1638                 }
1639 #endif
1640         } else {
1641                 retval = 1;
1642         }
1643
1644         return (retval);
1645 }
1646
1647 void BLI_where_am_i(char *fullname, const char *name)
1648 {
1649         char filename[FILE_MAXDIR+FILE_MAXFILE];
1650         char *path = NULL, *temp;
1651         
1652 #ifdef _WIN32
1653         const char *separator = ";";
1654         char slash = '\\';
1655 #else
1656         const char *separator = ":";
1657         char slash = '/';
1658 #endif
1659
1660         
1661 #ifdef __linux__
1662         /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1663         path = br_find_exe( NULL );
1664         if (path) {
1665                 BLI_strncpy(fullname, path, FILE_MAXDIR+FILE_MAXFILE);
1666                 free(path);
1667                 return;
1668         }
1669 #endif
1670
1671 #ifdef _WIN32
1672         if(GetModuleFileName(0, fullname, FILE_MAXDIR+FILE_MAXFILE)) {
1673                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1674                 return;
1675         }
1676 #endif
1677
1678         /* unix and non linux */
1679         if (name && fullname && strlen(name)) {
1680                 strcpy(fullname, name);
1681                 if (name[0] == '.') {
1682                         // relative path, prepend cwd
1683                         BLI_getwdN(fullname);
1684                         
1685                         // not needed but avoids annoying /./ in name
1686                         if(name && name[0]=='.' && name[1]==slash)
1687                                 BLI_join_dirfile(fullname, fullname, name+2);
1688                         else
1689                                 BLI_join_dirfile(fullname, fullname, name);
1690                         
1691                         add_win32_extension(fullname);
1692                 } else if (BLI_last_slash(name)) {
1693                         // full path
1694                         strcpy(fullname, name);
1695                         add_win32_extension(fullname);
1696                 } else {
1697                         // search for binary in $PATH
1698                         path = getenv("PATH");
1699                         if (path) {
1700                                 do {
1701                                         temp = strstr(path, separator);
1702                                         if (temp) {
1703                                                 strncpy(filename, path, temp - path);
1704                                                 filename[temp - path] = 0;
1705                                                 path = temp + 1;
1706                                         } else {
1707                                                 strncpy(filename, path, sizeof(filename));
1708                                         }
1709                                         BLI_join_dirfile(fullname, fullname, name);
1710                                         if (add_win32_extension(filename)) {
1711                                                 strcpy(fullname, filename);
1712                                                 break;
1713                                         }
1714                                 } while (temp);
1715                         }
1716                 }
1717 #if defined(DEBUG)
1718                 if (strcmp(name, fullname)) {
1719                         printf("guessing '%s' == '%s'\n", name, fullname);
1720                 }
1721 #endif
1722
1723 #ifdef _WIN32
1724                 // in windows change long filename to short filename because
1725                 // win2k doesn't know how to parse a commandline with lots of
1726                 // spaces and double-quotes. There's another solution to this
1727                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1728                 // that's even uglier
1729                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1730 #if defined(DEBUG)
1731                 printf("Shortname = '%s'\n", fullname);
1732 #endif
1733 #endif
1734         }
1735 }
1736
1737 void BLI_where_is_temp(char *fullname, int usertemp)
1738 {
1739         fullname[0] = '\0';
1740         
1741         if (usertemp && BLI_is_dir(U.tempdir)) {
1742                 strcpy(fullname, U.tempdir);
1743         }
1744         
1745         
1746 #ifdef WIN32
1747         if (fullname[0] == '\0') {
1748                 char *tmp = getenv("TEMP"); /* Windows */
1749                 if (tmp && BLI_is_dir(tmp)) {
1750                         strcpy(fullname, tmp);
1751                 }
1752         }
1753 #else
1754         /* Other OS's - Try TMP and TMPDIR */
1755         if (fullname[0] == '\0') {
1756                 char *tmp = getenv("TMP");
1757                 if (tmp && BLI_is_dir(tmp)) {
1758                         strcpy(fullname, tmp);
1759                 }
1760         }
1761         
1762         if (fullname[0] == '\0') {
1763                 char *tmp = getenv("TMPDIR");
1764                 if (tmp && BLI_is_dir(tmp)) {
1765                         strcpy(fullname, tmp);
1766                 }
1767         }
1768 #endif  
1769         
1770         if (fullname[0] == '\0') {
1771                 strcpy(fullname, "/tmp/");
1772         } else {
1773                 /* add a trailing slash if needed */
1774                 BLI_add_slash(fullname);
1775 #ifdef WIN32
1776                 strcpy(U.tempdir, fullname); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1777 #endif
1778         }
1779 }
1780
1781 char *get_install_dir(void) {
1782         char *tmpname = BLI_strdup(bprogname);
1783         char *cut;
1784
1785 #ifdef __APPLE__
1786         cut = strstr(tmpname, ".app");
1787         if (cut) cut[0] = 0;
1788 #endif
1789
1790         cut = BLI_last_slash(tmpname);
1791
1792         if (cut) {
1793                 cut[0] = 0;
1794                 return tmpname;
1795         } else {
1796                 MEM_freeN(tmpname);
1797                 return NULL;
1798         }
1799 }
1800
1801 #ifdef WITH_ICONV
1802
1803 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1804 {
1805         size_t inbytesleft=strlen(original);
1806         size_t outbytesleft=512;
1807         size_t rv=0;
1808         iconv_t cd;
1809         
1810         if (NULL == code) {
1811                 code = locale_charset();
1812         }
1813         cd=iconv_open("UTF-8", code);
1814
1815         if (cd == (iconv_t)(-1)) {
1816                 printf("iconv_open Error");
1817                 *utf_8='\0';
1818                 return ;
1819         }
1820         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1821         if (rv == (size_t) -1) {
1822                 printf("iconv Error\n");
1823                 return ;
1824         }
1825         *utf_8 = '\0';
1826         iconv_close(cd);
1827 }
1828 #endif // WITH_ICONV
1829
1830