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