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