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