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