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