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