quiet msvc/mingw compiler warnings.
[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 #ifdef WIN32
460                 while (tolower(*p) == tolower(*q))
461 #else
462                 while (*p == *q)
463 #endif
464                 {
465                         ++p; ++q;
466                         /* dont search beyond the end of the string
467                          * in the rare case they match */
468                         if ((*p=='\0') || (*q=='\0')) {
469                                 break;
470                         }
471                 }
472
473                 /* we might have passed the slash when the beginning of a dir matches 
474                    so we rewind. Only check on the actual filename
475                 */
476                 if (*q != '/') {
477                         while ( (q >= file) && (*q != '/') ) { --q; --p; }
478                 } 
479                 else if (*p != '/') {
480                         while ( (p >= temp) && (*p != '/') ) { --p; --q; }
481                 }
482                 
483                 strcpy(res,     "//");
484
485                 /* p now points to the slash that is at the beginning of the part
486                    where the path is different from the relative path. 
487                    We count the number of directories we need to go up in the
488                    hierarchy to arrive at the common 'prefix' of the path
489                 */                      
490                 while (p && p < lslash) {
491                         if (*p == '/') 
492                                 strcat(res,     "../");
493                         ++p;
494                 }
495
496                 strcat(res, q+1); /* don't copy the slash at the beginning */
497                 
498 #ifdef  WIN32
499                 BLI_char_switch(res+2, '/', '\\');
500 #endif
501                 strcpy(file, res);
502         }
503 }
504
505 int BLI_has_parent(char *path)
506 {
507         int len;
508         int slashes = 0;
509         BLI_clean(path);
510         len = BLI_add_slash(path) - 1;
511
512         while (len>=0) {
513                 if ((path[len] == '\\') || (path[len] == '/'))
514                         slashes++;
515                 len--;
516         }
517         return slashes > 1;
518 }
519
520 int BLI_parent_dir(char *path)
521 {
522         static char parent_dir[]= {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
523         char tmp[FILE_MAXDIR+FILE_MAXFILE+4];
524         BLI_strncpy(tmp, path, sizeof(tmp)-4);
525         BLI_add_slash(tmp);
526         strcat(tmp, parent_dir);
527         BLI_cleanup_dir(NULL, tmp);
528         
529         if (!BLI_testextensie(tmp, parent_dir)) {
530                 BLI_strncpy(path, tmp, sizeof(tmp));    
531                 return 1;
532         } else {
533                 return 0;
534         }
535 }
536
537 static int stringframe_chars(char *path, int *char_start, int *char_end)
538 {
539         int ch_sta, ch_end, i;
540         /* Insert current frame: file### -> file001 */
541         ch_sta = ch_end = 0;
542         for (i = 0; path[i] != '\0'; i++) {
543                 if (path[i] == '\\' || path[i] == '/') {
544                         ch_end = 0; /* this is a directory name, dont use any hashes we found */
545                 } else if (path[i] == '#') {
546                         ch_sta = i;
547                         ch_end = ch_sta+1;
548                         while (path[ch_end] == '#') {
549                                 ch_end++;
550                         }
551                         i = ch_end-1; /* keep searching */
552                         
553                         /* dont break, there may be a slash after this that invalidates the previous #'s */
554                 }
555         }
556
557         if(ch_end) {
558                 *char_start= ch_sta;
559                 *char_end= ch_end;
560                 return 1;
561         }
562         else {
563                 *char_start= -1;
564                 *char_end= -1;
565                 return 0;
566         }
567 }
568
569 static void ensure_digits(char *path, int digits)
570 {
571         char *file= BLI_last_slash(path);
572
573         if(file==NULL)
574                 file= path;
575
576         if(strrchr(file, '#') == NULL) {
577                 int len= strlen(file);
578
579                 while(digits--) {
580                         file[len++]= '#';
581                 }
582                 file[len]= '\0';
583         }
584 }
585
586 int BLI_path_frame(char *path, int frame, int digits)
587 {
588         int ch_sta, ch_end;
589
590         if(digits)
591                 ensure_digits(path, digits);
592
593         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
594                 char tmp[FILE_MAX];
595                 sprintf(tmp, "%.*s%.*d%s", ch_sta, path, ch_end-ch_sta, frame, path+ch_end);
596                 strcpy(path, tmp);
597                 return 1;
598         }
599         return 0;
600 }
601
602 int BLI_path_frame_range(char *path, int sta, int end, int digits)
603 {
604         int ch_sta, ch_end;
605
606         if(digits)
607                 ensure_digits(path, digits);
608
609         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
610                 char tmp[FILE_MAX];
611                 sprintf(tmp, "%.*s%.*d-%.*d%s", ch_sta, path, ch_end-ch_sta, sta, ch_end-ch_sta, end, path+ch_end);
612                 strcpy(path, tmp);
613                 return 1;
614         }
615         return 0;
616 }
617
618 int BLI_path_abs(char *path, const char *basepath)
619 {
620         int wasrelative = (strncmp(path, "//", 2)==0);
621         char tmp[FILE_MAX];
622         char base[FILE_MAX];
623 #ifdef WIN32
624         char vol[3] = {'\0', '\0', '\0'};
625
626         BLI_strncpy(vol, path, 3);
627         /* we are checking here if we have an absolute path that is not in the current
628            blend file as a lib main - we are basically checking for the case that a 
629            UNIX root '/' is passed.
630         */
631         if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
632                 char *p = path;
633                 get_default_root(tmp);
634                 // get rid of the slashes at the beginning of the path
635                 while (*p == '\\' || *p == '/') {
636                         p++;
637                 }
638                 strcat(tmp, p);
639         }
640         else {
641                 BLI_strncpy(tmp, path, FILE_MAX);
642         }
643 #else
644         BLI_strncpy(tmp, path, sizeof(tmp));
645         
646         /* Check for loading a windows path on a posix system
647          * in this case, there is no use in trying C:/ since it 
648          * will never exist on a unix os.
649          * 
650          * Add a / prefix and lowercase the driveletter, remove the :
651          * C:\foo.JPG -> /c/foo.JPG */
652         
653         if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) {
654                 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
655                 tmp[0] = '/'; 
656                 /* '\' the slash will be converted later */
657         }
658         
659 #endif
660
661         BLI_strncpy(base, basepath, sizeof(base));
662
663         /* file component is ignored, so dont bother with the trailing slash */
664         BLI_cleanup_path(NULL, base);
665         
666         /* push slashes into unix mode - strings entering this part are
667            potentially messed up: having both back- and forward slashes.
668            Here we push into one conform direction, and at the end we
669            push them into the system specific dir. This ensures uniformity
670            of paths and solving some problems (and prevent potential future
671            ones) -jesterKing. */
672         BLI_char_switch(tmp, '\\', '/');
673         BLI_char_switch(base, '\\', '/');       
674
675         /* Paths starting with // will get the blend file as their base,
676          * this isnt standard in any os but is uesed in blender all over the place */
677         if (wasrelative) {
678                 char *lslash= BLI_last_slash(base);
679                 if (lslash) {
680                         int baselen= (int) (lslash-base) + 1;
681                         /* use path for temp storage here, we copy back over it right away */
682                         BLI_strncpy(path, tmp+2, FILE_MAX);
683                         
684                         memcpy(tmp, base, baselen);
685                         BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen);
686                         BLI_strncpy(path, tmp, FILE_MAX);
687                 } else {
688                         BLI_strncpy(path, tmp+2, FILE_MAX);
689                 }
690         } else {
691                 BLI_strncpy(path, tmp, FILE_MAX);
692         }
693
694         BLI_cleanup_path(NULL, path);
695
696 #ifdef WIN32
697         /* skip first two chars, which in case of
698            absolute path will be drive:/blabla and
699            in case of relpath //blabla/. So relpath
700            // will be retained, rest will be nice and
701            shiny win32 backward slashes :) -jesterKing
702         */
703         BLI_char_switch(path+2, '/', '\\');
704 #endif
705         
706         return wasrelative;
707 }
708
709
710 /*
711  * Should only be done with command line paths.
712  * this is NOT somthing blenders internal paths support like the // prefix
713  */
714 int BLI_path_cwd(char *path)
715 {
716         int wasrelative = 1;
717         int filelen = strlen(path);
718         
719 #ifdef WIN32
720         if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
721                 wasrelative = 0;
722 #else
723         if (filelen >= 2 && path[0] == '/')
724                 wasrelative = 0;
725 #endif
726         
727         if (wasrelative==1) {
728                 char cwd[FILE_MAXDIR + FILE_MAXFILE]= "";
729                 BLI_getwdN(cwd, sizeof(cwd)); /* incase the full path to the blend isnt used */
730                 
731                 if (cwd[0] == '\0') {
732                         printf( "Could not get the current working directory - $PWD for an unknown reason.");
733                 } else {
734                         /* uses the blend path relative to cwd important for loading relative linked files.
735                         *
736                         * cwd should contain c:\ etc on win32 so the relbase can be NULL
737                         * relbase being NULL also prevents // being misunderstood as relative to the current
738                         * blend file which isnt a feature we want to use in this case since were dealing
739                         * with a path from the command line, rather then from inside Blender */
740                         
741                         char origpath[FILE_MAXDIR + FILE_MAXFILE];
742                         BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE);
743                         
744                         BLI_make_file_string(NULL, path, cwd, origpath); 
745                 }
746         }
747         
748         return wasrelative;
749 }
750
751
752 /* 'di's filename component is moved into 'fi', di is made a dir path */
753 void BLI_splitdirstring(char *di, char *fi)
754 {
755         char *lslash= BLI_last_slash(di);
756
757         if (lslash) {
758                 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
759                 *(lslash+1)=0;
760         } else {
761                 BLI_strncpy(fi, di, FILE_MAXFILE);
762                 di[0]= 0;
763         }
764 }
765
766 void BLI_getlastdir(const char* dir, char *last, int maxlen)
767 {
768         const char *s = dir;
769         const char *lslash = NULL;
770         const char *prevslash = NULL;
771         while (*s) {
772                 if ((*s == '\\') || (*s == '/')) {
773                         prevslash = lslash;
774                         lslash = s;
775                 }
776                 s++;
777         }
778         if (prevslash) {
779                 BLI_strncpy(last, prevslash+1, maxlen);
780         } else {
781                 BLI_strncpy(last, dir, maxlen);
782         }
783 }
784
785 /* This is now only used to really get the user's default document folder */
786 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
787    as default location to save documents */
788 const char *BLI_getDefaultDocumentFolder(void) {
789         #if !defined(WIN32)
790                 return getenv("HOME");
791
792         #else /* Windows */
793                 const char * ret;
794                 static char documentfolder[MAXPATHLEN];
795                 HRESULT hResult;
796
797                 /* Check for %HOME% env var */
798
799                 ret = getenv("HOME");
800                 if(ret) {
801                         if (BLI_is_dir(ret)) return ret;
802                 }
803                                 
804                 /* add user profile support for WIN 2K / NT.
805                  * This is %APPDATA%, which translates to either
806                  * %USERPROFILE%\Application Data or since Vista
807                  * to %USERPROFILE%\AppData\Roaming
808                  */
809                 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
810                 
811                 if (hResult == S_OK)
812                 {
813                         if (BLI_is_dir(documentfolder)) return documentfolder;
814                 }
815                 
816                 return NULL;
817         #endif
818 }
819
820 /* NEW stuff, to be cleaned up when fully migrated */
821 /* ************************************************************* */
822 /* ************************************************************* */
823
824 // #define PATH_DEBUG2
825
826 static char *blender_version_decimal(void)
827 {
828         static char version_str[5];
829         sprintf(version_str, "%d.%02d", BLENDER_VERSION/100, BLENDER_VERSION%100);
830         return version_str;
831 }
832
833 static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
834 {
835         char tmppath[FILE_MAX];
836         
837         if(path_sep)    BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
838         else                    BLI_strncpy(tmppath, path_base, sizeof(tmppath));
839         
840         BLI_make_file_string("/", targetpath, tmppath, folder_name);
841         
842         if (BLI_is_dir(targetpath)) {
843 #ifdef PATH_DEBUG2
844                 printf("\tpath found: %s\n", targetpath);
845 #endif
846                 return 1;
847         }
848         else {
849 #ifdef PATH_DEBUG2
850                 printf("\tpath missing: %s\n", targetpath);
851 #endif
852                 //targetpath[0] = '\0';
853                 return 0;
854         }
855 }
856
857 static int test_env_path(char *path, const char *envvar)
858 {
859         const char *env = envvar?getenv(envvar):NULL;
860         if (!env) return 0;
861         
862         if (BLI_is_dir(env)) {
863                 BLI_strncpy(path, env, FILE_MAX);
864                 return 1;
865         } else {
866                 path[0] = '\0';
867                 return 0;
868         }
869 }
870
871 static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name)
872 {
873         char bprogdir[FILE_MAX];
874         char relfolder[FILE_MAX];
875         
876 #ifdef PATH_DEBUG2
877         printf("get_path_local...\n");
878 #endif
879         
880         if (subfolder_name) {
881                 BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
882         } else {
883                 BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
884         }
885         
886         /* use argv[0] (bprogname) to get the path to the executable */
887         BLI_split_dirfile(bprogname, bprogdir, NULL);
888         
889         /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
890         if(test_path(targetpath, bprogdir, blender_version_decimal(), relfolder))
891                 return 1;
892
893         return 0;
894 }
895
896 static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar)
897 {
898         char user_path[FILE_MAX];
899         const char *user_base_path;
900         
901         user_path[0] = '\0';
902
903         if (test_env_path(user_path, envvar)) {
904                 if (subfolder_name) {
905                         return test_path(targetpath, user_path, NULL, subfolder_name);
906                 } else {
907                         BLI_strncpy(targetpath, user_path, FILE_MAX);
908                         return 1;
909                 }
910         }
911
912         user_base_path = (const char *)GHOST_getUserDir();
913         if (user_base_path) {
914                 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal());
915         }
916
917         if(!user_path[0])
918                 return 0;
919         
920 #ifdef PATH_DEBUG2
921         printf("get_path_user: %s\n", user_path);
922 #endif
923         
924         if (subfolder_name) {
925                 /* try $HOME/folder_name/subfolder_name */
926                 return test_path(targetpath, user_path, folder_name, subfolder_name);
927         } else {
928                 /* try $HOME/folder_name */
929                 return test_path(targetpath, user_path, NULL, folder_name);
930         }
931 }
932
933 static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar)
934 {
935         char system_path[FILE_MAX];
936         const char *system_base_path;
937
938
939         /* first allow developer only overrides to the system path
940          * these are only used when running blender from source */
941         char cwd[FILE_MAX];
942         char relfolder[FILE_MAX];
943         char bprogdir[FILE_MAX];
944
945         /* use argv[0] (bprogname) to get the path to the executable */
946         BLI_split_dirfile(bprogname, bprogdir, NULL);
947
948         if (subfolder_name) {
949                 BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
950         } else {
951                 BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
952         }
953
954         /* try CWD/release/folder_name */
955         if(BLI_getwdN(cwd, sizeof(cwd))) {
956                 if(test_path(targetpath, cwd, "release", relfolder)) {
957                         return 1;
958                 }
959         }
960
961         /* try EXECUTABLE_DIR/release/folder_name */
962         if(test_path(targetpath, bprogdir, "release", relfolder))
963                 return 1;
964         /* end developer overrides */
965
966
967
968         system_path[0] = '\0';
969
970         if (test_env_path(system_path, envvar)) {
971                 if (subfolder_name) {
972                         return test_path(targetpath, system_path, NULL, subfolder_name);
973                 } else {
974                         BLI_strncpy(targetpath, system_path, FILE_MAX);
975                         return 1;
976                 }
977         }
978
979         system_base_path = (const char *)GHOST_getSystemDir();
980         if (system_base_path) {
981                 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal());
982         }
983         
984         if(!system_path[0])
985                 return 0;
986         
987 #ifdef PATH_DEBUG2
988         printf("get_path_system: %s\n", system_path);
989 #endif
990         
991         if (subfolder_name) {
992                 /* try $BLENDERPATH/folder_name/subfolder_name */
993                 return test_path(targetpath, system_path, folder_name, subfolder_name);
994         } else {
995                 /* try $BLENDERPATH/folder_name */
996                 return test_path(targetpath, system_path, NULL, folder_name);
997         }
998 }
999
1000 /* get a folder out of the 'folder_id' presets for paths */
1001 /* returns the path if found, NULL string if not */
1002 char *BLI_get_folder(int folder_id, const char *subfolder)
1003 {
1004         static char path[FILE_MAX] = "";
1005         
1006         switch (folder_id) {
1007                 case BLENDER_DATAFILES:         /* general case */
1008                         if (get_path_local(path, "datafiles", subfolder)) break;
1009                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
1010                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES")) break;
1011                         return NULL;
1012                         
1013                 case BLENDER_USER_DATAFILES:
1014                         if (get_path_local(path, "datafiles", subfolder)) break;
1015                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
1016                         return NULL;
1017                         
1018                 case BLENDER_SYSTEM_DATAFILES:
1019                         if (get_path_local(path, "datafiles", subfolder)) break;
1020                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES"))  break;
1021                         return NULL;
1022                         
1023                 case BLENDER_USER_AUTOSAVE:
1024                         if (get_path_local(path, "autosave", subfolder)) break;
1025                         if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES"))       break;
1026                         return NULL;
1027
1028                 case BLENDER_CONFIG:            /* general case */
1029                         if (get_path_local(path, "config", subfolder)) break;
1030                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
1031                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
1032                         return NULL;
1033                         
1034                 case BLENDER_USER_CONFIG:
1035                         if (get_path_local(path, "config", subfolder)) break;
1036                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
1037                         return NULL;
1038                         
1039                 case BLENDER_SYSTEM_CONFIG:
1040                         if (get_path_local(path, "config", subfolder)) break;
1041                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
1042                         return NULL;
1043                         
1044                 case BLENDER_SCRIPTS:           /* general case */
1045                         if (get_path_local(path, "scripts", subfolder)) break;
1046                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;           
1047                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1048                         return NULL;
1049                         
1050                 case BLENDER_USER_SCRIPTS:
1051                         if (get_path_local(path, "scripts", subfolder)) break;
1052                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;
1053                         return NULL;
1054                         
1055                 case BLENDER_SYSTEM_SCRIPTS:
1056                         if (get_path_local(path, "scripts", subfolder)) break;
1057                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1058                         return NULL;
1059                         
1060                 case BLENDER_PYTHON:            /* general case */
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                 case BLENDER_SYSTEM_PYTHON:
1066                         if (get_path_local(path, "python", subfolder)) break;
1067                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1068                         return NULL;
1069         }
1070         
1071         return path;
1072 }
1073
1074 char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
1075 {
1076         static char path[FILE_MAX] = "";
1077
1078         switch (folder_id) {
1079                 case BLENDER_USER_DATAFILES:
1080                         get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES");
1081                         break;
1082                 case BLENDER_USER_CONFIG:
1083                         get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG");
1084                         break;
1085                 case BLENDER_USER_AUTOSAVE:
1086                         get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE");
1087                         break;
1088                 case BLENDER_USER_SCRIPTS:
1089                         get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS");
1090                         break;
1091         }
1092         if ('\0' == path[0]) {
1093                 return NULL;
1094         }
1095         return path;
1096 }
1097
1098 char *BLI_get_folder_create(int folder_id, const char *subfolder)
1099 {
1100         char *path;
1101
1102         /* only for user folders */
1103         if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1104                 return NULL;
1105         
1106         path = BLI_get_folder(folder_id, subfolder);
1107         
1108         if (!path) {
1109                 path = BLI_get_user_folder_notest(folder_id, subfolder);
1110                 if (path) BLI_recurdir_fileops(path);
1111         }
1112         
1113         return path;
1114 }
1115
1116
1117 /* End new stuff */
1118 /* ************************************************************* */
1119 /* ************************************************************* */
1120
1121
1122
1123 #ifdef PATH_DEBUG
1124 #undef PATH_DEBUG
1125 #endif
1126
1127 void BLI_setenv(const char *env, const char*val)
1128 {
1129         /* SGI or free windows */
1130 #if (defined(__sgi) || ((defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)))
1131         char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1132
1133         sprintf(envstr, "%s=%s", env, val);
1134         putenv(envstr);
1135         MEM_freeN(envstr);
1136
1137         /* non-free windows */
1138 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1139         _putenv_s(env, val);
1140 #else
1141         /* linux/osx/bsd */
1142         setenv(env, val, 1);
1143 #endif
1144 }
1145
1146
1147 /**
1148  Only set an env var if already not there.
1149  Like Unix setenv(env, val, 0);
1150  */
1151 void BLI_setenv_if_new(const char *env, const char* val)
1152 {
1153         if(getenv(env) == NULL)
1154                 BLI_setenv(env, val);
1155 }
1156
1157
1158 void BLI_clean(char *path)
1159 {
1160         if(path==NULL) return;
1161
1162 #ifdef WIN32
1163         if(path && BLI_strnlen(path, 3) > 2) {
1164                 BLI_char_switch(path+2, '/', '\\');
1165         }
1166 #else
1167         BLI_char_switch(path, '\\', '/');
1168 #endif
1169 }
1170
1171 void BLI_char_switch(char *string, char from, char to) 
1172 {
1173         if(string==NULL) return;
1174         while (*string != 0) {
1175                 if (*string == from) *string = to;
1176                 string++;
1177         }
1178 }
1179
1180 void BLI_make_exist(char *dir) {
1181         int a;
1182
1183         BLI_char_switch(dir, ALTSEP, SEP);
1184
1185         a = strlen(dir);
1186
1187         while(BLI_is_dir(dir) == 0){
1188                 a --;
1189                 while(dir[a] != SEP){
1190                         a--;
1191                         if (a <= 0) break;
1192                 }
1193                 if (a >= 0) {
1194                         dir[a+1] = '\0';
1195                 }
1196                 else {
1197 #ifdef WIN32
1198                         get_default_root(dir);
1199 #else
1200                         strcpy(dir,"/");
1201 #endif
1202                         break;
1203                 }
1204         }
1205 }
1206
1207 void BLI_make_existing_file(const char *name)
1208 {
1209         char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1210
1211         BLI_strncpy(di, name, sizeof(di));
1212         BLI_splitdirstring(di, fi);
1213         
1214         /* test exist */
1215         if (BLI_exists(di) == 0) {
1216                 BLI_recurdir_fileops(di);
1217         }
1218 }
1219
1220
1221 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1222 {
1223         int sl;
1224
1225         if (!string || !dir || !file) return; /* We don't want any NULLs */
1226         
1227         string[0]= 0; /* ton */
1228
1229         /* we first push all slashes into unix mode, just to make sure we don't get
1230            any mess with slashes later on. -jesterKing */
1231         /* constant strings can be passed for those parameters - don't change them - elubie */
1232         /*
1233         BLI_char_switch(relabase, '\\', '/');
1234         BLI_char_switch(dir, '\\', '/');
1235         BLI_char_switch(file, '\\', '/');
1236         */
1237
1238         /* Resolve relative references */       
1239         if (relabase && dir[0] == '/' && dir[1] == '/') {
1240                 char *lslash;
1241                 
1242                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1243                 strcpy(string, relabase);
1244                 
1245                 lslash= BLI_last_slash(string);
1246                 if(lslash) *(lslash+1)= 0;
1247
1248                 dir+=2; /* Skip over the relative reference */
1249         }
1250 #ifdef WIN32
1251         else {
1252                 if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':' ) {
1253                         BLI_strncpy(string, dir, 3);
1254                         dir += 2;
1255                 }
1256                 else { /* no drive specified */
1257                         /* first option: get the drive from the relabase if it has one */
1258                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1259                                 BLI_strncpy(string, relabase, 3);       
1260                                 string[2] = '\\';
1261                                 string[3] = '\0';
1262                         }
1263                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1264                                 get_default_root(string);
1265                         }
1266                         
1267                         /* ignore leading slashes */
1268                         while (*dir == '/' || *dir == '\\') dir++;
1269                 }
1270         }
1271 #endif
1272
1273         strcat(string, dir);
1274
1275         /* Make sure string ends in one (and only one) slash */ 
1276         /* first trim all slashes from the end of the string */
1277         sl = strlen(string);
1278         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1279                 string[sl-1] = '\0';
1280                 sl--;
1281         }
1282         /* since we've now removed all slashes, put back one slash at the end. */
1283         strcat(string, "/");
1284         
1285         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1286                 file++;
1287                 
1288         strcat (string, file);
1289         
1290         /* Push all slashes to the system preferred direction */
1291         BLI_clean(string);
1292 }
1293
1294 int BLI_testextensie(const char *str, const char *ext)
1295 {
1296         short a, b;
1297         int retval;
1298         
1299         a= strlen(str);
1300         b= strlen(ext);
1301         
1302         if(a==0 || b==0 || b>=a) {
1303                 retval = 0;
1304         } else if (BLI_strcasecmp(ext, str + a - b)) {
1305                 retval = 0;     
1306         } else {
1307                 retval = 1;
1308         }
1309         
1310         return (retval);
1311 }
1312
1313 int BLI_testextensie_array(const char *str, const char **ext_array)
1314 {
1315         int i=0;
1316         while(ext_array[i]) {
1317                 if(BLI_testextensie(str, ext_array[i])) {
1318                         return 1;
1319                 }
1320
1321                 i++;
1322         }
1323         return 0;
1324 }
1325
1326 /* semicolon separated wildcards, eg:
1327  *  '*.zip;*.py;*.exe' */
1328 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1329 {
1330         const char *ext_step= ext_fnmatch;
1331         char pattern[16];
1332
1333         while(ext_step[0]) {
1334                 char *ext_next;
1335                 int len_ext;
1336
1337                 if((ext_next=strchr(ext_step, ';'))) {
1338                         len_ext= (int)(ext_next - ext_step) + 1;
1339                 }
1340                 else {
1341                         len_ext= sizeof(pattern);
1342                 }
1343
1344                 BLI_strncpy(pattern, ext_step, len_ext);
1345
1346                 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1347                         return 1;
1348                 }
1349                 ext_step += len_ext;
1350         }
1351
1352         return 0;
1353 }
1354
1355
1356 int BLI_replace_extension(char *path, size_t maxlen, const char *ext)
1357 {
1358         size_t a;
1359
1360         for(a=strlen(path); a>0; a--) {
1361                 if(path[a-1] == '.' || path[a-1] == '/' || path[a-1] == '\\') {
1362                         a--;
1363                         break;
1364                 }
1365         }
1366         
1367         if(path[a] != '.')
1368                 a= strlen(path);
1369
1370         if(a + strlen(ext) >= maxlen)
1371                 return 0;
1372
1373         strcpy(path+a, ext);
1374         return 1;
1375 }
1376
1377 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1378  * - wont change 'string'
1379  * - wont create any directories
1380  * - dosnt use CWD, or deal with relative paths.
1381  * - Only fill's in *dir and *file when they are non NULL
1382  * */
1383 void BLI_split_dirfile(const char *string, char *dir, char *file)
1384 {
1385         char *lslash_str = BLI_last_slash(string);
1386         int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0;
1387
1388         if (dir) {
1389                 if (lslash) {
1390                         BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */
1391                 } else {
1392                         dir[0] = '\0';
1393                 }
1394         }
1395         
1396         if (file) {
1397                 strcpy( file, string+lslash);
1398         }
1399 }
1400
1401 /* simple appending of filename to dir, does not check for valid path! */
1402 void BLI_join_dirfile(char *string, const int maxlen, const char *dir, const char *file)
1403 {
1404         int sl_dir;
1405         
1406         if(string != dir) /* compare pointers */
1407                 BLI_strncpy(string, dir, maxlen);
1408
1409         if (!file)
1410                 return;
1411         
1412         sl_dir= BLI_add_slash(string);
1413         
1414         if (sl_dir <FILE_MAX) {
1415                 BLI_strncpy(string + sl_dir, file, maxlen - sl_dir);
1416         }
1417 }
1418
1419 /* like pythons os.path.basename( ) */
1420 char *BLI_path_basename(char *path)
1421 {
1422         char *filename= BLI_last_slash(path);
1423         return filename ? filename + 1 : path;
1424 }
1425
1426 /*
1427   Produce image export path.
1428
1429   Fails returning 0 if image filename is empty or if destination path
1430   matches image path (i.e. both are the same file).
1431
1432   Trailing slash in dest_dir is optional.
1433
1434   Logic:
1435
1436   - if an image is "below" current .blend file directory, rebuild the
1437         same dir structure in dest_dir
1438
1439   For example //textures/foo/bar.png becomes
1440   [dest_dir]/textures/foo/bar.png.
1441
1442   - if an image is not "below" current .blend file directory,
1443   disregard it's path and copy it in the same directory where 3D file
1444   goes.
1445
1446   For example //../foo/bar.png becomes [dest_dir]/bar.png.
1447
1448   This logic will help ensure that all image paths are relative and
1449   that a user gets his images in one place. It'll also provide
1450   consistent behaviour across exporters.
1451  */
1452 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)
1453 {
1454         char path[FILE_MAX];
1455         char dir[FILE_MAX];
1456         char base[FILE_MAX];
1457         char blend_dir[FILE_MAX];       /* directory, where current .blend file resides */
1458         char dest_path[FILE_MAX];
1459         char rel_dir[FILE_MAX];
1460         int len;
1461
1462         if (abs)
1463                 abs[0]= 0;
1464
1465         if (rel)
1466                 rel[0]= 0;
1467
1468         BLI_split_dirfile(base_dir, blend_dir, NULL);
1469
1470         if (src_dir[0]=='\0')
1471                 return 0;
1472
1473         BLI_strncpy(path, src_dir, sizeof(path));
1474
1475         /* expand "//" in filename and get absolute path */
1476         BLI_path_abs(path, base_dir);
1477
1478         /* get the directory part */
1479         BLI_split_dirfile(path, dir, base);
1480
1481         len= strlen(blend_dir);
1482
1483         rel_dir[0] = 0;
1484
1485         /* if image is "below" current .blend file directory */
1486         if (!strncmp(path, blend_dir, len)) {
1487
1488                 /* if image is _in_ current .blend file directory */
1489                 if (BLI_path_cmp(dir, blend_dir) == 0) {
1490                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1491                 }
1492                 /* "below" */
1493                 else {
1494                         /* rel = image_path_dir - blend_dir */
1495                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1496
1497                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir);
1498                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base);
1499                 }
1500
1501         }
1502         /* image is out of current directory */
1503         else {
1504                 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1505         }
1506
1507         if (abs)
1508                 BLI_strncpy(abs, dest_path, abs_size);
1509
1510         if (rel) {
1511                 strncat(rel, rel_dir, rel_size);
1512                 strncat(rel, base, rel_size);
1513         }
1514
1515         /* return 2 if src=dest */
1516         if (BLI_path_cmp(path, dest_path) == 0) {
1517                 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1518                 return 2;
1519         }
1520
1521         return 1;
1522 }
1523
1524 char *BLI_first_slash(char *string) {
1525         char *ffslash, *fbslash;
1526         
1527         ffslash= strchr(string, '/');   
1528         fbslash= strchr(string, '\\');
1529         
1530         if (!ffslash) return fbslash;
1531         else if (!fbslash) return ffslash;
1532         
1533         if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1534         else return fbslash;
1535 }
1536
1537 char *BLI_last_slash(const char *string) {
1538         char *lfslash, *lbslash;
1539         
1540         lfslash= strrchr(string, '/');  
1541         lbslash= strrchr(string, '\\');
1542
1543         if (!lfslash) return lbslash; 
1544         else if (!lbslash) return lfslash;
1545         
1546         if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1547         else return lfslash;
1548 }
1549
1550 /* adds a slash if there isnt one there already */
1551 int BLI_add_slash(char *string) {
1552         int len = strlen(string);
1553 #ifdef WIN32
1554         if (len==0 || string[len-1]!='\\') {
1555                 string[len] = '\\';
1556                 string[len+1] = '\0';
1557                 return len+1;
1558         }
1559 #else
1560         if (len==0 || string[len-1]!='/') {
1561                 string[len] = '/';
1562                 string[len+1] = '\0';
1563                 return len+1;
1564         }
1565 #endif
1566         return len;
1567 }
1568
1569 /* removes a slash if there is one */
1570 void BLI_del_slash(char *string) {
1571         int len = strlen(string);
1572         while (len) {
1573 #ifdef WIN32
1574                 if (string[len-1]=='\\') {
1575 #else
1576                 if (string[len-1]=='/') {
1577 #endif
1578                         string[len-1] = '\0';
1579                         len--;
1580                 } else {
1581                         break;
1582                 }
1583         }
1584 }
1585
1586 static int add_win32_extension(char *name)
1587 {
1588         int retval = 0;
1589         int type;
1590
1591         type = BLI_exist(name);
1592         if ((type == 0) || S_ISDIR(type)) {
1593 #ifdef _WIN32
1594                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1595                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1596                 const char *extensions = getenv("PATHEXT");
1597                 if (extensions) {
1598                         char *temp;
1599                         do {
1600                                 strcpy(filename, name);
1601                                 temp = strstr(extensions, ";");
1602                                 if (temp) {
1603                                         strncpy(ext, extensions, temp - extensions);
1604                                         ext[temp - extensions] = 0;
1605                                         extensions = temp + 1;
1606                                         strcat(filename, ext);
1607                                 } else {
1608                                         strcat(filename, extensions);
1609                                 }
1610
1611                                 type = BLI_exist(filename);
1612                                 if (type && (! S_ISDIR(type))) {
1613                                         retval = 1;
1614                                         strcpy(name, filename);
1615                                         break;
1616                                 }
1617                         } while (temp);
1618                 }
1619 #endif
1620         } else {
1621                 retval = 1;
1622         }
1623
1624         return (retval);
1625 }
1626
1627 /* filename must be FILE_MAX length minimum */
1628 void BLI_where_am_i(char *fullname, const int maxlen, const char *name)
1629 {
1630         char filename[FILE_MAXDIR+FILE_MAXFILE];
1631         const char *path = NULL, *temp;
1632
1633 #ifdef _WIN32
1634         const char *separator = ";";
1635 #else
1636         const char *separator = ":";
1637 #endif
1638
1639         
1640 #ifdef WITH_BINRELOC
1641         /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1642         path = br_find_exe( NULL );
1643         if (path) {
1644                 BLI_strncpy(fullname, path, maxlen);
1645                 free((void *)path);
1646                 return;
1647         }
1648 #endif
1649
1650 #ifdef _WIN32
1651         if(GetModuleFileName(0, fullname, maxlen)) {
1652                 GetShortPathName(fullname, fullname, maxlen);
1653                 return;
1654         }
1655 #endif
1656
1657         /* unix and non linux */
1658         if (name && name[0]) {
1659                 BLI_strncpy(fullname, name, maxlen);
1660                 if (name[0] == '.') {
1661                         char wdir[FILE_MAX]= "";
1662                         BLI_getwdN(wdir, sizeof(wdir));  /* backup cwd to restore after */
1663
1664                         // not needed but avoids annoying /./ in name
1665                         if(name[1]==SEP)
1666                                 BLI_join_dirfile(fullname, maxlen, wdir, name+2);
1667                         else
1668                                 BLI_join_dirfile(fullname, maxlen, wdir, name);
1669
1670                         add_win32_extension(fullname); /* XXX, doesnt respect length */
1671                 }
1672                 else if (BLI_last_slash(name)) {
1673                         // full path
1674                         BLI_strncpy(fullname, name, maxlen);
1675                         add_win32_extension(fullname);
1676                 } else {
1677                         // search for binary in $PATH
1678                         path = getenv("PATH");
1679                         if (path) {
1680                                 do {
1681                                         temp = strstr(path, separator);
1682                                         if (temp) {
1683                                                 strncpy(filename, path, temp - path);
1684                                                 filename[temp - path] = 0;
1685                                                 path = temp + 1;
1686                                         } else {
1687                                                 strncpy(filename, path, sizeof(filename));
1688                                         }
1689                                         BLI_join_dirfile(fullname, maxlen, fullname, name);
1690                                         if (add_win32_extension(filename)) {
1691                                                 BLI_strncpy(fullname, filename, maxlen);
1692                                                 break;
1693                                         }
1694                                 } while (temp);
1695                         }
1696                 }
1697 #if defined(DEBUG)
1698                 if (strcmp(name, fullname)) {
1699                         printf("guessing '%s' == '%s'\n", name, fullname);
1700                 }
1701 #endif
1702
1703 #ifdef _WIN32
1704                 // in windows change long filename to short filename because
1705                 // win2k doesn't know how to parse a commandline with lots of
1706                 // spaces and double-quotes. There's another solution to this
1707                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1708                 // that's even uglier
1709                 GetShortPathName(fullname, fullname, maxlen);
1710 #if defined(DEBUG)
1711                 printf("Shortname = '%s'\n", fullname);
1712 #endif
1713 #endif
1714         }
1715 }
1716
1717 void BLI_where_is_temp(char *fullname, const int maxlen, int usertemp)
1718 {
1719         fullname[0] = '\0';
1720         
1721         if (usertemp && BLI_is_dir(U.tempdir)) {
1722                 BLI_strncpy(fullname, U.tempdir, maxlen);
1723         }
1724         
1725         
1726 #ifdef WIN32
1727         if (fullname[0] == '\0') {
1728                 const char *tmp = getenv("TEMP"); /* Windows */
1729                 if (tmp && BLI_is_dir(tmp)) {
1730                         BLI_strncpy(fullname, tmp, maxlen);
1731                 }
1732         }
1733 #else
1734         /* Other OS's - Try TMP and TMPDIR */
1735         if (fullname[0] == '\0') {
1736                 const char *tmp = getenv("TMP");
1737                 if (tmp && BLI_is_dir(tmp)) {
1738                         BLI_strncpy(fullname, tmp, maxlen);
1739                 }
1740         }
1741         
1742         if (fullname[0] == '\0') {
1743                 const char *tmp = getenv("TMPDIR");
1744                 if (tmp && BLI_is_dir(tmp)) {
1745                         BLI_strncpy(fullname, tmp, maxlen);
1746                 }
1747         }
1748 #endif  
1749         
1750         if (fullname[0] == '\0') {
1751                 BLI_strncpy(fullname, "/tmp/", maxlen);
1752         } else {
1753                 /* add a trailing slash if needed */
1754                 BLI_add_slash(fullname);
1755 #ifdef WIN32
1756                 if(U.tempdir != fullname) {
1757                         BLI_strncpy(U.tempdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1758                 }
1759 #endif
1760         }
1761 }
1762
1763 char *get_install_dir(void) {
1764         char *tmpname = BLI_strdup(bprogname);
1765         char *cut;
1766
1767 #ifdef __APPLE__
1768         cut = strstr(tmpname, ".app");
1769         if (cut) cut[0] = 0;
1770 #endif
1771
1772         cut = BLI_last_slash(tmpname);
1773
1774         if (cut) {
1775                 cut[0] = 0;
1776                 return tmpname;
1777         } else {
1778                 MEM_freeN(tmpname);
1779                 return NULL;
1780         }
1781 }
1782
1783 #ifdef WITH_ICONV
1784
1785 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1786 {
1787         size_t inbytesleft=strlen(original);
1788         size_t outbytesleft=512;
1789         size_t rv=0;
1790         iconv_t cd;
1791         
1792         if (NULL == code) {
1793                 code = locale_charset();
1794         }
1795         cd=iconv_open("UTF-8", code);
1796
1797         if (cd == (iconv_t)(-1)) {
1798                 printf("iconv_open Error");
1799                 *utf_8='\0';
1800                 return ;
1801         }
1802         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1803         if (rv == (size_t) -1) {
1804                 printf("iconv Error\n");
1805                 return ;
1806         }
1807         *utf_8 = '\0';
1808         iconv_close(cd);
1809 }
1810 #endif // WITH_ICONV
1811
1812