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