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