Fix msvc 2013 compiler errors after the ingenious cleanup in 4ca67869cc7a.
[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 #include <ctype.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <assert.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "DNA_listBase.h"
42
43 #include "BLI_utildefines.h"
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_fnmatch.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 #ifdef WIN32
55 #  include "utf_winfunc.h"
56 #  include "utfconv.h"
57 #  include <io.h>
58 #  ifdef _WIN32_IE
59 #    undef _WIN32_IE
60 #  endif
61 #  define _WIN32_IE 0x0501
62 #  include <windows.h>
63 #  include <shlobj.h>
64 #  include "BLI_winstuff.h"
65 #else /* non windows */
66 #  ifdef WITH_BINRELOC
67 #    include "binreloc.h"
68 #  endif
69 #endif /* WIN32 */
70
71 /* local */
72 #define UNIQUE_NAME_MAX 128
73
74 static char bprogname[FILE_MAX];    /* full path to program executable */
75 static char bprogdir[FILE_MAX];     /* full path to directory in which executable is located */
76 static char btempdir[FILE_MAX];     /* temporary directory */
77
78 /* implementation */
79
80 /**
81  * Looks for a sequence of decimal digits in string, preceding any filename extension,
82  * returning the integer value if found, or 0 if not.
83  *
84  * \param string  String to scan.
85  * \param head  Optional area to return copy of part of string prior to digits, or before dot if no digits.
86  * \param tail  Optional area to return copy of part of string following digits, or from dot if no digits.
87  * \param numlen  Optional to return number of digits found.
88  */
89 int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
90 {
91         unsigned int nums = 0, nume = 0;
92         int i;
93         bool found_digit = false;
94         const char * const lslash = BLI_last_slash(string);
95         const unsigned int string_len = strlen(string);
96         const unsigned int lslash_len = lslash != NULL ? (int)(lslash - string) : 0;
97         unsigned int name_end = string_len;
98
99         while (name_end > lslash_len && string[--name_end] != '.') {} /* name ends at dot if present */
100         if (name_end == lslash_len && string[name_end] != '.') name_end = string_len;
101
102         for (i = name_end - 1; i >= (int)lslash_len; i--) {
103                 if (isdigit(string[i])) {
104                         if (found_digit) {
105                                 nums = i;
106                         }
107                         else {
108                                 nume = i;
109                                 nums = i;
110                                 found_digit = true;
111                         }
112                 }
113                 else {
114                         if (found_digit) break;
115                 }
116         }
117
118         if (found_digit) {
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         else {
128                 if (tail) strcpy(tail, string + name_end);
129                 if (head) {
130                         /* name_end points to last character of head,
131                          * make it +1 so null-terminator is nicely placed
132                          */
133                         BLI_strncpy(head, string, name_end + 1);
134                 }
135                 if (numlen) *numlen = 0;
136                 return 0;
137         }
138 }
139
140
141 /**
142  * Returns in area pointed to by string a string of the form "<head><pic><tail>", where pic
143  * is formatted as numlen digits with leading zeroes.
144  */
145 void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
146 {
147         sprintf(string, "%s%.*d%s", head, numlen, MAX2(0, pic), tail);
148 }
149
150 /**
151  * Looks for a numeric suffix preceded by delim character on the end of
152  * name, puts preceding part into *left and value of suffix into *nr.
153  * Returns the length of *left.
154  *
155  * Foo.001 -> "Foo", 1
156  * Returning the length of "Foo"
157  *
158  * \param left  Where to return copy of part preceding delim
159  * \param nr  Where to return value of numeric suffix
160  * \param name  String to split
161  * \param delim  Delimiter character
162  * \return  Length of \a left
163  */
164 int BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
165 {
166         const int name_len = strlen(name);
167
168         *nr = 0;
169         memcpy(left, name, (name_len + 1) * sizeof(char));
170
171         /* name doesn't end with a delimiter "foo." */
172         if ((name_len > 1 && name[name_len - 1] == delim) == 0) {
173                 int a = name_len;
174                 while (a--) {
175                         if (name[a] == delim) {
176                                 left[a] = '\0';  /* truncate left part here */
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                         else if (isdigit(name[a]) == 0) {
184                                 /* non-numeric suffix - give up */
185                                 break;
186                         }
187                 }
188         }
189
190         return name_len;
191 }
192
193 /**
194  * Looks for a string of digits within name (using BLI_stringdec) and adjusts it by add.
195  */
196 void BLI_newname(char *name, int add)
197 {
198         char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX];
199         int pic;
200         unsigned short digits;
201         
202         pic = BLI_stringdec(name, head, tail, &digits);
203         
204         /* are we going from 100 -> 99 or from 10 -> 9 */
205         if (add < 0 && digits < 4 && digits > 0) {
206                 int i, exp;
207                 exp = 1;
208                 for (i = digits; i > 1; i--) exp *= 10;
209                 if (pic >= exp && (pic + add) < exp) digits--;
210         }
211         
212         pic += add;
213         
214         if (digits == 4 && pic < 0) pic = 0;
215         BLI_stringenc(name, head, tail, digits, pic);
216 }
217
218 /**
219  * Ensures name is unique (according to criteria specified by caller in unique_check callback),
220  * incrementing its numeric suffix as necessary. Returns true if name had to be adjusted.
221  *
222  * \param unique_check  Return true if name is not unique
223  * \param arg  Additional arg to unique_check--meaning is up to caller
224  * \param defname  To initialize name if latter is empty
225  * \param delim  Delimits numeric suffix in name
226  * \param name  Name to be ensured unique
227  * \param name_len  Maximum length of name area
228  * \return true if there if the name was changed
229  */
230 bool BLI_uniquename_cb(bool (*unique_check)(void *arg, const char *name),
231                        void *arg, const char *defname, char delim, char *name, int name_len)
232 {
233         if (name[0] == '\0') {
234                 BLI_strncpy(name, defname, name_len);
235         }
236
237         if (unique_check(arg, name)) {
238                 char numstr[16];
239                 char tempname[UNIQUE_NAME_MAX];
240                 char left[UNIQUE_NAME_MAX];
241                 int number;
242                 int len = BLI_split_name_num(left, &number, name, delim);
243                 do {
244                         const int numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number);
245
246                         /* highly unlikely the string only has enough room for the number
247                          * but support anyway */
248                         if ((len == 0) || (numlen >= name_len)) {
249                                 /* number is know not to be utf-8 */
250                                 BLI_strncpy(tempname, numstr, name_len);
251                         }
252                         else {
253                                 char *tempname_buf;
254                                 tempname[0] = '\0';
255                                 tempname_buf = BLI_strncat_utf8(tempname, left, name_len - numlen);
256                                 memcpy(tempname_buf, numstr, numlen + 1);
257                         }
258                 } while (unique_check(arg, tempname));
259
260                 BLI_strncpy(name, tempname, name_len);
261                 
262                 return true;
263         }
264         
265         return false;
266 }
267
268 /* little helper macro for BLI_uniquename */
269 #ifndef GIVE_STRADDR
270 #  define GIVE_STRADDR(data, offset) ( ((char *)data) + offset)
271 #endif
272
273 /* Generic function to set a unique name. It is only designed to be used in situations
274  * where the name is part of the struct, and also that the name is at most UNIQUE_NAME_MAX chars long.
275  * 
276  * For places where this is used, see constraint.c for example...
277  *
278  *  name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
279  *  len: maximum length of string (to prevent overflows, etc.)
280  *  defname: the name that should be used by default if none is specified already
281  *  delim: the character which acts as a delimiter between parts of the name
282  */
283 static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name, int name_offs)
284 {
285         Link *link;
286
287         for (link = list->first; link; link = link->next) {
288                 if (link != vlink) {
289                         if (STREQ(GIVE_STRADDR(link, name_offs), name)) {
290                                 return true;
291                         }
292                 }
293         }
294
295         return false;
296 }
297
298 static bool uniquename_unique_check(void *arg, const char *name)
299 {
300         struct {ListBase *lb; void *vlink; int name_offs; } *data = arg;
301         return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
302 }
303
304 /**
305  * Ensures that the specified block has a unique name within the containing list,
306  * incrementing its numeric suffix as necessary.
307  *
308  * \param list  List containing the block
309  * \param vlink  The block to check the name for
310  * \param defname  To initialize block name if latter is empty
311  * \param delim  Delimits numeric suffix in name
312  * \param name_offs  Offset of name within block structure
313  * \param name_len  Maximum length of name area
314  */
315 void BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim, int name_offs, int name_len)
316 {
317         struct {ListBase *lb; void *vlink; int name_offs; } data;
318         data.lb = list;
319         data.vlink = vlink;
320         data.name_offs = name_offs;
321
322         assert((name_len > 1) && (name_len <= UNIQUE_NAME_MAX));
323
324         /* See if we are given an empty string */
325         if (ELEM(NULL, vlink, defname))
326                 return;
327
328         BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
329 }
330
331 static int BLI_path_unc_prefix_len(const char *path); /* defined below in same file */
332
333 /* ******************** string encoding ***************** */
334
335 /* This is quite an ugly function... its purpose is to
336  * take the dir name, make it absolute, and clean it up, replacing
337  * excess file entry stuff (like /tmp/../tmp/../)
338  * note that dir isn't protected for max string names... 
339  * 
340  * If relbase is NULL then its ignored
341  */
342
343 void BLI_cleanup_path(const char *relabase, char *path)
344 {
345         ptrdiff_t a;
346         char *start, *eind;
347         if (relabase) {
348                 BLI_path_abs(path, relabase);
349         }
350         else {
351                 if (path[0] == '/' && path[1] == '/') {
352                         if (path[2] == '\0') {
353                                 return; /* path is "//" - cant clean it */
354                         }
355                         path = path + 2;  /* leave the initial "//" untouched */
356                 }
357         }
358         
359         /* Note
360          *   memmove(start, eind, strlen(eind) + 1);
361          * is the same as
362          *   strcpy( start, eind ); 
363          * except strcpy should not be used because there is overlap,
364          * so use memmove's slightly more obscure syntax - Campbell
365          */
366         
367 #ifdef WIN32
368         
369         /* Note, this should really be moved to the file selector,
370          * since this function is used in many areas */
371         if (strcmp(path, ".") == 0) {  /* happens for example in FILE_MAIN */
372                 get_default_root(path);
373                 return;
374         }
375
376         while ( (start = strstr(path, "\\..\\")) ) {
377                 eind = start + strlen("\\..\\") - 1;
378                 a = start - path - 1;
379                 while (a > 0) {
380                         if (path[a] == '\\') break;
381                         a--;
382                 }
383                 if (a < 0) {
384                         break;
385                 }
386                 else {
387                         memmove(path + a, eind, strlen(eind) + 1);
388                 }
389         }
390
391         while ( (start = strstr(path, "\\.\\")) ) {
392                 eind = start + strlen("\\.\\") - 1;
393                 memmove(start, eind, strlen(eind) + 1);
394         }
395
396         /* remove two consecutive backslashes, but skip the UNC prefix,
397          * which needs to be preserved */
398         while ( (start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\")) ) {
399                 eind = start + strlen("\\\\") - 1;
400                 memmove(start, eind, strlen(eind) + 1);
401         }
402 #else
403         if (path[0] == '.') {  /* happens, for example in FILE_MAIN */
404                 path[0] = '/';
405                 path[1] = 0;
406                 return;
407         }
408
409         while ( (start = strstr(path, "/../")) ) {
410                 a = start - path - 1;
411                 if (a > 0) {
412                         /* <prefix>/<parent>/../<postfix> => <prefix>/<postfix> */
413                         eind = start + (4 - 1) /* strlen("/../") - 1 */; /* strip "/.." and keep last "/" */
414                         while (a > 0 && path[a] != '/') { /* find start of <parent> */
415                                 a--;
416                         }
417                         memmove(path + a, eind, strlen(eind) + 1);
418                 }
419                 else {
420                         /* support for odd paths: eg /../home/me --> /home/me
421                          * this is a valid path in blender but we cant handle this the usual way below
422                          * simply strip this prefix then evaluate the path as usual.
423                          * pythons os.path.normpath() does this */
424
425                         /* Note: previous version of following call used an offset of 3 instead of 4,
426                          * which meant that the "/../home/me" example actually became "home/me".
427                          * Using offset of 3 gives behaviour consistent with the abovementioned
428                          * Python routine. */
429                         memmove(path, path + 3, strlen(path + 3) + 1);
430                 }
431         }
432
433         while ( (start = strstr(path, "/./")) ) {
434                 eind = start + (3 - 1) /* strlen("/./") - 1 */;
435                 memmove(start, eind, strlen(eind) + 1);
436         }
437
438         while ( (start = strstr(path, "//")) ) {
439                 eind = start + (2 - 1) /* strlen("//") - 1 */;
440                 memmove(start, eind, strlen(eind) + 1);
441         }
442 #endif
443 }
444
445 void BLI_cleanup_dir(const char *relabase, char *dir)
446 {
447         BLI_cleanup_path(relabase, dir);
448         BLI_add_slash(dir);
449
450 }
451
452 void BLI_cleanup_file(const char *relabase, char *path)
453 {
454         BLI_cleanup_path(relabase, path);
455         BLI_del_slash(path);
456 }
457
458 /**
459  * Does path begin with the special "//" prefix that Blender uses to indicate
460  * a path relative to the .blend file.
461  */
462 bool BLI_path_is_rel(const char *path)
463 {
464         return path[0] == '/' && path[1] == '/';
465 }
466
467 /* return true if the path is a UNC share */
468 bool BLI_path_is_unc(const char *name)
469 {
470         return name[0] == '\\' && name[1] == '\\';
471 }
472
473 /**
474  * Returns the length of the identifying prefix
475  * of a UNC path which can start with '\\' (short version)
476  * or '\\?\' (long version)
477  * If the path is not a UNC path, return 0
478  *
479  * \param name  the path name
480  */
481 static int BLI_path_unc_prefix_len(const char *path)
482 {
483         if (BLI_path_is_unc(path)) {
484                 if ((path[2] == '?') && (path[3] == '\\') ) {
485                         /* we assume long UNC path like \\?\server\share\folder etc... */
486                         return 4;
487                 }
488                 else {
489                         return 2;
490                 }
491         }
492
493         return 0;
494 }
495
496 #if defined(WIN32)
497
498 /* return true if the path is absolute ie starts with a drive specifier (eg A:\) or is a UNC path */
499 static bool BLI_path_is_abs(const char *name)
500 {
501         return (name[1] == ':' && (name[2] == '\\' || name[2] == '/') ) || BLI_path_is_unc(name);
502 }
503
504 static wchar_t *next_slash(wchar_t *path)
505 {
506         wchar_t *slash = path;
507         while (*slash && *slash != L'\\') slash++;
508         return slash;
509 }
510
511 /* adds a slash if the unc path points sto a share */
512 static void BLI_path_add_slash_to_share(wchar_t *uncpath)
513 {
514         wchar_t *slash_after_server = next_slash(uncpath + 2);
515         if (*slash_after_server) {
516                 wchar_t *slash_after_share = next_slash(slash_after_server + 1);
517                 if (!(*slash_after_share)) {
518                         slash_after_share[0] = L'\\';
519                         slash_after_share[1] = L'\0';
520                 }
521         }
522 }
523
524 static void BLI_path_unc_to_short(wchar_t *unc)
525 {
526         wchar_t tmp[PATH_MAX];
527
528         int len = wcslen(unc);
529         int copy_start = 0;
530         /* convert:
531          *    \\?\UNC\server\share\folder\... to \\server\share\folder\...
532          *    \\?\C:\ to C:\ and \\?\C:\folder\... to C:\folder\...
533          */
534         if ((len > 3) &&
535             (unc[0] ==  L'\\') &&
536             (unc[1] ==  L'\\') &&
537             (unc[2] ==  L'?') &&
538             ((unc[3] ==  L'\\') || (unc[3] ==  L'/')))
539         {
540                 if ((len > 5) && (unc[5] ==  L':')) {
541                         wcsncpy(tmp, unc + 4, len - 4);
542                         tmp[len - 4] = L'\0';
543                         wcscpy(unc, tmp);
544                 }
545                 else if ((len > 7) && (wcsncmp(&unc[4], L"UNC", 3) == 0) &&
546                          ((unc[7] ==  L'\\') || (unc[7] ==  L'/')))
547                 {
548                         tmp[0] = L'\\';
549                         tmp[1] = L'\\';
550                         wcsncpy(tmp + 2, unc + 8, len - 8);
551                         tmp[len - 6] = L'\0';
552                         wcscpy(unc, tmp);
553                 }
554         }
555 }
556
557 void BLI_cleanup_unc(char *path, int maxlen)
558 {
559         wchar_t *tmp_16 = alloc_utf16_from_8(path, 1);
560         BLI_cleanup_unc_16(tmp_16);
561         conv_utf_16_to_8(tmp_16, path, maxlen);
562 }
563
564 void BLI_cleanup_unc_16(wchar_t *path_16)
565 {
566         BLI_path_unc_to_short(path_16);
567         BLI_path_add_slash_to_share(path_16);
568 }
569 #endif
570
571 /**
572  * Replaces *file with a relative version (prefixed by "//") such that BLI_path_abs, given
573  * the same *relfile, will convert it back to its original value.
574  */
575 void BLI_path_rel(char *file, const char *relfile)
576 {
577         const char *lslash;
578         char temp[FILE_MAX];
579         char res[FILE_MAX];
580         
581         /* if file is already relative, bail out */
582         if (BLI_path_is_rel(file)) {
583                 return;
584         }
585         
586         /* also bail out if relative path is not set */
587         if (relfile[0] == '\0') {
588                 return;
589         }
590
591 #ifdef WIN32
592         if (BLI_strnlen(relfile, 3) > 2 && !BLI_path_is_abs(relfile)) {
593                 char *ptemp;
594                 /* fix missing volume name in relative base,
595                  * can happen with old recent-files.txt files */
596                 get_default_root(temp);
597                 ptemp = &temp[2];
598                 if (relfile[0] != '\\' && relfile[0] != '/') {
599                         ptemp++;
600                 }
601                 BLI_strncpy(ptemp, relfile, FILE_MAX - 3);
602         }
603         else {
604                 BLI_strncpy(temp, relfile, FILE_MAX);
605         }
606
607         if (BLI_strnlen(file, 3) > 2) {
608                 bool is_unc = BLI_path_is_unc(file);
609
610                 /* Ensure paths are both UNC paths or are both drives */
611                 if (BLI_path_is_unc(temp) != is_unc) {
612                         return;
613                 }
614
615                 /* Ensure both UNC paths are on the same share */
616                 if (is_unc) {
617                         int off;
618                         int slash = 0;
619                         for (off = 0; temp[off] && slash < 4; off++) {
620                                 if (temp[off] != file[off])
621                                         return;
622
623                                 if (temp[off] == '\\')
624                                         slash++;
625                         }
626                 }
627                 else if (temp[1] == ':' && file[1] == ':' && temp[0] != file[0]) {
628                         return;
629                 }
630         }
631 #else
632         BLI_strncpy(temp, relfile, FILE_MAX);
633 #endif
634
635         BLI_char_switch(temp + BLI_path_unc_prefix_len(temp), '\\', '/');
636         BLI_char_switch(file + BLI_path_unc_prefix_len(file), '\\', '/');
637         
638         /* remove /./ which confuse the following slash counting... */
639         BLI_cleanup_path(NULL, file);
640         BLI_cleanup_path(NULL, temp);
641         
642         /* the last slash in the file indicates where the path part ends */
643         lslash = BLI_last_slash(temp);
644
645         if (lslash) {
646                 /* find the prefix of the filename that is equal for both filenames.
647                  * This is replaced by the two slashes at the beginning */
648                 const char *p = temp;
649                 const char *q = file;
650                 char *r = res;
651
652 #ifdef WIN32
653                 while (tolower(*p) == tolower(*q))
654 #else
655                 while (*p == *q)
656 #endif
657                 {
658                         p++;
659                         q++;
660
661                         /* don't search beyond the end of the string
662                          * in the rare case they match */
663                         if ((*p == '\0') || (*q == '\0')) {
664                                 break;
665                         }
666                 }
667
668                 /* we might have passed the slash when the beginning of a dir matches 
669                  * so we rewind. Only check on the actual filename
670                  */
671                 if (*q != '/') {
672                         while ( (q >= file) && (*q != '/') ) { --q; --p; }
673                 }
674                 else if (*p != '/') {
675                         while ( (p >= temp) && (*p != '/') ) { --p; --q; }
676                 }
677                 
678                 r += BLI_strcpy_rlen(r, "//");
679
680                 /* p now points to the slash that is at the beginning of the part
681                  * where the path is different from the relative path. 
682                  * We count the number of directories we need to go up in the
683                  * hierarchy to arrive at the common 'prefix' of the path
684                  */
685                 if (p < temp) p = temp;
686                 while (p && p < lslash) {
687                         if (*p == '/') {
688                                 r += BLI_strcpy_rlen(r, "../");
689                         }
690                         p++;
691                 }
692
693                 /* don't copy the slash at the beginning */
694                 r += BLI_strcpy_rlen(r, q + 1);
695                 
696 #ifdef  WIN32
697                 BLI_char_switch(res + 2, '/', '\\');
698 #endif
699                 strcpy(file, res);
700         }
701 }
702
703 /**
704  * Replaces path with the path of its parent directory, returning true if
705  * it was able to find a parent directory within the pathname.
706  */
707 bool BLI_parent_dir(char *path)
708 {
709         const char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
710         char tmp[FILE_MAX + 4];
711
712         BLI_join_dirfile(tmp, sizeof(tmp), path, parent_dir);
713         BLI_cleanup_dir(NULL, tmp); /* does all the work of normalizing the path for us */
714
715         if (!BLI_testextensie(tmp, parent_dir)) {
716                 BLI_strncpy(path, tmp, sizeof(tmp));
717                 return true;
718         }
719         else {
720                 return false;
721         }
722 }
723
724 /**
725  * Looks for a sequence of "#" characters in the last slash-separated component of *path,
726  * returning the indexes of the first and one past the last character in the sequence in
727  * *char_start and *char_end respectively. Returns true if such a sequence was found.
728  */
729 static bool stringframe_chars(const char *path, int *char_start, int *char_end)
730 {
731         unsigned int ch_sta, ch_end, i;
732         /* Insert current frame: file### -> file001 */
733         ch_sta = ch_end = 0;
734         for (i = 0; path[i] != '\0'; i++) {
735                 if (path[i] == '\\' || path[i] == '/') {
736                         ch_end = 0; /* this is a directory name, don't use any hashes we found */
737                 }
738                 else if (path[i] == '#') {
739                         ch_sta = i;
740                         ch_end = ch_sta + 1;
741                         while (path[ch_end] == '#') {
742                                 ch_end++;
743                         }
744                         i = ch_end - 1; /* keep searching */
745                         
746                         /* don't break, there may be a slash after this that invalidates the previous #'s */
747                 }
748         }
749
750         if (ch_end) {
751                 *char_start = ch_sta;
752                 *char_end = ch_end;
753                 return true;
754         }
755         else {
756                 *char_start = -1;
757                 *char_end = -1;
758                 return false;
759         }
760 }
761
762 /**
763  * Ensure *path contains at least one "#" character in its last slash-separated
764  * component, appending one digits long if not.
765  */
766 static void ensure_digits(char *path, int digits)
767 {
768         char *file = (char *)BLI_last_slash(path);
769
770         if (file == NULL)
771                 file = path;
772
773         if (strrchr(file, '#') == NULL) {
774                 int len = strlen(file);
775
776                 while (digits--) {
777                         file[len++] = '#';
778                 }
779                 file[len] = '\0';
780         }
781 }
782
783 /**
784  * Replaces "#" character sequence in last slash-separated component of *path
785  * with frame as decimal integer, with leading zeroes as necessary, to make digits digits.
786  */
787 bool BLI_path_frame(char *path, int frame, int digits)
788 {
789         int ch_sta, ch_end;
790
791         if (digits)
792                 ensure_digits(path, digits);
793
794         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
795                 char tmp[FILE_MAX];
796                 BLI_snprintf(tmp, sizeof(tmp),
797                              "%.*s%.*d%s",
798                              ch_sta, path, ch_end - ch_sta, frame, path + ch_end);
799                 BLI_strncpy(path, tmp, FILE_MAX);
800                 return true;
801         }
802         return false;
803 }
804
805 /**
806  * Replaces "#" character sequence in last slash-separated component of *path
807  * with sta and end as decimal integers, with leading zeroes as necessary, to make digits
808  * digits each, with a hyphen in-between.
809  */
810 bool BLI_path_frame_range(char *path, int sta, int end, int digits)
811 {
812         int ch_sta, ch_end;
813
814         if (digits)
815                 ensure_digits(path, digits);
816
817         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
818                 char tmp[FILE_MAX];
819                 BLI_snprintf(tmp, sizeof(tmp),
820                              "%.*s%.*d-%.*d%s",
821                              ch_sta, path, ch_end - ch_sta, sta, ch_end - ch_sta, end, path + ch_end);
822                 BLI_strncpy(path, tmp, FILE_MAX);
823                 return true;
824         }
825         return false;
826 }
827
828 /**
829  * Check if we have '#' chars, usable for #BLI_path_frame, #BLI_path_frame_range
830  */
831 bool BLI_path_frame_check_chars(const char *path)
832 {
833         int ch_sta, ch_end;  /* dummy args */
834         return stringframe_chars(path, &ch_sta, &ch_end);
835 }
836
837 /**
838  * If path begins with "//", strips that and replaces it with basepath directory. Also converts
839  * a drive-letter prefix to something more sensible if this is a non-drive-letter-based system.
840  * Returns true if "//" prefix expansion was done.
841  */
842 bool BLI_path_abs(char *path, const char *basepath)
843 {
844         const bool wasrelative = BLI_path_is_rel(path);
845         char tmp[FILE_MAX];
846         char base[FILE_MAX];
847 #ifdef WIN32
848         char vol[3] = {'\0', '\0', '\0'};
849
850         BLI_strncpy(vol, path, 3);
851         /* we are checking here if we have an absolute path that is not in the current
852          * blend file as a lib main - we are basically checking for the case that a 
853          * UNIX root '/' is passed.
854          */
855         if (!wasrelative && !BLI_path_is_abs(path)) {
856                 char *p = path;
857                 get_default_root(tmp);
858                 // get rid of the slashes at the beginning of the path
859                 while (*p == '\\' || *p == '/') {
860                         p++;
861                 }
862                 strcat(tmp, p);
863         }
864         else {
865                 BLI_strncpy(tmp, path, FILE_MAX);
866         }
867 #else
868         BLI_strncpy(tmp, path, sizeof(tmp));
869         
870         /* Check for loading a windows path on a posix system
871          * in this case, there is no use in trying C:/ since it 
872          * will never exist on a unix os.
873          * 
874          * Add a / prefix and lowercase the driveletter, remove the :
875          * C:\foo.JPG -> /c/foo.JPG */
876         
877         if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2] == '\\' || tmp[2] == '/') ) {
878                 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
879                 tmp[0] = '/'; 
880                 /* '\' the slash will be converted later */
881         }
882         
883 #endif
884
885         /* push slashes into unix mode - strings entering this part are
886          * potentially messed up: having both back- and forward slashes.
887          * Here we push into one conform direction, and at the end we
888          * push them into the system specific dir. This ensures uniformity
889          * of paths and solving some problems (and prevent potential future
890          * ones) -jesterKing.
891          * For UNC paths the first characters containing the UNC prefix
892          * shouldn't be switched as we need to distinguish them from
893          * paths relative to the .blend file -elubie */
894         BLI_char_switch(tmp + BLI_path_unc_prefix_len(tmp), '\\', '/');
895
896         /* Paths starting with // will get the blend file as their base,
897          * this isn't standard in any os but is used in blender all over the place */
898         if (wasrelative) {
899                 const char *lslash;
900                 BLI_strncpy(base, basepath, sizeof(base));
901
902                 /* file component is ignored, so don't bother with the trailing slash */
903                 BLI_cleanup_path(NULL, base);
904                 lslash = BLI_last_slash(base);
905                 BLI_char_switch(base + BLI_path_unc_prefix_len(base), '\\', '/');
906
907                 if (lslash) {
908                         const int baselen = (int) (lslash - base) + 1;  /* length up to and including last "/" */
909                         /* use path for temp storage here, we copy back over it right away */
910                         BLI_strncpy(path, tmp + 2, FILE_MAX);  /* strip "//" */
911                         
912                         memcpy(tmp, base, baselen);  /* prefix with base up to last "/" */
913                         BLI_strncpy(tmp + baselen, path, sizeof(tmp) - baselen);  /* append path after "//" */
914                         BLI_strncpy(path, tmp, FILE_MAX);  /* return as result */
915                 }
916                 else {
917                         /* base doesn't seem to be a directory--ignore it and just strip "//" prefix on path */
918                         BLI_strncpy(path, tmp + 2, FILE_MAX);
919                 }
920         }
921         else {
922                 /* base ignored */
923                 BLI_strncpy(path, tmp, FILE_MAX);
924         }
925
926         BLI_cleanup_path(NULL, path);
927
928 #ifdef WIN32
929         /* skip first two chars, which in case of
930          * absolute path will be drive:/blabla and
931          * in case of relpath //blabla/. So relpath
932          * // will be retained, rest will be nice and
933          * shiny win32 backward slashes :) -jesterKing
934          */
935         BLI_char_switch(path + 2, '/', '\\');
936 #endif
937         
938         return wasrelative;
939 }
940
941
942 /**
943  * Expands path relative to the current working directory, if it was relative.
944  * Returns true if such expansion was done.
945  *
946  * \note Should only be done with command line paths.
947  * this is _not_ something blenders internal paths support like the "//" prefix
948  */
949 bool BLI_path_cwd(char *path)
950 {
951         bool wasrelative = true;
952         const int filelen = strlen(path);
953         
954 #ifdef WIN32
955         if ((filelen >= 3 && BLI_path_is_abs(path)) || BLI_path_is_unc(path))
956                 wasrelative = false;
957 #else
958         if (filelen >= 2 && path[0] == '/')
959                 wasrelative = false;
960 #endif
961         
962         if (wasrelative) {
963                 char cwd[FILE_MAX] = "";
964                 BLI_current_working_dir(cwd, sizeof(cwd)); /* in case the full path to the blend isn't used */
965                 
966                 if (cwd[0] == '\0') {
967                         printf("Could not get the current working directory - $PWD for an unknown reason.\n");
968                 }
969                 else {
970                         /* uses the blend path relative to cwd important for loading relative linked files.
971                          *
972                          * cwd should contain c:\ etc on win32 so the relbase can be NULL
973                          * relbase being NULL also prevents // being misunderstood as relative to the current
974                          * blend file which isn't a feature we want to use in this case since were dealing
975                          * with a path from the command line, rather than from inside Blender */
976
977                         char origpath[FILE_MAX];
978                         BLI_strncpy(origpath, path, FILE_MAX);
979                         
980                         BLI_make_file_string(NULL, path, cwd, origpath); 
981                 }
982         }
983         
984         return wasrelative;
985 }
986
987 /**
988  * Copies into *last the part of *dir following the second-last slash.
989  */
990 void BLI_getlastdir(const char *dir, char *last, const size_t maxlen)
991 {
992         const char *s = dir;
993         const char *lslash = NULL;
994         const char *prevslash = NULL;
995         while (*s) {
996                 if ((*s == '\\') || (*s == '/')) {
997                         prevslash = lslash;
998                         lslash = s;
999                 }
1000                 s++;
1001         }
1002         if (prevslash) {
1003                 BLI_strncpy(last, prevslash + 1, maxlen);
1004         }
1005         else {
1006                 BLI_strncpy(last, dir, maxlen);
1007         }
1008 }
1009
1010 /* This is now only used to really get the user's default document folder */
1011 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
1012  * as default location to save documents */
1013 const char *BLI_getDefaultDocumentFolder(void)
1014 {
1015 #ifndef WIN32
1016         const char * const xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR");
1017
1018         if (xdg_documents_dir)
1019                 return xdg_documents_dir;
1020
1021         return getenv("HOME");
1022 #else /* Windows */
1023         static char documentfolder[MAXPATHLEN];
1024         HRESULT hResult;
1025
1026         /* Check for %HOME% env var */
1027         if (uput_getenv("HOME", documentfolder, MAXPATHLEN)) {
1028                 if (BLI_is_dir(documentfolder)) return documentfolder;
1029         }
1030                                 
1031         /* add user profile support for WIN 2K / NT.
1032          * This is %APPDATA%, which translates to either
1033          * %USERPROFILE%\Application Data or since Vista
1034          * to %USERPROFILE%\AppData\Roaming
1035          */
1036         hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
1037                 
1038         if (hResult == S_OK) {
1039                 if (BLI_is_dir(documentfolder)) return documentfolder;
1040         }
1041                 
1042         return NULL;
1043 #endif /* WIN32 */
1044 }
1045
1046 /* NEW stuff, to be cleaned up when fully migrated */
1047 /* ************************************************************* */
1048 /* ************************************************************* */
1049
1050 // #define PATH_DEBUG
1051
1052 /* returns a formatted representation of the specified version number. Non-reentrant! */
1053 static char *blender_version_decimal(const int ver)
1054 {
1055         static char version_str[5];
1056         sprintf(version_str, "%d.%02d", ver / 100, ver % 100);
1057         return version_str;
1058 }
1059
1060 /**
1061  * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath,
1062  * returning true if result points to a directory.
1063  */
1064 static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
1065 {
1066         char tmppath[FILE_MAX];
1067         
1068         if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
1069         else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
1070
1071         /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
1072         if (folder_name)
1073                 BLI_make_file_string("/", targetpath, tmppath, folder_name);
1074         else
1075                 BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
1076         /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile)
1077          * if folder_name is specified but not otherwise? */
1078
1079         if (BLI_is_dir(targetpath)) {
1080 #ifdef PATH_DEBUG
1081                 printf("\t%s found: %s\n", __func__, targetpath);
1082 #endif
1083                 return true;
1084         }
1085         else {
1086 #ifdef PATH_DEBUG
1087                 printf("\t%s missing: %s\n", __func__, targetpath);
1088 #endif
1089                 //targetpath[0] = '\0';
1090                 return false;
1091         }
1092 }
1093
1094 /**
1095  * Puts the value of the specified environment variable into *path if it exists
1096  * and points at a directory. Returns true if this was done.
1097  */
1098 static bool test_env_path(char *path, const char *envvar)
1099 {
1100         const char *env = envvar ? getenv(envvar) : NULL;
1101         if (!env) return false;
1102         
1103         if (BLI_is_dir(env)) {
1104                 BLI_strncpy(path, env, FILE_MAX);
1105 #ifdef PATH_DEBUG
1106                 printf("\t%s env %s found: %s\n", __func__, envvar, env);
1107 #endif
1108                 return true;
1109         }
1110         else {
1111                 path[0] = '\0';
1112 #ifdef PATH_DEBUG
1113                 printf("\t%s env %s missing: %s\n", __func__, envvar, env);
1114 #endif
1115                 return false;
1116         }
1117 }
1118
1119 /**
1120  * Constructs in \a targetpath the name of a directory relative to a version-specific
1121  * subdirectory in the parent directory of the Blender executable.
1122  *
1123  * \param targetpath  String to return path
1124  * \param folder_name  Optional folder name within version-specific directory
1125  * \param subfolder_name  Optional subfolder name within folder_name
1126  * \param ver  To construct name of version-specific directory within bprogdir
1127  * \return true if such a directory exists.
1128  */
1129 static bool get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
1130 {
1131         char relfolder[FILE_MAX];
1132         
1133 #ifdef PATH_DEBUG
1134         printf("%s...\n", __func__);
1135 #endif
1136
1137         if (folder_name) {
1138                 if (subfolder_name) {
1139                         BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
1140                 }
1141                 else {
1142                         BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
1143                 }
1144         }
1145         else {
1146                 relfolder[0] = '\0';
1147         }
1148
1149         /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
1150         return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder);
1151 }
1152
1153 /**
1154  * Is this an install with user files kept together with the Blender executable and its
1155  * installation files.
1156  */
1157 static bool is_portable_install(void)
1158 {
1159         /* detect portable install by the existence of config folder */
1160         const int ver = BLENDER_VERSION;
1161         char path[FILE_MAX];
1162
1163         return get_path_local(path, "config", NULL, ver);
1164 }
1165
1166 /**
1167  * Returns the path of a folder within the user-files area.
1168  *
1169  *
1170  * \param targetpath  String to return path
1171  * \param folder_name  default name of folder within user area
1172  * \param subfolder_name  optional name of subfolder within folder
1173  * \param envvar  name of environment variable which, if defined, overrides folder_name
1174  * \param ver  Blender version, used to construct a subdirectory name
1175  * \return true if it was able to construct such a path.
1176  */
1177 static bool get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
1178 {
1179         char user_path[FILE_MAX];
1180         const char *user_base_path;
1181
1182         /* for portable install, user path is always local */
1183         if (is_portable_install())
1184                 return get_path_local(targetpath, folder_name, subfolder_name, ver);
1185         
1186         user_path[0] = '\0';
1187
1188         if (test_env_path(user_path, envvar)) {
1189                 if (subfolder_name) {
1190                         return test_path(targetpath, user_path, NULL, subfolder_name);
1191                 }
1192                 else {
1193                         BLI_strncpy(targetpath, user_path, FILE_MAX);
1194                         return true;
1195                 }
1196         }
1197
1198         user_base_path = (const char *)GHOST_getUserDir(ver, blender_version_decimal(ver));
1199         if (user_base_path)
1200                 BLI_strncpy(user_path, user_base_path, FILE_MAX);
1201
1202         if (!user_path[0])
1203                 return false;
1204         
1205 #ifdef PATH_DEBUG
1206         printf("%s: %s\n", __func__, user_path);
1207 #endif
1208         
1209         if (subfolder_name) {
1210                 return test_path(targetpath, user_path, folder_name, subfolder_name);
1211         }
1212         else {
1213                 return test_path(targetpath, user_path, NULL, folder_name);
1214         }
1215 }
1216
1217 /**
1218  * Returns the path of a folder within the Blender installation directory.
1219  *
1220  * \param targetpath  String to return path
1221  * \param folder_name  default name of folder within installation area
1222  * \param subfolder_name  optional name of subfolder within folder
1223  * \param envvar  name of environment variable which, if defined, overrides folder_name
1224  * \param ver  Blender version, used to construct a subdirectory name
1225  * \return  true if it was able to construct such a path.
1226  */
1227 static bool get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
1228 {
1229         char system_path[FILE_MAX];
1230         const char *system_base_path;
1231         char cwd[FILE_MAX];
1232         char relfolder[FILE_MAX];
1233
1234         if (folder_name) {
1235                 if (subfolder_name) {
1236                         BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
1237                 }
1238                 else {
1239                         BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
1240                 }
1241         }
1242         else {
1243                 relfolder[0] = '\0';
1244         }
1245
1246         /* first allow developer only overrides to the system path
1247          * these are only used when running blender from source */
1248
1249         /* try CWD/release/folder_name */
1250         if (BLI_current_working_dir(cwd, sizeof(cwd))) {
1251                 if (test_path(targetpath, cwd, "release", relfolder)) {
1252                         return true;
1253                 }
1254         }
1255
1256         /* try EXECUTABLE_DIR/release/folder_name */
1257         if (test_path(targetpath, bprogdir, "release", relfolder))
1258                 return true;
1259
1260         /* end developer overrides */
1261
1262
1263
1264         system_path[0] = '\0';
1265
1266         if (test_env_path(system_path, envvar)) {
1267                 if (subfolder_name) {
1268                         return test_path(targetpath, system_path, NULL, subfolder_name);
1269                 }
1270                 else {
1271                         BLI_strncpy(targetpath, system_path, FILE_MAX);
1272                         return true;
1273                 }
1274         }
1275
1276         system_base_path = (const char *)GHOST_getSystemDir(ver, blender_version_decimal(ver));
1277         if (system_base_path)
1278                 BLI_strncpy(system_path, system_base_path, FILE_MAX);
1279         
1280         if (!system_path[0])
1281                 return false;
1282         
1283 #ifdef PATH_DEBUG
1284         printf("%s: %s\n", __func__, system_path);
1285 #endif
1286         
1287         if (subfolder_name) {
1288                 /* try $BLENDERPATH/folder_name/subfolder_name */
1289                 return test_path(targetpath, system_path, folder_name, subfolder_name);
1290         }
1291         else {
1292                 /* try $BLENDERPATH/folder_name */
1293                 return test_path(targetpath, system_path, NULL, folder_name);
1294         }
1295 }
1296
1297 /* get a folder out of the 'folder_id' presets for paths */
1298 /* returns the path if found, NULL string if not */
1299 const char *BLI_get_folder(int folder_id, const char *subfolder)
1300 {
1301         const int ver = BLENDER_VERSION;
1302         static char path[FILE_MAX] = "";
1303         
1304         switch (folder_id) {
1305                 case BLENDER_DATAFILES:     /* general case */
1306                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1307                         if (get_path_local(path, "datafiles", subfolder, ver)) break;
1308                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
1309                         return NULL;
1310                         
1311                 case BLENDER_USER_DATAFILES:
1312                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1313                         return NULL;
1314                         
1315                 case BLENDER_SYSTEM_DATAFILES:
1316                         if (get_path_local(path, "datafiles", subfolder, ver)) break;
1317                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
1318                         return NULL;
1319                         
1320                 case BLENDER_USER_AUTOSAVE:
1321                         if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1322                         return NULL;
1323
1324                 case BLENDER_USER_CONFIG:
1325                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
1326                         return NULL;
1327                         
1328                 case BLENDER_USER_SCRIPTS:
1329                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
1330                         return NULL;
1331                         
1332                 case BLENDER_SYSTEM_SCRIPTS:
1333                         if (get_path_local(path, "scripts", subfolder, ver)) break;
1334                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
1335                         return NULL;
1336                         
1337                 case BLENDER_SYSTEM_PYTHON:
1338                         if (get_path_local(path, "python", subfolder, ver)) break;
1339                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
1340                         return NULL;
1341
1342                 default:
1343                         BLI_assert(0);
1344                         break;
1345         }
1346         
1347         return path;
1348 }
1349
1350 /**
1351  * Returns the path to a folder in the user area without checking that it actually exists first.
1352  */
1353 const char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
1354 {
1355         const int ver = BLENDER_VERSION;
1356         static char path[FILE_MAX] = "";
1357
1358         switch (folder_id) {
1359                 case BLENDER_USER_DATAFILES:
1360                         get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
1361                         break;
1362                 case BLENDER_USER_CONFIG:
1363                         get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
1364                         break;
1365                 case BLENDER_USER_AUTOSAVE:
1366                         get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
1367                         break;
1368                 case BLENDER_USER_SCRIPTS:
1369                         get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
1370                         break;
1371                 default:
1372                         BLI_assert(0);
1373                         break;
1374         }
1375
1376         if ('\0' == path[0]) {
1377                 return NULL;
1378         }
1379         return path;
1380 }
1381
1382 /**
1383  * Returns the path to a folder in the user area, creating it if it doesn't exist.
1384  */
1385 const char *BLI_get_folder_create(int folder_id, const char *subfolder)
1386 {
1387         const char *path;
1388
1389         /* only for user folders */
1390         if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1391                 return NULL;
1392         
1393         path = BLI_get_folder(folder_id, subfolder);
1394         
1395         if (!path) {
1396                 path = BLI_get_user_folder_notest(folder_id, subfolder);
1397                 if (path) BLI_dir_create_recursive(path);
1398         }
1399         
1400         return path;
1401 }
1402
1403 /**
1404  * Returns the path of the top-level version-specific local, user or system directory.
1405  * If do_check, then the result will be NULL if the directory doesn't exist.
1406  */
1407 const char *BLI_get_folder_version(const int id, const int ver, const bool do_check)
1408 {
1409         static char path[FILE_MAX] = "";
1410         bool ok;
1411         switch (id) {
1412                 case BLENDER_RESOURCE_PATH_USER:
1413                         ok = get_path_user(path, NULL, NULL, NULL, ver);
1414                         break;
1415                 case BLENDER_RESOURCE_PATH_LOCAL:
1416                         ok = get_path_local(path, NULL, NULL, ver);
1417                         break;
1418                 case BLENDER_RESOURCE_PATH_SYSTEM:
1419                         ok = get_path_system(path, NULL, NULL, NULL, ver);
1420                         break;
1421                 default:
1422                         path[0] = '\0'; /* in case do_check is false */
1423                         ok = false;
1424                         BLI_assert(!"incorrect ID");
1425                         break;
1426         }
1427
1428         if (!ok && do_check) {
1429                 return NULL;
1430         }
1431
1432         return path;
1433 }
1434
1435 /* End new stuff */
1436 /* ************************************************************* */
1437 /* ************************************************************* */
1438
1439
1440
1441 #ifdef PATH_DEBUG
1442 #  undef PATH_DEBUG
1443 #endif
1444
1445 /**
1446  * Sets the specified environment variable to the specified value,
1447  * and clears it if val == NULL.
1448  */
1449 void BLI_setenv(const char *env, const char *val)
1450 {
1451         /* free windows */
1452 #if (defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)
1453         char *envstr;
1454
1455         if (val)
1456                 envstr = BLI_sprintfN("%s=%s", env, val);
1457         else
1458                 envstr = BLI_sprintfN("%s=", env);
1459
1460         putenv(envstr);
1461         MEM_freeN(envstr);
1462
1463         /* non-free windows */
1464 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1465         uputenv(env, val);
1466
1467
1468 #else
1469         /* linux/osx/bsd */
1470         if (val)
1471                 setenv(env, val, 1);
1472         else
1473                 unsetenv(env);
1474 #endif
1475 }
1476
1477
1478 /**
1479  * Only set an env var if already not there.
1480  * Like Unix setenv(env, val, 0);
1481  *
1482  * (not used anywhere).
1483  */
1484 void BLI_setenv_if_new(const char *env, const char *val)
1485 {
1486         if (getenv(env) == NULL)
1487                 BLI_setenv(env, val);
1488 }
1489
1490
1491 /**
1492  * Changes to the path separators to the native ones for this OS.
1493  */
1494 void BLI_clean(char *path)
1495 {
1496 #ifdef WIN32
1497         if (path && BLI_strnlen(path, 3) > 2) {
1498                 BLI_char_switch(path + 2, '/', '\\');
1499         }
1500 #else
1501         BLI_char_switch(path + BLI_path_unc_prefix_len(path), '\\', '/');
1502 #endif
1503 }
1504
1505 /**
1506  * Change every \a from in \a string into \a to. The
1507  * result will be in \a string
1508  *
1509  * \param string The string to work on
1510  * \param from The character to replace
1511  * \param to The character to replace with
1512  */
1513 void BLI_char_switch(char *string, char from, char to) 
1514 {
1515         while (*string != 0) {
1516                 if (*string == from) *string = to;
1517                 string++;
1518         }
1519 }
1520
1521 /**
1522  * Strips off nonexistent subdirectories from the end of *dir, leaving the path of
1523  * the lowest-level directory that does exist.
1524  */
1525 void BLI_make_exist(char *dir)
1526 {
1527         int a;
1528
1529         BLI_char_switch(dir, ALTSEP, SEP);
1530
1531         a = strlen(dir);
1532
1533         while (!BLI_is_dir(dir)) {
1534                 a--;
1535                 while (dir[a] != SEP) {
1536                         a--;
1537                         if (a <= 0) break;
1538                 }
1539                 if (a >= 0) {
1540                         dir[a + 1] = '\0';
1541                 }
1542                 else {
1543 #ifdef WIN32
1544                         get_default_root(dir);
1545 #else
1546                         strcpy(dir, "/");
1547 #endif
1548                         break;
1549                 }
1550         }
1551 }
1552
1553 /**
1554  * Ensures that the parent directory of *name exists.
1555  */
1556 void BLI_make_existing_file(const char *name)
1557 {
1558         char di[FILE_MAX];
1559         BLI_split_dir_part(name, di, sizeof(di));
1560
1561         /* make if if the dir doesn't exist */
1562         BLI_dir_create_recursive(di);
1563 }
1564
1565 /**
1566  * Returns in *string the concatenation of *dir and *file (also with *relabase on the
1567  * front if specified and *dir begins with "//"). Normalizes all occurrences of path
1568  * separators, including ensuring there is exactly one between the copies of *dir and *file,
1569  * and between the copies of *relabase and *dir.
1570  *
1571  * \param relabase  Optional prefix to substitute for "//" on front of *dir
1572  * \param string  Area to return result
1573  */
1574 void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file)
1575 {
1576         int sl;
1577
1578         if (string) {
1579                 /* ensure this is always set even if dir/file are NULL */
1580                 string[0] = '\0';
1581
1582                 if (ELEM(NULL, dir, file)) {
1583                         return; /* We don't want any NULLs */
1584                 }
1585         }
1586         else {
1587                 return; /* string is NULL, probably shouldnt happen but return anyway */
1588         }
1589
1590
1591         /* we first push all slashes into unix mode, just to make sure we don't get
1592          * any mess with slashes later on. -jesterKing */
1593         /* constant strings can be passed for those parameters - don't change them - elubie */
1594 #if 0
1595         BLI_char_switch(relabase, '\\', '/');
1596         BLI_char_switch(dir, '\\', '/');
1597         BLI_char_switch(file, '\\', '/');
1598 #endif
1599
1600         /* Resolve relative references */
1601         if (relabase && dir[0] == '/' && dir[1] == '/') {
1602                 char *lslash;
1603                 
1604                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1605                 strcpy(string, relabase);
1606                 
1607                 lslash = (char *)BLI_last_slash(string);
1608                 if (lslash) *(lslash + 1) = 0;
1609
1610                 dir += 2; /* Skip over the relative reference */
1611         }
1612 #ifdef WIN32
1613         else {
1614                 if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':') {
1615                         BLI_strncpy(string, dir, 3);
1616                         dir += 2;
1617                 }
1618                 else if (BLI_strnlen(dir, 3) >= 2 && BLI_path_is_unc(dir)) {
1619                         string[0] = 0;
1620                 }
1621                 else { /* no drive specified */
1622                            /* first option: get the drive from the relabase if it has one */
1623                         if (relabase && BLI_strnlen(relabase, 3) >= 2 && relabase[1] == ':') {
1624                                 BLI_strncpy(string, relabase, 3);
1625                                 string[2] = '\\';
1626                                 string[3] = '\0';
1627                         }
1628                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1629                                 get_default_root(string);
1630                         }
1631                         
1632                         /* ignore leading slashes */
1633                         while (*dir == '/' || *dir == '\\') dir++;
1634                 }
1635         }
1636 #endif
1637
1638         strcat(string, dir);
1639
1640         /* Make sure string ends in one (and only one) slash */
1641         /* first trim all slashes from the end of the string */
1642         sl = strlen(string);
1643         while (sl > 0 && (string[sl - 1] == '/' || string[sl - 1] == '\\') ) {
1644                 string[sl - 1] = '\0';
1645                 sl--;
1646         }
1647         /* since we've now removed all slashes, put back one slash at the end. */
1648         strcat(string, "/");
1649         
1650         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1651                 file++;
1652                 
1653         strcat(string, file);
1654         
1655         /* Push all slashes to the system preferred direction */
1656         BLI_clean(string);
1657 }
1658
1659 static bool testextensie_ex(const char *str, const size_t str_len,
1660                             const char *ext, const size_t ext_len)
1661 {
1662         BLI_assert(strlen(str) == str_len);
1663         BLI_assert(strlen(ext) == ext_len);
1664
1665         return  (((str_len == 0 || ext_len == 0 || ext_len >= str_len) == 0) &&
1666                  (BLI_strcasecmp(ext, str + str_len - ext_len) == 0));
1667 }
1668
1669 /* does str end with ext. */
1670 bool BLI_testextensie(const char *str, const char *ext)
1671 {
1672         return testextensie_ex(str, strlen(str), ext, strlen(ext));
1673 }
1674
1675 bool BLI_testextensie_n(const char *str, ...)
1676 {
1677         const size_t str_len = strlen(str);
1678
1679         va_list args;
1680         const char *ext;
1681         bool ret = false;
1682
1683         va_start(args, str);
1684
1685         while ((ext = (const char *) va_arg(args, void *))) {
1686                 if (testextensie_ex(str, str_len, ext, strlen(ext))) {
1687                         ret = true;
1688                         goto finally;
1689                 }
1690         }
1691
1692 finally:
1693         va_end(args);
1694
1695         return ret;
1696 }
1697
1698 /* does str end with any of the suffixes in *ext_array. */
1699 bool BLI_testextensie_array(const char *str, const char **ext_array)
1700 {
1701         const size_t str_len = strlen(str);
1702         int i = 0;
1703
1704         while (ext_array[i]) {
1705                 if (testextensie_ex(str, str_len, ext_array[i], strlen(ext_array[i]))) {
1706                         return true;
1707                 }
1708
1709                 i++;
1710         }
1711         return false;
1712 }
1713
1714 /**
1715  * Semicolon separated wildcards, eg:
1716  *  '*.zip;*.py;*.exe'
1717  * does str match any of the semicolon-separated glob patterns in fnmatch.
1718  */
1719 bool BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1720 {
1721         const char *ext_step = ext_fnmatch;
1722         char pattern[16];
1723
1724         while (ext_step[0]) {
1725                 const char *ext_next;
1726                 int len_ext;
1727
1728                 if ((ext_next = strchr(ext_step, ';'))) {
1729                         len_ext = (int)(ext_next - ext_step) + 1;
1730                 }
1731                 else {
1732                         len_ext = sizeof(pattern);
1733                 }
1734
1735                 BLI_strncpy(pattern, ext_step, len_ext);
1736
1737                 if (fnmatch(pattern, str, FNM_CASEFOLD) == 0) {
1738                         return true;
1739                 }
1740                 ext_step += len_ext;
1741         }
1742
1743         return false;
1744 }
1745
1746
1747 /**
1748  * Removes any existing extension on the end of \a path and appends \a ext.
1749  * \return false if there was no room.
1750  */
1751 bool BLI_replace_extension(char *path, size_t maxlen, const char *ext)
1752 {
1753         const size_t path_len = strlen(path);
1754         const size_t ext_len = strlen(ext);
1755         ssize_t a;
1756
1757         for (a = path_len - 1; a >= 0; a--) {
1758                 if (ELEM3(path[a], '.', '/', '\\')) {
1759                         break;
1760                 }
1761         }
1762
1763         if ((a < 0) || (path[a] != '.')) {
1764                 a = path_len;
1765         }
1766
1767         if (a + ext_len >= maxlen)
1768                 return false;
1769
1770         memcpy(path + a, ext, ext_len + 1);
1771         return true;
1772 }
1773
1774 /**
1775  * Strip's trailing '.'s and adds the extension only when needed
1776  */
1777 bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext)
1778 {
1779         const size_t path_len = strlen(path);
1780         const size_t ext_len = strlen(ext);
1781         ssize_t a;
1782
1783         /* first check the extension is already there */
1784         if (    (ext_len <= path_len) &&
1785                 (strcmp(path + (path_len - ext_len), ext) == 0))
1786         {
1787                 return true;
1788         }
1789
1790         for (a = path_len - 1; a >= 0; a--) {
1791                 if (path[a] == '.') {
1792                         path[a] = '\0';
1793                 }
1794                 else {
1795                         break;
1796                 }
1797         }
1798         a++;
1799
1800         if (a + ext_len >= maxlen)
1801                 return false;
1802
1803         memcpy(path + a, ext, ext_len + 1);
1804         return true;
1805 }
1806
1807 bool BLI_ensure_filename(char *filepath, size_t maxlen, const char *filename)
1808 {
1809         char *c = (char *)BLI_last_slash(filepath);
1810         if (!c || ((c - filepath) < maxlen - (strlen(filename) + 1))) {
1811                 strcpy(c ? &c[1] : filepath, filename);
1812                 return true;
1813         }
1814         return false;
1815 }
1816
1817 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1818  * - wont change 'string'
1819  * - wont create any directories
1820  * - dosnt use CWD, or deal with relative paths.
1821  * - Only fill's in *dir and *file when they are non NULL
1822  * */
1823 void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
1824 {
1825         const char *lslash_str = BLI_last_slash(string);
1826         const size_t lslash = lslash_str ? (size_t)(lslash_str - string) + 1 : 0;
1827
1828         if (dir) {
1829                 if (lslash) {
1830                         BLI_strncpy(dir, string, MIN2(dirlen, lslash + 1)); /* +1 to include the slash and the last char */
1831                 }
1832                 else {
1833                         dir[0] = '\0';
1834                 }
1835         }
1836         
1837         if (file) {
1838                 BLI_strncpy(file, string + lslash, filelen);
1839         }
1840 }
1841
1842 /**
1843  * Copies the parent directory part of string into *dir, max length dirlen.
1844  */
1845 void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen)
1846 {
1847         BLI_split_dirfile(string, dir, NULL, dirlen, 0);
1848 }
1849
1850 /**
1851  * Copies the leaf filename part of string into *file, max length filelen.
1852  */
1853 void BLI_split_file_part(const char *string, char *file, const size_t filelen)
1854 {
1855         BLI_split_dirfile(string, NULL, file, 0, filelen);
1856 }
1857
1858 /**
1859  * Append a filename to a dir, ensuring slash separates.
1860  */
1861 void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file)
1862 {
1863         size_t dirlen = BLI_strnlen(dst, maxlen);
1864
1865         /* inline BLI_add_slash */
1866         if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) {
1867                 dst[dirlen++] = SEP;
1868                 dst[dirlen] = '\0';
1869         }
1870
1871         if (dirlen >= maxlen) {
1872                 return; /* fills the path */
1873         }
1874
1875         BLI_strncpy(dst + dirlen, file, maxlen - dirlen);
1876 }
1877
1878 /**
1879  * Simple appending of filename to dir, does not check for valid path!
1880  * Puts result into *dst, which may be same area as *dir.
1881  */
1882 void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__restrict dir, const char *__restrict file)
1883 {
1884         size_t dirlen = BLI_strnlen(dir, maxlen);
1885
1886         /* args can't match */
1887         BLI_assert(!ELEM(dst, dir, file));
1888
1889         if (dirlen == maxlen) {
1890                 memcpy(dst, dir, dirlen);
1891                 dst[dirlen - 1] = '\0';
1892                 return; /* dir fills the path */
1893         }
1894         else {
1895                 memcpy(dst, dir, dirlen + 1);
1896         }
1897
1898         if (dirlen + 1 >= maxlen) {
1899                 return; /* fills the path */
1900         }
1901
1902         /* inline BLI_add_slash */
1903         if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) {
1904                 dst[dirlen++] = SEP;
1905                 dst[dirlen] = '\0';
1906         }
1907
1908         if (dirlen >= maxlen) {
1909                 return; /* fills the path */
1910         }
1911
1912         BLI_strncpy(dst + dirlen, file, maxlen - dirlen);
1913 }
1914
1915 /**
1916  * like pythons os.path.basename()
1917  *
1918  * \return The pointer into \a path string immediately after last slash,
1919  * or start of \a path if none found.
1920  */
1921 const char *BLI_path_basename(const char *path)
1922 {
1923         const char * const filename = BLI_last_slash(path);
1924         return filename ? filename + 1 : path;
1925 }
1926
1927 /**
1928  * Produce image export path.
1929  * 
1930  * Returns:
1931  * 0        if image filename is empty or if destination path
1932  *          matches image path (i.e. both are the same file).
1933  * 2        if source is identical to destination.
1934  * 1        if rebase was successful
1935  * -------------------------------------------------------------
1936  * Hint: Trailing slash in dest_dir is optional.
1937  *
1938  * Logic:
1939  *
1940  * - if an image is "below" current .blend file directory:
1941  *   rebuild the same dir structure in dest_dir
1942  *
1943  *   Example: 
1944  *   src : //textures/foo/bar.png
1945  *   dest: [dest_dir]/textures/foo/bar.png.
1946  *
1947  * - if an image is not "below" current .blend file directory,
1948  *   disregard it's path and copy it into the destination  
1949  *   directory.
1950  *
1951  *   Example:
1952  *   src : //../foo/bar.png becomes
1953  *   dest: [dest_dir]/bar.png.
1954  *
1955  * This logic ensures that all image paths are relative and
1956  * that a user gets his images in one place. It'll also provide
1957  * consistent behavior across exporters.
1958  * IMPORTANT NOTE: If base_dir contains an empty string, then
1959  * this function returns wrong results!
1960  * XXX: test on empty base_dir and return an error ?
1961  */
1962
1963 /**
1964  *
1965  * \param abs  Optional string to return new full path
1966  * \param abs_len  Size of *abs string
1967  * \param rel  Optional area to return new path relative to parent directory of .blend file
1968  *             (only meaningful if item is in a subdirectory thereof)
1969  * \param rel_len  Size of *rel area
1970  * \param base_dir  Path of .blend file
1971  * \param src_dir  Original path of item (any initial "//" will be expanded to
1972  *                 parent directory of .blend file)
1973  * \param dest_dir  New directory into which item will be moved
1974  * \return bli_rebase_state
1975  *
1976  * \note Not actually used anywhere!
1977  */
1978 int BLI_rebase_path(char *abs, size_t abs_len,
1979                     char *rel, size_t rel_len,
1980                     const char *base_dir, const char *src_dir, const char *dest_dir)
1981 {
1982         char path[FILE_MAX];  /* original full path of item */
1983         char dir[FILE_MAX];   /* directory part of src_dir */
1984         char base[FILE_MAX];  /* basename part of src_dir */
1985         char blend_dir[FILE_MAX];   /* directory, where current .blend file resides */
1986         char dest_path[FILE_MAX];
1987         char rel_dir[FILE_MAX];
1988         int len;
1989
1990         if (abs)
1991                 abs[0] = 0;
1992
1993         if (rel)
1994                 rel[0] = 0;
1995
1996         BLI_split_dir_part(base_dir, blend_dir, sizeof(blend_dir));
1997
1998         if (src_dir[0] == '\0')
1999                 return BLI_REBASE_NO_SRCDIR;
2000
2001         BLI_strncpy(path, src_dir, sizeof(path));
2002
2003         /* expand "//" in filename and get absolute path */
2004         BLI_path_abs(path, base_dir);
2005
2006         /* get the directory part */
2007         BLI_split_dirfile(path, dir, base, sizeof(dir), sizeof(base));
2008
2009         len = strlen(blend_dir);
2010
2011         rel_dir[0] = 0;
2012
2013         /* if image is "below" current .blend file directory */
2014         if (!BLI_path_ncmp(path, blend_dir, len)) {
2015
2016                 if (BLI_path_cmp(dir, blend_dir) == 0) {
2017                         /* image is directly in .blend file parent directory => put directly in dest_dir */
2018                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
2019                 }
2020                 else {
2021                         /* "below" (in subdirectory of .blend file parent directory) => put in same relative directory structure in dest_dir */
2022                         /* rel = image_path_dir - blend_dir */
2023                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
2024                         /* subdirectories relative to blend_dir */
2025                         BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir);
2026                         /* same subdirectories relative to dest_dir */
2027                         BLI_path_append(dest_path, sizeof(dest_path), base);
2028                         /* keeping original item basename */
2029                 }
2030
2031         }
2032         /* image is out of current directory -- just put straight in dest_dir */
2033         else {
2034                 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
2035         }
2036
2037         if (abs)
2038                 BLI_strncpy(abs, dest_path, abs_len);
2039
2040         if (rel) {
2041                 strncat(rel, rel_dir, rel_len);
2042                 strncat(rel, base, rel_len); /* FIXME: could overflow rel area! */
2043         }
2044
2045         /* return 2 if (src == dest) */
2046         if (BLI_path_cmp(path, dest_path) == 0) {
2047                 // if (G.debug & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
2048                 return BLI_REBASE_IDENTITY;
2049         }
2050
2051         return BLI_REBASE_OK;
2052 }
2053
2054 /**
2055  * Returns pointer to the leftmost path separator in string. Not actually used anywhere.
2056  */
2057 const char *BLI_first_slash(const char *string)
2058 {
2059         const char * const ffslash = strchr(string, '/');
2060         const char * const fbslash = strchr(string, '\\');
2061         
2062         if (!ffslash) return fbslash;
2063         else if (!fbslash) return ffslash;
2064         
2065         if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
2066         else return fbslash;
2067 }
2068
2069 /**
2070  * Returns pointer to the rightmost path separator in string.
2071  */
2072 const char *BLI_last_slash(const char *string)
2073 {
2074         const char * const lfslash = strrchr(string, '/');
2075         const char * const lbslash = strrchr(string, '\\');
2076
2077         if (!lfslash) return lbslash; 
2078         else if (!lbslash) return lfslash;
2079         
2080         if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
2081         else return lfslash;
2082 }
2083
2084 /**
2085  * Appends a slash to string if there isn't one there already.
2086  * Returns the new length of the string.
2087  */
2088 int BLI_add_slash(char *string)
2089 {
2090         int len = strlen(string);
2091         if (len == 0 || string[len - 1] != SEP) {
2092                 string[len] = SEP;
2093                 string[len + 1] = '\0';
2094                 return len + 1;
2095         }
2096         return len;
2097 }
2098
2099 /**
2100  * Removes the last slash and everything after it to the end of string, if there is one.
2101  */
2102 void BLI_del_slash(char *string)
2103 {
2104         int len = strlen(string);
2105         while (len) {
2106                 if (string[len - 1] == SEP) {
2107                         string[len - 1] = '\0';
2108                         len--;
2109                 }
2110                 else {
2111                         break;
2112                 }
2113         }
2114 }
2115
2116 /**
2117  * Tries appending each of the semicolon-separated extensions in the PATHEXT
2118  * environment variable (Windows-only) onto *name in turn until such a file is found.
2119  * Returns success/failure.
2120  */
2121 static int add_win32_extension(char *name)
2122 {
2123         int retval = 0;
2124         int type;
2125
2126         type = BLI_exists(name);
2127         if ((type == 0) || S_ISDIR(type)) {
2128 #ifdef _WIN32
2129                 char filename[FILE_MAX];
2130                 char ext[FILE_MAX];
2131                 const char *extensions = getenv("PATHEXT");
2132                 if (extensions) {
2133                         char *temp;
2134                         do {
2135                                 strcpy(filename, name);
2136                                 temp = strstr(extensions, ";");
2137                                 if (temp) {
2138                                         strncpy(ext, extensions, temp - extensions);
2139                                         ext[temp - extensions] = 0;
2140                                         extensions = temp + 1;
2141                                         strcat(filename, ext);
2142                                 }
2143                                 else {
2144                                         strcat(filename, extensions);
2145                                 }
2146
2147                                 type = BLI_exists(filename);
2148                                 if (type && (!S_ISDIR(type))) {
2149                                         retval = 1;
2150                                         strcpy(name, filename);
2151                                         break;
2152                                 }
2153                         } while (temp);
2154                 }
2155 #endif
2156         }
2157         else {
2158                 retval = 1;
2159         }
2160
2161         return (retval);
2162 }
2163
2164 /**
2165  * Checks if name is a fully qualified filename to an executable.
2166  * If not it searches $PATH for the file. On Windows it also
2167  * adds the correct extension (.com .exe etc) from
2168  * $PATHEXT if necessary. Also on Windows it translates
2169  * the name to its 8.3 version to prevent problems with
2170  * spaces and stuff. Final result is returned in fullname.
2171  *
2172  * \param fullname The full path and full name of the executable
2173  * (must be FILE_MAX minimum)
2174  * \param name The name of the executable (usually argv[0]) to be checked
2175  */
2176 static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name)
2177 {
2178         char filename[FILE_MAX];
2179         const char *path = NULL, *temp;
2180
2181 #ifdef _WIN32
2182         const char *separator = ";";
2183 #else
2184         const char *separator = ":";
2185 #endif
2186
2187         
2188 #ifdef WITH_BINRELOC
2189         /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
2190         path = br_find_exe(NULL);
2191         if (path) {
2192                 BLI_strncpy(fullname, path, maxlen);
2193                 free((void *)path);
2194                 return;
2195         }
2196 #endif
2197
2198 #ifdef _WIN32
2199         wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath");
2200         if (GetModuleFileNameW(0, fullname_16, maxlen)) {
2201                 conv_utf_16_to_8(fullname_16, fullname, maxlen);
2202                 if (!BLI_exists(fullname)) {
2203                         printf("path can't be found: \"%.*s\"\n", (int)maxlen, fullname);
2204                         MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
2205                 }
2206                 MEM_freeN(fullname_16);
2207                 return;
2208         }
2209
2210         MEM_freeN(fullname_16);
2211 #endif
2212
2213         /* unix and non linux */
2214         if (name && name[0]) {
2215
2216                 BLI_strncpy(fullname, name, maxlen);
2217                 if (name[0] == '.') {
2218                         char wdir[FILE_MAX] = "";
2219                         BLI_current_working_dir(wdir, sizeof(wdir));     /* backup cwd to restore after */
2220
2221                         // not needed but avoids annoying /./ in name
2222                         if (name[1] == SEP)
2223                                 BLI_join_dirfile(fullname, maxlen, wdir, name + 2);
2224                         else
2225                                 BLI_join_dirfile(fullname, maxlen, wdir, name);
2226
2227                         add_win32_extension(fullname); /* XXX, doesnt respect length */
2228                 }
2229                 else if (BLI_last_slash(name)) {
2230                         // full path
2231                         BLI_strncpy(fullname, name, maxlen);
2232                         add_win32_extension(fullname);
2233                 }
2234                 else {
2235                         // search for binary in $PATH
2236                         path = getenv("PATH");
2237                         if (path) {
2238                                 do {
2239                                         temp = strstr(path, separator);
2240                                         if (temp) {
2241                                                 strncpy(filename, path, temp - path);
2242                                                 filename[temp - path] = 0;
2243                                                 path = temp + 1;
2244                                         }
2245                                         else {
2246                                                 strncpy(filename, path, sizeof(filename));
2247                                         }
2248                                         BLI_path_append(fullname, maxlen, name);
2249                                         if (add_win32_extension(filename)) {
2250                                                 BLI_strncpy(fullname, filename, maxlen);
2251                                                 break;
2252                                         }
2253                                 } while (temp);
2254                         }
2255                 }
2256 #if defined(DEBUG)
2257                 if (strcmp(name, fullname)) {
2258                         printf("guessing '%s' == '%s'\n", name, fullname);
2259                 }
2260 #endif
2261         }
2262 }
2263
2264 void BLI_init_program_path(const char *argv0)
2265 {
2266         bli_where_am_i(bprogname, sizeof(bprogname), argv0);
2267         BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir));
2268 }
2269
2270 /**
2271  * Path to executable
2272  */
2273 const char *BLI_program_path(void)
2274 {
2275         return bprogname;
2276 }
2277
2278 /**
2279  * Path to directory of executable
2280  */
2281 const char *BLI_program_dir(void)
2282 {
2283         return bprogdir;
2284 }
2285
2286 /**
2287  * Gets the temp directory when blender first runs.
2288  * If the default path is not found, use try $TEMP
2289  * 
2290  * Also make sure the temp dir has a trailing slash
2291  *
2292  * \param fullname The full path to the temp directory
2293  * \param maxlen The size of the fullname buffer
2294  * \param userdir Directory specified in user preferences 
2295  */
2296 static void BLI_where_is_temp(char *fullname, const size_t maxlen, char *userdir)
2297 {
2298         fullname[0] = '\0';
2299         
2300         if (userdir && BLI_is_dir(userdir)) {
2301                 BLI_strncpy(fullname, userdir, maxlen);
2302         }
2303         
2304         
2305 #ifdef WIN32
2306         if (fullname[0] == '\0') {
2307                 const char *tmp = getenv("TEMP"); /* Windows */
2308                 if (tmp && BLI_is_dir(tmp)) {
2309                         BLI_strncpy(fullname, tmp, maxlen);
2310                 }
2311         }
2312 #else
2313         /* Other OS's - Try TMP and TMPDIR */
2314         if (fullname[0] == '\0') {
2315                 const char *tmp = getenv("TMP");
2316                 if (tmp && BLI_is_dir(tmp)) {
2317                         BLI_strncpy(fullname, tmp, maxlen);
2318                 }
2319         }
2320         
2321         if (fullname[0] == '\0') {
2322                 const char *tmp = getenv("TMPDIR");
2323                 if (tmp && BLI_is_dir(tmp)) {
2324                         BLI_strncpy(fullname, tmp, maxlen);
2325                 }
2326         }
2327 #endif
2328         
2329         if (fullname[0] == '\0') {
2330                 BLI_strncpy(fullname, "/tmp/", maxlen);
2331         }
2332         else {
2333                 /* add a trailing slash if needed */
2334                 BLI_add_slash(fullname);
2335 #ifdef WIN32
2336                 if (userdir && userdir != fullname) {
2337                         BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
2338                 }
2339 #endif
2340         }
2341 }
2342
2343 /**
2344  * Sets btempdir to userdir if specified and is a valid directory, otherwise
2345  * chooses a suitable OS-specific temporary directory.
2346  */
2347 void BLI_init_temporary_dir(char *userdir)
2348 {
2349         BLI_where_is_temp(btempdir, FILE_MAX, userdir);
2350 }
2351
2352 /**
2353  * Path to temporary directory (with trailing slash)
2354  */
2355 const char *BLI_temporary_dir(void)
2356 {
2357         return btempdir;
2358 }
2359
2360 /**
2361  * Path to the system temporary directory (with trailing slash)
2362  */
2363 void BLI_system_temporary_dir(char *dir)
2364 {
2365         BLI_where_is_temp(dir, FILE_MAX, NULL);
2366 }
2367
2368 #ifdef WITH_ICONV
2369
2370 /**
2371  * Converts a string encoded in the charset named by *code to UTF-8.
2372  * Opens a new iconv context each time it is run, which is probably not the
2373  * most efficient. */
2374 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
2375 {
2376         size_t inbytesleft = strlen(original);
2377         size_t outbytesleft = 512;
2378         size_t rv = 0;
2379         iconv_t cd;
2380         
2381         if (NULL == code) {
2382                 code = locale_charset();
2383         }
2384         cd = iconv_open("UTF-8", code);
2385
2386         if (cd == (iconv_t)(-1)) {
2387                 printf("iconv_open Error");
2388                 *utf_8 = '\0';
2389                 return;
2390         }
2391         rv = iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
2392         if (rv == (size_t) -1) {
2393                 printf("iconv Error\n");
2394                 iconv_close(cd);
2395                 return;
2396         }
2397         *utf_8 = '\0';
2398         iconv_close(cd);
2399 }
2400 #endif // WITH_ICONV