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