Stupid error in commit to allow .blend1 and .blend2 being dropped in
[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 /* if ext is .blend*, it doesn't compare last char */
1319 int BLI_testextensie(const char *str, const char *ext)
1320 {
1321         short a, b;
1322         int retval= 0;
1323         
1324         a= strlen(str);
1325         b= strlen(ext);
1326         
1327         if(a==0 || b==0 || b>=a) {
1328                 retval = 0;
1329         }
1330         else {
1331                 /* allow .blend1 .blend2 */
1332                 char *loc= BLI_strcasestr(str+a-b-1, ext);
1333                 
1334                 if(loc)
1335                         retval= 1;
1336         }
1337         
1338         return (retval);
1339 }
1340
1341 int BLI_testextensie_array(const char *str, const char **ext_array)
1342 {
1343         int i=0;
1344         while(ext_array[i]) {
1345                 if(BLI_testextensie(str, ext_array[i])) {
1346                         return 1;
1347                 }
1348
1349                 i++;
1350         }
1351         return 0;
1352 }
1353
1354 /* semicolon separated wildcards, eg:
1355  *  '*.zip;*.py;*.exe' */
1356 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1357 {
1358         const char *ext_step= ext_fnmatch;
1359         char pattern[16];
1360
1361         while(ext_step[0]) {
1362                 char *ext_next;
1363                 int len_ext;
1364
1365                 if((ext_next=strchr(ext_step, ';'))) {
1366                         len_ext= (int)(ext_next - ext_step) + 1;
1367                 }
1368                 else {
1369                         len_ext= sizeof(pattern);
1370                 }
1371
1372                 BLI_strncpy(pattern, ext_step, len_ext);
1373
1374                 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1375                         return 1;
1376                 }
1377                 ext_step += len_ext;
1378         }
1379
1380         return 0;
1381 }
1382
1383
1384 int BLI_replace_extension(char *path, int maxlen, const char *ext)
1385 {
1386         int a;
1387
1388         for(a=strlen(path)-1; a>=0; a--)
1389                 if(path[a] == '.' || path[a] == '/' || path[a] == '\\')
1390                         break;
1391         
1392         if(path[a] != '.')
1393                 a= strlen(path);
1394
1395         if(a + strlen(ext) >= maxlen)
1396                 return 0;
1397
1398         strcpy(path+a, ext);
1399         return 1;
1400 }
1401
1402 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1403  * - wont change 'string'
1404  * - wont create any directories
1405  * - dosnt use CWD, or deal with relative paths.
1406  * - Only fill's in *dir and *file when they are non NULL
1407  * */
1408 void BLI_split_dirfile(const char *string, char *dir, char *file)
1409 {
1410         char *lslash_str = BLI_last_slash(string);
1411         int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0;
1412
1413         if (dir) {
1414                 if (lslash) {
1415                         BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */
1416                 } else {
1417                         dir[0] = '\0';
1418                 }
1419         }
1420         
1421         if (file) {
1422                 strcpy( file, string+lslash);
1423         }
1424 }
1425
1426 /* simple appending of filename to dir, does not check for valid path! */
1427 void BLI_join_dirfile(char *string, const char *dir, const char *file)
1428 {
1429         int sl_dir;
1430         
1431         if(string != dir) /* compare pointers */
1432                 BLI_strncpy(string, dir, FILE_MAX);
1433
1434         if (!file)
1435                 return;
1436         
1437         sl_dir= BLI_add_slash(string);
1438         
1439         if (sl_dir <FILE_MAX) {
1440                 BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
1441         }
1442 }
1443
1444 /* like pythons os.path.basename( ) */
1445 char *BLI_path_basename(char *path)
1446 {
1447         char *filename= BLI_last_slash(path);
1448         return filename ? filename + 1 : path;
1449 }
1450
1451 /*
1452   Produce image export path.
1453
1454   Fails returning 0 if image filename is empty or if destination path
1455   matches image path (i.e. both are the same file).
1456
1457   Trailing slash in dest_dir is optional.
1458
1459   Logic:
1460
1461   - if an image is "below" current .blend file directory, rebuild the
1462         same dir structure in dest_dir
1463
1464   For example //textures/foo/bar.png becomes
1465   [dest_dir]/textures/foo/bar.png.
1466
1467   - if an image is not "below" current .blend file directory,
1468   disregard it's path and copy it in the same directory where 3D file
1469   goes.
1470
1471   For example //../foo/bar.png becomes [dest_dir]/bar.png.
1472
1473   This logic will help ensure that all image paths are relative and
1474   that a user gets his images in one place. It'll also provide
1475   consistent behaviour across exporters.
1476  */
1477 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)
1478 {
1479         char path[FILE_MAX];
1480         char dir[FILE_MAX];
1481         char base[FILE_MAX];
1482         char blend_dir[FILE_MAX];       /* directory, where current .blend file resides */
1483         char dest_path[FILE_MAX];
1484         char rel_dir[FILE_MAX];
1485         int len;
1486
1487         if (abs)
1488                 abs[0]= 0;
1489
1490         if (rel)
1491                 rel[0]= 0;
1492
1493         BLI_split_dirfile(base_dir, blend_dir, NULL);
1494
1495         if (src_dir[0]=='\0')
1496                 return 0;
1497
1498         BLI_strncpy(path, src_dir, sizeof(path));
1499
1500         /* expand "//" in filename and get absolute path */
1501         BLI_path_abs(path, base_dir);
1502
1503         /* get the directory part */
1504         BLI_split_dirfile(path, dir, base);
1505
1506         len= strlen(blend_dir);
1507
1508         rel_dir[0] = 0;
1509
1510         /* if image is "below" current .blend file directory */
1511         if (!strncmp(path, blend_dir, len)) {
1512
1513                 /* if image is _in_ current .blend file directory */
1514                 if (!strcmp(dir, blend_dir)) {
1515                         BLI_join_dirfile(dest_path, dest_dir, base);
1516                 }
1517                 /* "below" */
1518                 else {
1519                         /* rel = image_path_dir - blend_dir */
1520                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1521
1522                         BLI_join_dirfile(dest_path, dest_dir, rel_dir);
1523                         BLI_join_dirfile(dest_path, dest_path, base);
1524                 }
1525
1526         }
1527         /* image is out of current directory */
1528         else {
1529                 BLI_join_dirfile(dest_path, dest_dir, base);
1530         }
1531
1532         if (abs)
1533                 BLI_strncpy(abs, dest_path, abs_size);
1534
1535         if (rel) {
1536                 strncat(rel, rel_dir, rel_size);
1537                 strncat(rel, base, rel_size);
1538         }
1539
1540         /* return 2 if src=dest */
1541         if (!strcmp(path, dest_path)) {
1542                 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1543                 return 2;
1544         }
1545
1546         return 1;
1547 }
1548
1549 char *BLI_first_slash(char *string) {
1550         char *ffslash, *fbslash;
1551         
1552         ffslash= strchr(string, '/');   
1553         fbslash= strchr(string, '\\');
1554         
1555         if (!ffslash) return fbslash;
1556         else if (!fbslash) return ffslash;
1557         
1558         if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1559         else return fbslash;
1560 }
1561
1562 char *BLI_last_slash(const char *string) {
1563         char *lfslash, *lbslash;
1564         
1565         lfslash= strrchr(string, '/');  
1566         lbslash= strrchr(string, '\\');
1567
1568         if (!lfslash) return lbslash; 
1569         else if (!lbslash) return lfslash;
1570         
1571         if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1572         else return lfslash;
1573 }
1574
1575 /* adds a slash if there isnt one there already */
1576 int BLI_add_slash(char *string) {
1577         int len = strlen(string);
1578 #ifdef WIN32
1579         if (len==0 || string[len-1]!='\\') {
1580                 string[len] = '\\';
1581                 string[len+1] = '\0';
1582                 return len+1;
1583         }
1584 #else
1585         if (len==0 || string[len-1]!='/') {
1586                 string[len] = '/';
1587                 string[len+1] = '\0';
1588                 return len+1;
1589         }
1590 #endif
1591         return len;
1592 }
1593
1594 /* removes a slash if there is one */
1595 void BLI_del_slash(char *string) {
1596         int len = strlen(string);
1597         while (len) {
1598 #ifdef WIN32
1599                 if (string[len-1]=='\\') {
1600 #else
1601                 if (string[len-1]=='/') {
1602 #endif
1603                         string[len-1] = '\0';
1604                         len--;
1605                 } else {
1606                         break;
1607                 }
1608         }
1609 }
1610
1611 static int add_win32_extension(char *name)
1612 {
1613         int retval = 0;
1614         int type;
1615
1616         type = BLI_exist(name);
1617         if ((type == 0) || S_ISDIR(type)) {
1618 #ifdef _WIN32
1619                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1620                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1621                 char *extensions = getenv("PATHEXT");
1622                 if (extensions) {
1623                         char *temp;
1624                         do {
1625                                 strcpy(filename, name);
1626                                 temp = strstr(extensions, ";");
1627                                 if (temp) {
1628                                         strncpy(ext, extensions, temp - extensions);
1629                                         ext[temp - extensions] = 0;
1630                                         extensions = temp + 1;
1631                                         strcat(filename, ext);
1632                                 } else {
1633                                         strcat(filename, extensions);
1634                                 }
1635
1636                                 type = BLI_exist(filename);
1637                                 if (type && (! S_ISDIR(type))) {
1638                                         retval = 1;
1639                                         strcpy(name, filename);
1640                                         break;
1641                                 }
1642                         } while (temp);
1643                 }
1644 #endif
1645         } else {
1646                 retval = 1;
1647         }
1648
1649         return (retval);
1650 }
1651
1652 void BLI_where_am_i(char *fullname, const char *name)
1653 {
1654         char filename[FILE_MAXDIR+FILE_MAXFILE];
1655         char *path = NULL, *temp;
1656         
1657 #ifdef _WIN32
1658         const char *separator = ";";
1659         char slash = '\\';
1660 #else
1661         const char *separator = ":";
1662         char slash = '/';
1663 #endif
1664
1665         
1666 #ifdef __linux__
1667         /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1668         path = br_find_exe( NULL );
1669         if (path) {
1670                 BLI_strncpy(fullname, path, FILE_MAXDIR+FILE_MAXFILE);
1671                 free(path);
1672                 return;
1673         }
1674 #endif
1675
1676 #ifdef _WIN32
1677         if(GetModuleFileName(0, fullname, FILE_MAXDIR+FILE_MAXFILE)) {
1678                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1679                 return;
1680         }
1681 #endif
1682
1683         /* unix and non linux */
1684         if (name && fullname && strlen(name)) {
1685                 strcpy(fullname, name);
1686                 if (name[0] == '.') {
1687                         // relative path, prepend cwd
1688                         BLI_getwdN(fullname);
1689                         
1690                         // not needed but avoids annoying /./ in name
1691                         if(name && name[0]=='.' && name[1]==slash)
1692                                 BLI_join_dirfile(fullname, fullname, name+2);
1693                         else
1694                                 BLI_join_dirfile(fullname, fullname, name);
1695                         
1696                         add_win32_extension(fullname);
1697                 } else if (BLI_last_slash(name)) {
1698                         // full path
1699                         strcpy(fullname, name);
1700                         add_win32_extension(fullname);
1701                 } else {
1702                         // search for binary in $PATH
1703                         path = getenv("PATH");
1704                         if (path) {
1705                                 do {
1706                                         temp = strstr(path, separator);
1707                                         if (temp) {
1708                                                 strncpy(filename, path, temp - path);
1709                                                 filename[temp - path] = 0;
1710                                                 path = temp + 1;
1711                                         } else {
1712                                                 strncpy(filename, path, sizeof(filename));
1713                                         }
1714                                         BLI_join_dirfile(fullname, fullname, name);
1715                                         if (add_win32_extension(filename)) {
1716                                                 strcpy(fullname, filename);
1717                                                 break;
1718                                         }
1719                                 } while (temp);
1720                         }
1721                 }
1722 #if defined(DEBUG)
1723                 if (strcmp(name, fullname)) {
1724                         printf("guessing '%s' == '%s'\n", name, fullname);
1725                 }
1726 #endif
1727
1728 #ifdef _WIN32
1729                 // in windows change long filename to short filename because
1730                 // win2k doesn't know how to parse a commandline with lots of
1731                 // spaces and double-quotes. There's another solution to this
1732                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1733                 // that's even uglier
1734                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1735 #if defined(DEBUG)
1736                 printf("Shortname = '%s'\n", fullname);
1737 #endif
1738 #endif
1739         }
1740 }
1741
1742 void BLI_where_is_temp(char *fullname, int usertemp)
1743 {
1744         fullname[0] = '\0';
1745         
1746         if (usertemp && BLI_is_dir(U.tempdir)) {
1747                 strcpy(fullname, U.tempdir);
1748         }
1749         
1750         
1751 #ifdef WIN32
1752         if (fullname[0] == '\0') {
1753                 char *tmp = getenv("TEMP"); /* Windows */
1754                 if (tmp && BLI_is_dir(tmp)) {
1755                         strcpy(fullname, tmp);
1756                 }
1757         }
1758 #else
1759         /* Other OS's - Try TMP and TMPDIR */
1760         if (fullname[0] == '\0') {
1761                 char *tmp = getenv("TMP");
1762                 if (tmp && BLI_is_dir(tmp)) {
1763                         strcpy(fullname, tmp);
1764                 }
1765         }
1766         
1767         if (fullname[0] == '\0') {
1768                 char *tmp = getenv("TMPDIR");
1769                 if (tmp && BLI_is_dir(tmp)) {
1770                         strcpy(fullname, tmp);
1771                 }
1772         }
1773 #endif  
1774         
1775         if (fullname[0] == '\0') {
1776                 strcpy(fullname, "/tmp/");
1777         } else {
1778                 /* add a trailing slash if needed */
1779                 BLI_add_slash(fullname);
1780 #ifdef WIN32
1781                 strcpy(U.tempdir, fullname); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1782 #endif
1783         }
1784 }
1785
1786 char *get_install_dir(void) {
1787         char *tmpname = BLI_strdup(bprogname);
1788         char *cut;
1789
1790 #ifdef __APPLE__
1791         cut = strstr(tmpname, ".app");
1792         if (cut) cut[0] = 0;
1793 #endif
1794
1795         cut = BLI_last_slash(tmpname);
1796
1797         if (cut) {
1798                 cut[0] = 0;
1799                 return tmpname;
1800         } else {
1801                 MEM_freeN(tmpname);
1802                 return NULL;
1803         }
1804 }
1805
1806 #ifdef WITH_ICONV
1807
1808 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1809 {
1810         size_t inbytesleft=strlen(original);
1811         size_t outbytesleft=512;
1812         size_t rv=0;
1813         iconv_t cd;
1814         
1815         if (NULL == code) {
1816                 code = locale_charset();
1817         }
1818         cd=iconv_open("UTF-8", code);
1819
1820         if (cd == (iconv_t)(-1)) {
1821                 printf("iconv_open Error");
1822                 *utf_8='\0';
1823                 return ;
1824         }
1825         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1826         if (rv == (size_t) -1) {
1827                 printf("iconv Error\n");
1828                 return ;
1829         }
1830         *utf_8 = '\0';
1831         iconv_close(cd);
1832 }
1833 #endif // WITH_ICONV
1834
1835