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