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