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