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