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