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