f57ac09c9b92bb68c61104935a50477a7805d48e
[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_listBase.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 static char bprogname[FILE_MAX];        /* path to program executable */
91 static char bprogdir[FILE_MAX];         /* path in which executable is located */
92 static char btempdir[FILE_MAX];         /* temporary directory */
93
94 static int add_win32_extension(char *name);
95 static char *blender_version_decimal(const int ver);
96
97 /* implementation */
98
99 int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
100 {
101         unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0;
102         short i, found = 0;
103         char *lslash = BLI_last_slash(string);
104         len2 = len = strlen(string);
105         if(lslash)
106                 lenlslash= (int)(lslash - string);
107
108         while(len > lenlslash && string[--len] != '.') {};
109         if(len == lenlslash && string[len] != '.') len = len2;
110
111         for (i = len - 1; i >= lenlslash; i--) {
112                 if (isdigit(string[i])) {
113                         if (found){
114                                 nums = i;
115                         }
116                         else{
117                                 nume = i;
118                                 nums = i;
119                                 found = 1;
120                         }
121                 }
122                 else {
123                         if (found) break;
124                 }
125         }
126         if (found) {
127                 if (tail) strcpy(tail, &string[nume+1]);
128                 if (head) {
129                         strcpy(head,string);
130                         head[nums]=0;
131                 }
132                 if (numlen) *numlen = nume-nums+1;
133                 return ((int)atoi(&(string[nums])));
134         }
135         if (tail) strcpy(tail, string + len);
136         if (head) {
137                 strncpy(head, string, len);
138                 head[len] = '\0';
139         }
140         if (numlen) *numlen=0;
141         return 0;
142 }
143
144
145 void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
146 {
147         char fmtstr[16]="";
148         if(pic < 0) pic= 0;
149         sprintf(fmtstr, "%%s%%.%dd%%s", numlen);
150         sprintf(string, fmtstr, head, pic, tail);
151 }
152
153 /* Foo.001 -> "Foo", 1
154  * Returns the length of "Foo" */
155 int BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
156 {
157         int a;
158
159         *nr= 0;
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(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 {
792         #if !defined(WIN32)
793                 return getenv("HOME");
794
795         #else /* Windows */
796                 const char * ret;
797                 static char documentfolder[MAXPATHLEN];
798                 HRESULT hResult;
799
800                 /* Check for %HOME% env var */
801
802                 ret = getenv("HOME");
803                 if(ret) {
804                         if (BLI_is_dir(ret)) return ret;
805                 }
806                                 
807                 /* add user profile support for WIN 2K / NT.
808                  * This is %APPDATA%, which translates to either
809                  * %USERPROFILE%\Application Data or since Vista
810                  * to %USERPROFILE%\AppData\Roaming
811                  */
812                 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
813                 
814                 if (hResult == S_OK)
815                 {
816                         if (BLI_is_dir(documentfolder)) return documentfolder;
817                 }
818                 
819                 return NULL;
820         #endif
821 }
822
823 /* NEW stuff, to be cleaned up when fully migrated */
824 /* ************************************************************* */
825 /* ************************************************************* */
826
827 // #define PATH_DEBUG2
828
829 static char *blender_version_decimal(const int ver)
830 {
831         static char version_str[5];
832         sprintf(version_str, "%d.%02d", ver/100, ver%100);
833         return version_str;
834 }
835
836 static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
837 {
838         char tmppath[FILE_MAX];
839         
840         if(path_sep)    BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
841         else                    BLI_strncpy(tmppath, path_base, sizeof(tmppath));
842
843         /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
844         if(folder_name)
845                 BLI_make_file_string("/", targetpath, tmppath, folder_name);
846         else
847                 BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
848
849         if (BLI_is_dir(targetpath)) {
850 #ifdef PATH_DEBUG2
851                 printf("\tpath found: %s\n", targetpath);
852 #endif
853                 return 1;
854         }
855         else {
856 #ifdef PATH_DEBUG2
857                 printf("\tpath missing: %s\n", targetpath);
858 #endif
859                 //targetpath[0] = '\0';
860                 return 0;
861         }
862 }
863
864 static int test_env_path(char *path, const char *envvar)
865 {
866         const char *env = envvar?getenv(envvar):NULL;
867         if (!env) return 0;
868         
869         if (BLI_is_dir(env)) {
870                 BLI_strncpy(path, env, FILE_MAX);
871                 return 1;
872         } else {
873                 path[0] = '\0';
874                 return 0;
875         }
876 }
877
878 static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
879 {
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         /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
898         if(test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder))
899                 return 1;
900
901         return 0;
902 }
903
904 static int is_portable_install(void)
905 {
906         /* detect portable install by the existance of config folder */
907         const int ver= BLENDER_VERSION;
908         char path[FILE_MAX];
909
910         return get_path_local(path, "config", NULL, ver);
911 }
912
913 static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
914 {
915         char user_path[FILE_MAX];
916         const char *user_base_path;
917
918         /* for portable install, user path is always local */
919         if (is_portable_install())
920                 return get_path_local(targetpath, folder_name, subfolder_name, ver);
921         
922         user_path[0] = '\0';
923
924         if (test_env_path(user_path, envvar)) {
925                 if (subfolder_name) {
926                         return test_path(targetpath, user_path, NULL, subfolder_name);
927                 } else {
928                         BLI_strncpy(targetpath, user_path, FILE_MAX);
929                         return 1;
930                 }
931         }
932
933         user_base_path = (const char *)GHOST_getUserDir();
934         if (user_base_path) {
935                 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal(ver));
936         }
937
938         if(!user_path[0])
939                 return 0;
940         
941 #ifdef PATH_DEBUG2
942         printf("get_path_user: %s\n", user_path);
943 #endif
944         
945         if (subfolder_name) {
946                 /* try $HOME/folder_name/subfolder_name */
947                 return test_path(targetpath, user_path, folder_name, subfolder_name);
948         } else {
949                 /* try $HOME/folder_name */
950                 return test_path(targetpath, user_path, NULL, folder_name);
951         }
952 }
953
954 static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
955 {
956         char system_path[FILE_MAX];
957         const char *system_base_path;
958
959
960         /* first allow developer only overrides to the system path
961          * these are only used when running blender from source */
962         char cwd[FILE_MAX];
963         char relfolder[FILE_MAX];
964
965         if(folder_name) {
966                 if (subfolder_name) {
967                         BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
968                 } else {
969                         BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
970                 }
971         }
972         else {
973                 relfolder[0]= '\0';
974         }
975
976         /* try CWD/release/folder_name */
977         if(BLI_getwdN(cwd, sizeof(cwd))) {
978                 if(test_path(targetpath, cwd, "release", relfolder)) {
979                         return 1;
980                 }
981         }
982
983         /* try EXECUTABLE_DIR/release/folder_name */
984         if(test_path(targetpath, bprogdir, "release", relfolder))
985                 return 1;
986         /* end developer overrides */
987
988
989
990         system_path[0] = '\0';
991
992         if (test_env_path(system_path, envvar)) {
993                 if (subfolder_name) {
994                         return test_path(targetpath, system_path, NULL, subfolder_name);
995                 } else {
996                         BLI_strncpy(targetpath, system_path, FILE_MAX);
997                         return 1;
998                 }
999         }
1000
1001         system_base_path = (const char *)GHOST_getSystemDir();
1002         if (system_base_path) {
1003                 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal(ver));
1004         }
1005         
1006         if(!system_path[0])
1007                 return 0;
1008         
1009 #ifdef PATH_DEBUG2
1010         printf("get_path_system: %s\n", system_path);
1011 #endif
1012         
1013         if (subfolder_name) {
1014                 /* try $BLENDERPATH/folder_name/subfolder_name */
1015                 return test_path(targetpath, system_path, folder_name, subfolder_name);
1016         } else {
1017                 /* try $BLENDERPATH/folder_name */
1018                 return test_path(targetpath, system_path, NULL, folder_name);
1019         }
1020 }
1021
1022 /* get a folder out of the 'folder_id' presets for paths */
1023 /* returns the path if found, NULL string if not */
1024 char *BLI_get_folder(int folder_id, const char *subfolder)
1025 {
1026         const int ver= BLENDER_VERSION;
1027         static char path[FILE_MAX] = "";
1028         
1029         switch (folder_id) {
1030                 case BLENDER_DATAFILES:         /* general case */
1031                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1032                         if (get_path_local(path, "datafiles", subfolder, ver)) break;
1033                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
1034                         return NULL;
1035                         
1036                 case BLENDER_USER_DATAFILES:
1037                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1038                         return NULL;
1039                         
1040                 case BLENDER_SYSTEM_DATAFILES:
1041                         if (get_path_local(path, "datafiles", subfolder, ver)) break;
1042                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver))     break;
1043                         return NULL;
1044                         
1045                 case BLENDER_USER_AUTOSAVE:
1046                         if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver))  break;
1047                         return NULL;
1048
1049                 case BLENDER_USER_CONFIG:
1050                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
1051                         return NULL;
1052                         
1053                 case BLENDER_USER_SCRIPTS:
1054                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
1055                         return NULL;
1056                         
1057                 case BLENDER_SYSTEM_SCRIPTS:
1058                         if (get_path_local(path, "scripts", subfolder, ver)) break;
1059                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
1060                         return NULL;
1061                         
1062                 case BLENDER_SYSTEM_PYTHON:
1063                         if (get_path_local(path, "python", subfolder, ver)) break;
1064                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
1065                         return NULL;
1066         }
1067         
1068         return path;
1069 }
1070
1071 char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
1072 {
1073         const int ver= BLENDER_VERSION;
1074         static char path[FILE_MAX] = "";
1075
1076         switch (folder_id) {
1077                 case BLENDER_USER_DATAFILES:
1078                         get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
1079                         break;
1080                 case BLENDER_USER_CONFIG:
1081                         get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
1082                         break;
1083                 case BLENDER_USER_AUTOSAVE:
1084                         get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
1085                         break;
1086                 case BLENDER_USER_SCRIPTS:
1087                         get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
1088                         break;
1089         }
1090         if ('\0' == path[0]) {
1091                 return NULL;
1092         }
1093         return path;
1094 }
1095
1096 char *BLI_get_folder_create(int folder_id, const char *subfolder)
1097 {
1098         char *path;
1099
1100         /* only for user folders */
1101         if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1102                 return NULL;
1103         
1104         path = BLI_get_folder(folder_id, subfolder);
1105         
1106         if (!path) {
1107                 path = BLI_get_user_folder_notest(folder_id, subfolder);
1108                 if (path) BLI_recurdir_fileops(path);
1109         }
1110         
1111         return path;
1112 }
1113
1114 char *BLI_get_folder_version(const int id, const int ver, const int do_check)
1115 {
1116         static char path[FILE_MAX] = "";
1117         int ok;
1118         switch(id) {
1119         case BLENDER_RESOURCE_PATH_USER:
1120                 ok= get_path_user(path, NULL, NULL, NULL, ver);
1121                 break;
1122         case BLENDER_RESOURCE_PATH_LOCAL:
1123                 ok= get_path_local(path, NULL, NULL, ver);
1124                 break;
1125         case BLENDER_RESOURCE_PATH_SYSTEM:
1126                 ok= get_path_system(path, NULL, NULL, NULL, ver);
1127                 break;
1128         default:
1129                 path[0]= '\0'; /* incase do_check is false */
1130                 ok= FALSE;
1131                 BLI_assert(!"incorrect ID");
1132         }
1133
1134         if((ok == FALSE) && do_check) {
1135                 return NULL;
1136         }
1137
1138         return path;
1139 }
1140
1141 /* End new stuff */
1142 /* ************************************************************* */
1143 /* ************************************************************* */
1144
1145
1146
1147 #ifdef PATH_DEBUG
1148 #undef PATH_DEBUG
1149 #endif
1150
1151 void BLI_setenv(const char *env, const char*val)
1152 {
1153         /* free windows */
1154 #if (defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)
1155         char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1156
1157         sprintf(envstr, "%s=%s", env, val);
1158         putenv(envstr);
1159         MEM_freeN(envstr);
1160
1161         /* non-free windows */
1162 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1163         _putenv_s(env, val);
1164 #else
1165         /* linux/osx/bsd */
1166         setenv(env, val, 1);
1167 #endif
1168 }
1169
1170
1171 /**
1172  Only set an env var if already not there.
1173  Like Unix setenv(env, val, 0);
1174  */
1175 void BLI_setenv_if_new(const char *env, const char* val)
1176 {
1177         if(getenv(env) == NULL)
1178                 BLI_setenv(env, val);
1179 }
1180
1181
1182 void BLI_clean(char *path)
1183 {
1184         if(path==NULL) return;
1185
1186 #ifdef WIN32
1187         if(path && BLI_strnlen(path, 3) > 2) {
1188                 BLI_char_switch(path+2, '/', '\\');
1189         }
1190 #else
1191         BLI_char_switch(path, '\\', '/');
1192 #endif
1193 }
1194
1195 void BLI_char_switch(char *string, char from, char to) 
1196 {
1197         if(string==NULL) return;
1198         while (*string != 0) {
1199                 if (*string == from) *string = to;
1200                 string++;
1201         }
1202 }
1203
1204 void BLI_make_exist(char *dir)
1205 {
1206         int a;
1207
1208         BLI_char_switch(dir, ALTSEP, SEP);
1209
1210         a = strlen(dir);
1211
1212         while(BLI_is_dir(dir) == 0){
1213                 a --;
1214                 while(dir[a] != SEP){
1215                         a--;
1216                         if (a <= 0) break;
1217                 }
1218                 if (a >= 0) {
1219                         dir[a+1] = '\0';
1220                 }
1221                 else {
1222 #ifdef WIN32
1223                         get_default_root(dir);
1224 #else
1225                         strcpy(dir,"/");
1226 #endif
1227                         break;
1228                 }
1229         }
1230 }
1231
1232 void BLI_make_existing_file(const char *name)
1233 {
1234         char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1235
1236         BLI_strncpy(di, name, sizeof(di));
1237         BLI_splitdirstring(di, fi);
1238         
1239         /* test exist */
1240         if (BLI_exists(di) == 0) {
1241                 BLI_recurdir_fileops(di);
1242         }
1243 }
1244
1245
1246 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1247 {
1248         int sl;
1249
1250         if (!string || !dir || !file) return; /* We don't want any NULLs */
1251         
1252         string[0]= 0; /* ton */
1253
1254         /* we first push all slashes into unix mode, just to make sure we don't get
1255            any mess with slashes later on. -jesterKing */
1256         /* constant strings can be passed for those parameters - don't change them - elubie */
1257         /*
1258         BLI_char_switch(relabase, '\\', '/');
1259         BLI_char_switch(dir, '\\', '/');
1260         BLI_char_switch(file, '\\', '/');
1261         */
1262
1263         /* Resolve relative references */       
1264         if (relabase && dir[0] == '/' && dir[1] == '/') {
1265                 char *lslash;
1266                 
1267                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1268                 strcpy(string, relabase);
1269                 
1270                 lslash= BLI_last_slash(string);
1271                 if(lslash) *(lslash+1)= 0;
1272
1273                 dir+=2; /* Skip over the relative reference */
1274         }
1275 #ifdef WIN32
1276         else {
1277                 if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':' ) {
1278                         BLI_strncpy(string, dir, 3);
1279                         dir += 2;
1280                 }
1281                 else { /* no drive specified */
1282                         /* first option: get the drive from the relabase if it has one */
1283                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1284                                 BLI_strncpy(string, relabase, 3);       
1285                                 string[2] = '\\';
1286                                 string[3] = '\0';
1287                         }
1288                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1289                                 get_default_root(string);
1290                         }
1291                         
1292                         /* ignore leading slashes */
1293                         while (*dir == '/' || *dir == '\\') dir++;
1294                 }
1295         }
1296 #endif
1297
1298         strcat(string, dir);
1299
1300         /* Make sure string ends in one (and only one) slash */ 
1301         /* first trim all slashes from the end of the string */
1302         sl = strlen(string);
1303         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1304                 string[sl-1] = '\0';
1305                 sl--;
1306         }
1307         /* since we've now removed all slashes, put back one slash at the end. */
1308         strcat(string, "/");
1309         
1310         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1311                 file++;
1312                 
1313         strcat (string, file);
1314         
1315         /* Push all slashes to the system preferred direction */
1316         BLI_clean(string);
1317 }
1318
1319 int BLI_testextensie(const char *str, const char *ext)
1320 {
1321         short a, b;
1322         int retval;
1323         
1324         a= strlen(str);
1325         b= strlen(ext);
1326         
1327         if(a==0 || b==0 || b>=a) {
1328                 retval = 0;
1329         } else if (BLI_strcasecmp(ext, str + a - b)) {
1330                 retval = 0;     
1331         } else {
1332                 retval = 1;
1333         }
1334         
1335         return (retval);
1336 }
1337
1338 int BLI_testextensie_array(const char *str, const char **ext_array)
1339 {
1340         int i=0;
1341         while(ext_array[i]) {
1342                 if(BLI_testextensie(str, ext_array[i])) {
1343                         return 1;
1344                 }
1345
1346                 i++;
1347         }
1348         return 0;
1349 }
1350
1351 /* semicolon separated wildcards, eg:
1352  *  '*.zip;*.py;*.exe' */
1353 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1354 {
1355         const char *ext_step= ext_fnmatch;
1356         char pattern[16];
1357
1358         while(ext_step[0]) {
1359                 char *ext_next;
1360                 int len_ext;
1361
1362                 if((ext_next=strchr(ext_step, ';'))) {
1363                         len_ext= (int)(ext_next - ext_step) + 1;
1364                 }
1365                 else {
1366                         len_ext= sizeof(pattern);
1367                 }
1368
1369                 BLI_strncpy(pattern, ext_step, len_ext);
1370
1371                 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1372                         return 1;
1373                 }
1374                 ext_step += len_ext;
1375         }
1376
1377         return 0;
1378 }
1379
1380
1381 int BLI_replace_extension(char *path, size_t maxlen, const char *ext)
1382 {
1383         size_t a;
1384
1385         for(a=strlen(path); a>0; a--) {
1386                 if(path[a-1] == '.' || path[a-1] == '/' || path[a-1] == '\\') {
1387                         a--;
1388                         break;
1389                 }
1390         }
1391         
1392         if(path[a] != '.')
1393                 a= strlen(path);
1394
1395         if(a + strlen(ext) >= maxlen)
1396                 return 0;
1397
1398         strcpy(path+a, ext);
1399         return 1;
1400 }
1401
1402 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1403  * - wont change 'string'
1404  * - wont create any directories
1405  * - dosnt use CWD, or deal with relative paths.
1406  * - Only fill's in *dir and *file when they are non NULL
1407  * */
1408 void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
1409 {
1410         char *lslash_str = BLI_last_slash(string);
1411         size_t lslash= lslash_str ? (size_t)(lslash_str - string) + 1 : 0;
1412
1413         if (dir) {
1414                 if (lslash) {
1415                         BLI_strncpy( dir, string, MIN2(dirlen, lslash + 1)); /* +1 to include the slash and the last char */
1416                 }
1417                 else {
1418                         dir[0] = '\0';
1419                 }
1420         }
1421         
1422         if (file) {
1423                 BLI_strncpy(file, string+lslash, filelen);
1424         }
1425 }
1426
1427 void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen)
1428 {
1429         BLI_split_dirfile(string, dir, NULL, dirlen, 0);
1430 }
1431
1432 void BLI_split_file_part(const char *string, char *file, const size_t filelen)
1433 {
1434         BLI_split_dirfile(string, NULL, file, 0, filelen);
1435 }
1436
1437 /* simple appending of filename to dir, does not check for valid path! */
1438 void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const char *file)
1439 {
1440         size_t dirlen= BLI_strnlen(dir, maxlen);
1441
1442         if (dst != dir) {
1443                 if(dirlen  == maxlen) {
1444                         memcpy(dst, dir, dirlen);
1445                         dst[dirlen - 1]= '\0';
1446                         return; /* dir fills the path */
1447                 }
1448                 else {
1449                         memcpy(dst, dir, dirlen + 1);
1450                 }
1451         }
1452
1453         if (dirlen + 1 >= maxlen) {
1454                 return; /* fills the path */
1455         }
1456
1457         /* inline BLI_add_slash */
1458         if (dst[dirlen - 1] != SEP) {
1459                 dst[dirlen++]= SEP;
1460                 dst[dirlen  ]= '\0';
1461         }
1462
1463         if (dirlen >= maxlen) {
1464                 return; /* fills the path */
1465         }
1466
1467         if (file == NULL) {
1468                 return;
1469         }
1470
1471         BLI_strncpy(dst + dirlen, file, maxlen - dirlen);
1472 }
1473
1474 /* like pythons os.path.basename( ) */
1475 char *BLI_path_basename(char *path)
1476 {
1477         char *filename= BLI_last_slash(path);
1478         return filename ? filename + 1 : path;
1479 }
1480
1481 /*
1482   Produce image export path.
1483
1484   Fails returning 0 if image filename is empty or if destination path
1485   matches image path (i.e. both are the same file).
1486
1487   Trailing slash in dest_dir is optional.
1488
1489   Logic:
1490
1491   - if an image is "below" current .blend file directory, rebuild the
1492         same dir structure in dest_dir
1493
1494   For example //textures/foo/bar.png becomes
1495   [dest_dir]/textures/foo/bar.png.
1496
1497   - if an image is not "below" current .blend file directory,
1498   disregard it's path and copy it in the same directory where 3D file
1499   goes.
1500
1501   For example //../foo/bar.png becomes [dest_dir]/bar.png.
1502
1503   This logic will help ensure that all image paths are relative and
1504   that a user gets his images in one place. It'll also provide
1505   consistent behaviour across exporters.
1506  */
1507 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)
1508 {
1509         char path[FILE_MAX];
1510         char dir[FILE_MAX];
1511         char base[FILE_MAX];
1512         char blend_dir[FILE_MAX];       /* directory, where current .blend file resides */
1513         char dest_path[FILE_MAX];
1514         char rel_dir[FILE_MAX];
1515         int len;
1516
1517         if (abs)
1518                 abs[0]= 0;
1519
1520         if (rel)
1521                 rel[0]= 0;
1522
1523         BLI_split_dir_part(base_dir, blend_dir, sizeof(blend_dir));
1524
1525         if (src_dir[0]=='\0')
1526                 return 0;
1527
1528         BLI_strncpy(path, src_dir, sizeof(path));
1529
1530         /* expand "//" in filename and get absolute path */
1531         BLI_path_abs(path, base_dir);
1532
1533         /* get the directory part */
1534         BLI_split_dirfile(path, dir, base, sizeof(dir), sizeof(base));
1535
1536         len= strlen(blend_dir);
1537
1538         rel_dir[0] = 0;
1539
1540         /* if image is "below" current .blend file directory */
1541         if (!strncmp(path, blend_dir, len)) {
1542
1543                 /* if image is _in_ current .blend file directory */
1544                 if (BLI_path_cmp(dir, blend_dir) == 0) {
1545                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1546                 }
1547                 /* "below" */
1548                 else {
1549                         /* rel = image_path_dir - blend_dir */
1550                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1551
1552                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir);
1553                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base);
1554                 }
1555
1556         }
1557         /* image is out of current directory */
1558         else {
1559                 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1560         }
1561
1562         if (abs)
1563                 BLI_strncpy(abs, dest_path, abs_len);
1564
1565         if (rel) {
1566                 strncat(rel, rel_dir, rel_len);
1567                 strncat(rel, base, rel_len);
1568         }
1569
1570         /* return 2 if src=dest */
1571         if (BLI_path_cmp(path, dest_path) == 0) {
1572                 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1573                 return 2;
1574         }
1575
1576         return 1;
1577 }
1578
1579 char *BLI_first_slash(char *string)
1580 {
1581         char *ffslash, *fbslash;
1582         
1583         ffslash= strchr(string, '/');   
1584         fbslash= strchr(string, '\\');
1585         
1586         if (!ffslash) return fbslash;
1587         else if (!fbslash) return ffslash;
1588         
1589         if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1590         else return fbslash;
1591 }
1592
1593 char *BLI_last_slash(const char *string)
1594 {
1595         char *lfslash, *lbslash;
1596         
1597         lfslash= strrchr(string, '/');  
1598         lbslash= strrchr(string, '\\');
1599
1600         if (!lfslash) return lbslash; 
1601         else if (!lbslash) return lfslash;
1602         
1603         if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1604         else return lfslash;
1605 }
1606
1607 /* adds a slash if there isnt one there already */
1608 int BLI_add_slash(char *string)
1609 {
1610         int len = strlen(string);
1611         if (len==0 || string[len-1] != SEP) {
1612                 string[len] = SEP;
1613                 string[len+1] = '\0';
1614                 return len+1;
1615         }
1616         return len;
1617 }
1618
1619 /* removes a slash if there is one */
1620 void BLI_del_slash(char *string)
1621 {
1622         int len = strlen(string);
1623         while (len) {
1624                 if (string[len-1] == SEP) {
1625                         string[len-1] = '\0';
1626                         len--;
1627                 } else {
1628                         break;
1629                 }
1630         }
1631 }
1632
1633 static int add_win32_extension(char *name)
1634 {
1635         int retval = 0;
1636         int type;
1637
1638         type = BLI_exist(name);
1639         if ((type == 0) || S_ISDIR(type)) {
1640 #ifdef _WIN32
1641                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1642                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1643                 const char *extensions = getenv("PATHEXT");
1644                 if (extensions) {
1645                         char *temp;
1646                         do {
1647                                 strcpy(filename, name);
1648                                 temp = strstr(extensions, ";");
1649                                 if (temp) {
1650                                         strncpy(ext, extensions, temp - extensions);
1651                                         ext[temp - extensions] = 0;
1652                                         extensions = temp + 1;
1653                                         strcat(filename, ext);
1654                                 } else {
1655                                         strcat(filename, extensions);
1656                                 }
1657
1658                                 type = BLI_exist(filename);
1659                                 if (type && (! S_ISDIR(type))) {
1660                                         retval = 1;
1661                                         strcpy(name, filename);
1662                                         break;
1663                                 }
1664                         } while (temp);
1665                 }
1666 #endif
1667         } else {
1668                 retval = 1;
1669         }
1670
1671         return (retval);
1672 }
1673
1674 /*
1675 * Checks if name is a fully qualified filename to an executable.
1676 * If not it searches $PATH for the file. On Windows it also
1677 * adds the correct extension (.com .exe etc) from
1678 * $PATHEXT if necessary. Also on Windows it translates
1679 * the name to its 8.3 version to prevent problems with
1680 * spaces and stuff. Final result is returned in fullname.
1681 *
1682 * @param fullname The full path and full name of the executable
1683 * (must be FILE_MAX minimum)
1684 * @param name The name of the executable (usually argv[0]) to be checked
1685 */
1686 static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name)
1687 {
1688         char filename[FILE_MAXDIR+FILE_MAXFILE];
1689         const char *path = NULL, *temp;
1690
1691 #ifdef _WIN32
1692         const char *separator = ";";
1693 #else
1694         const char *separator = ":";
1695 #endif
1696
1697         
1698 #ifdef WITH_BINRELOC
1699         /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
1700         path = br_find_exe( NULL );
1701         if (path) {
1702                 BLI_strncpy(fullname, path, maxlen);
1703                 free((void *)path);
1704                 return;
1705         }
1706 #endif
1707
1708 #ifdef _WIN32
1709         if(GetModuleFileName(0, fullname, maxlen)) {
1710                 if(!BLI_exists(fullname)) {
1711                         printf("path can't be found: \"%.*s\"\n", maxlen, fullname);
1712                         MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
1713                 }
1714                 return;
1715         }
1716 #endif
1717
1718         /* unix and non linux */
1719         if (name && name[0]) {
1720                 BLI_strncpy(fullname, name, maxlen);
1721                 if (name[0] == '.') {
1722                         char wdir[FILE_MAX]= "";
1723                         BLI_getwdN(wdir, sizeof(wdir));  /* backup cwd to restore after */
1724
1725                         // not needed but avoids annoying /./ in name
1726                         if(name[1]==SEP)
1727                                 BLI_join_dirfile(fullname, maxlen, wdir, name+2);
1728                         else
1729                                 BLI_join_dirfile(fullname, maxlen, wdir, name);
1730
1731                         add_win32_extension(fullname); /* XXX, doesnt respect length */
1732                 }
1733                 else if (BLI_last_slash(name)) {
1734                         // full path
1735                         BLI_strncpy(fullname, name, maxlen);
1736                         add_win32_extension(fullname);
1737                 } else {
1738                         // search for binary in $PATH
1739                         path = getenv("PATH");
1740                         if (path) {
1741                                 do {
1742                                         temp = strstr(path, separator);
1743                                         if (temp) {
1744                                                 strncpy(filename, path, temp - path);
1745                                                 filename[temp - path] = 0;
1746                                                 path = temp + 1;
1747                                         } else {
1748                                                 strncpy(filename, path, sizeof(filename));
1749                                         }
1750                                         BLI_join_dirfile(fullname, maxlen, fullname, name);
1751                                         if (add_win32_extension(filename)) {
1752                                                 BLI_strncpy(fullname, filename, maxlen);
1753                                                 break;
1754                                         }
1755                                 } while (temp);
1756                         }
1757                 }
1758 #if defined(DEBUG)
1759                 if (strcmp(name, fullname)) {
1760                         printf("guessing '%s' == '%s'\n", name, fullname);
1761                 }
1762 #endif
1763         }
1764 }
1765
1766 void BLI_init_program_path(const char *argv0)
1767 {
1768         bli_where_am_i(bprogname, sizeof(bprogname), argv0);
1769         BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir));
1770 }
1771
1772 const char *BLI_program_path(void)
1773 {
1774         return bprogname;
1775 }
1776
1777 const char *BLI_program_dir(void)
1778 {
1779         return bprogdir;
1780 }
1781
1782 /**
1783 * Gets the temp directory when blender first runs.
1784 * If the default path is not found, use try $TEMP
1785
1786 * Also make sure the temp dir has a trailing slash
1787 *
1788 * @param fullname The full path to the temp directory
1789 * @param userdir Directory specified in user preferences 
1790 */
1791 void BLI_where_is_temp(char *fullname, const size_t maxlen, char *userdir)
1792 {
1793         fullname[0] = '\0';
1794         
1795         if (userdir && BLI_is_dir(userdir)) {
1796                 BLI_strncpy(fullname, userdir, maxlen);
1797         }
1798         
1799         
1800 #ifdef WIN32
1801         if (fullname[0] == '\0') {
1802                 const char *tmp = getenv("TEMP"); /* Windows */
1803                 if (tmp && BLI_is_dir(tmp)) {
1804                         BLI_strncpy(fullname, tmp, maxlen);
1805                 }
1806         }
1807 #else
1808         /* Other OS's - Try TMP and TMPDIR */
1809         if (fullname[0] == '\0') {
1810                 const char *tmp = getenv("TMP");
1811                 if (tmp && BLI_is_dir(tmp)) {
1812                         BLI_strncpy(fullname, tmp, maxlen);
1813                 }
1814         }
1815         
1816         if (fullname[0] == '\0') {
1817                 const char *tmp = getenv("TMPDIR");
1818                 if (tmp && BLI_is_dir(tmp)) {
1819                         BLI_strncpy(fullname, tmp, maxlen);
1820                 }
1821         }
1822 #endif  
1823         
1824         if (fullname[0] == '\0') {
1825                 BLI_strncpy(fullname, "/tmp/", maxlen);
1826         } else {
1827                 /* add a trailing slash if needed */
1828                 BLI_add_slash(fullname);
1829 #ifdef WIN32
1830                 if(userdir != fullname) {
1831                         BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1832                 }
1833 #endif
1834         }
1835 }
1836
1837 void BLI_init_temporary_dir(char *userdir)
1838 {
1839         BLI_where_is_temp(btempdir, FILE_MAX, userdir);
1840 }
1841
1842 const char *BLI_temporary_dir(void)
1843 {
1844         return btempdir;
1845 }
1846
1847 void BLI_system_temporary_dir(char *dir)
1848 {
1849         BLI_where_is_temp(dir, FILE_MAX, NULL);
1850 }
1851
1852 #ifdef WITH_ICONV
1853
1854 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1855 {
1856         size_t inbytesleft=strlen(original);
1857         size_t outbytesleft=512;
1858         size_t rv=0;
1859         iconv_t cd;
1860         
1861         if (NULL == code) {
1862                 code = locale_charset();
1863         }
1864         cd=iconv_open("UTF-8", code);
1865
1866         if (cd == (iconv_t)(-1)) {
1867                 printf("iconv_open Error");
1868                 *utf_8='\0';
1869                 return ;
1870         }
1871         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1872         if (rv == (size_t) -1) {
1873                 printf("iconv Error\n");
1874                 return ;
1875         }
1876         *utf_8 = '\0';
1877         iconv_close(cd);
1878 }
1879 #endif // WITH_ICONV
1880
1881