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