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