build systems have been updated, remove use of ~/.blender/ directly, ~/.blender...
[blender.git] / source / blender / blenlib / intern / path_util.c
1 /**
2  *  $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  * various string, file, list operations.
30  */
31
32 #include <ctype.h>
33 #include <string.h>
34 #include <stdlib.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_userdef_types.h"
39
40 #include "BLI_fileops.h"
41 #include "BLI_path_util.h"
42 #include "BLI_string.h"
43 #include "BLI_storage.h"
44 #include "BLI_storage_types.h"
45
46 #include "BKE_utildefines.h"
47 #include "BKE_blender.h"        // BLENDER_VERSION
48
49 #include "GHOST_Path-api.h"
50
51 #if defined WIN32 && !defined _LIBC
52 # include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
53 #else
54 # define _GNU_SOURCE
55 # include <fnmatch.h>
56 #endif
57
58 #ifdef WIN32
59 #include <io.h>
60
61 #ifdef _WIN32_IE
62 #undef _WIN32_IE
63 #endif
64 #define _WIN32_IE 0x0501
65 #include <windows.h>
66 #include <shlobj.h>
67
68 #include "BLI_winstuff.h"
69
70 #else /* non windows */
71
72 #ifdef __linux__
73 #include "binreloc.h"
74 #endif
75
76 #endif /* WIN32 */
77
78 /* local */
79
80 static int add_win32_extension(char *name);
81 static char *blender_version_decimal(void);
82
83 /* implementation */
84
85 int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
86 {
87         unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0;
88         short i, found = 0;
89         char *lslash = BLI_last_slash(string);
90         len2 = len = strlen(string);
91         if(lslash)
92                 lenlslash= (int)(lslash - string);
93
94         while(len > lenlslash && string[--len] != '.') {};
95         if(len == lenlslash && string[len] != '.') len = len2;
96
97         for (i = len - 1; i >= lenlslash; i--) {
98                 if (isdigit(string[i])) {
99                         if (found){
100                                 nums = i;
101                         }
102                         else{
103                                 nume = i;
104                                 nums = i;
105                                 found = 1;
106                         }
107                 }
108                 else {
109                         if (found) break;
110                 }
111         }
112         if (found) {
113                 if (tail) strcpy(tail, &string[nume+1]);
114                 if (head) {
115                         strcpy(head,string);
116                         head[nums]=0;
117                 }
118                 if (numlen) *numlen = nume-nums+1;
119                 return ((int)atoi(&(string[nums])));
120         }
121         if (tail) strcpy(tail, string + len);
122         if (head) {
123                 strncpy(head, string, len);
124                 head[len] = '\0';
125         }
126         if (numlen) *numlen=0;
127         return 0;
128 }
129
130
131 void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
132 {
133         char fmtstr[16]="";
134         if(pic < 0) pic= 0;
135         sprintf(fmtstr, "%%s%%.%dd%%s", numlen);
136         sprintf(string, fmtstr, head, pic, tail);
137 }
138
139
140 void BLI_newname(char *name, int add)
141 {
142         char head[128], tail[128];
143         int pic;
144         unsigned short digits;
145         
146         pic = BLI_stringdec(name, head, tail, &digits);
147         
148         /* are we going from 100 -> 99 or from 10 -> 9 */
149         if (add < 0 && digits < 4 && digits > 0) {
150                 int i, exp;
151                 exp = 1;
152                 for (i = digits; i > 1; i--) exp *= 10;
153                 if (pic >= exp && (pic + add) < exp) digits--;
154         }
155         
156         pic += add;
157         
158         if (digits==4 && pic<0) pic= 0;
159         BLI_stringenc(name, head, tail, digits, pic);
160 }
161
162 /* little helper macro for BLI_uniquename */
163 #ifndef GIVE_STRADDR
164         #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset )
165 #endif
166
167 /* Generic function to set a unique name. It is only designed to be used in situations
168  * where the name is part of the struct, and also that the name is at most 128 chars long.
169  * 
170  * For places where this is used, see constraint.c for example...
171  *
172  *      name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
173  *      len: maximum length of string (to prevent overflows, etc.)
174  *      defname: the name that should be used by default if none is specified already
175  *      delim: the character which acts as a delimeter between parts of the name
176  */
177 void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short len)
178 {
179         Link *link;
180         char tempname[128];
181         int     number = 1, exists = 0;
182         char *dot;
183         
184         /* Make sure length can be handled */
185         if ((len < 0) || (len > 128))
186                 return;
187         
188         /* See if we are given an empty string */
189         if (ELEM(NULL, vlink, defname))
190                 return;
191         
192         if (GIVE_STRADDR(vlink, name_offs) == '\0') {
193                 /* give it default name first */
194                 BLI_strncpy(GIVE_STRADDR(vlink, name_offs), defname, len);
195         }
196         
197         /* See if we even need to do this */
198         if (list == NULL)
199                 return;
200         
201         for (link = list->first; link; link= link->next) {
202                 if (link != vlink) {
203                         if (!strcmp(GIVE_STRADDR(link, name_offs), GIVE_STRADDR(vlink, name_offs))) {
204                                 exists = 1;
205                                 break;
206                         }
207                 }
208         }
209         if (exists == 0)
210                 return;
211
212         /* Strip off the suffix */
213         dot = strrchr(GIVE_STRADDR(vlink, name_offs), delim);
214         if (dot)
215                 *dot=0;
216         
217         for (number = 1; number <= 999; number++) {
218                 BLI_snprintf(tempname, sizeof(tempname), "%s%c%03d", GIVE_STRADDR(vlink, name_offs), delim, number);
219                 
220                 exists = 0;
221                 for (link= list->first; link; link= link->next) {
222                         if (vlink != link) {
223                                 if (!strcmp(GIVE_STRADDR(link, name_offs), tempname)) {
224                                         exists = 1;
225                                         break;
226                                 }
227                         }
228                 }
229                 if (exists == 0) {
230                         BLI_strncpy(GIVE_STRADDR(vlink, name_offs), tempname, len);
231                         return;
232                 }
233         }
234 }
235
236 /* ******************** string encoding ***************** */
237
238 /* This is quite an ugly function... its purpose is to
239  * take the dir name, make it absolute, and clean it up, replacing
240  * excess file entry stuff (like /tmp/../tmp/../)
241  * note that dir isn't protected for max string names... 
242  * 
243  * If relbase is NULL then its ignored
244  */
245
246 void BLI_cleanup_dir(const char *relabase, char *dir)
247 {
248         BLI_cleanup_file(relabase, dir);
249         BLI_add_slash(dir);
250
251 }
252
253 void BLI_cleanup_file(const char *relabase, char *dir)
254 {
255         short a;
256         char *start, *eind;
257         if (relabase) {
258                 BLI_path_abs(dir, relabase);
259         } else {
260                 if (dir[0]=='/' && dir[1]=='/') {
261                         if (dir[2]== '\0') {
262                                 return; /* path is "//" - cant clean it */
263                         }
264                         dir = dir+2; /* skip the first // */
265                 }
266         }
267         
268         /* Note
269          *   memmove( start, eind, strlen(eind)+1 );
270          * is the same as
271          *   strcpy( start, eind ); 
272          * except strcpy should not be used because there is overlap,
273           * so use memmove's slightly more obscure syntax - Campbell
274          */
275         
276 #ifdef WIN32
277         
278         /* Note, this should really be moved to the file selector,
279          * since this function is used in many areas */
280         if(strcmp(dir, ".")==0) {       /* happens for example in FILE_MAIN */
281            get_default_root(dir);
282            return;
283         }       
284
285         while ( (start = strstr(dir, "\\..\\")) ) {
286                 eind = start + strlen("\\..\\") - 1;
287                 a = start-dir-1;
288                 while (a>0) {
289                         if (dir[a] == '\\') break;
290                         a--;
291                 }
292                 if (a<0) {
293                         break;
294                 } else {
295                         memmove( dir+a, eind, strlen(eind)+1 );
296                 }
297         }
298
299         while ( (start = strstr(dir,"\\.\\")) ){
300                 eind = start + strlen("\\.\\") - 1;
301                 memmove( start, eind, strlen(eind)+1 );
302         }
303
304         while ( (start = strstr(dir,"\\\\" )) ){
305                 eind = start + strlen("\\\\") - 1;
306                 memmove( start, eind, strlen(eind)+1 );
307         }
308
309         if((a = strlen(dir))){                          /* remove the '\\' at the end */
310                 while(a>0 && dir[a-1] == '\\'){
311                         a--;
312                         dir[a] = 0;
313                 }
314         }
315 #else
316         if(dir[0]=='.') {       /* happens, for example in FILE_MAIN */
317            dir[0]= '/';
318            dir[1]= 0;
319            return;
320         }
321
322         /* support for odd paths: eg /../home/me --> /home/me
323          * this is a valid path in blender but we cant handle this the useual way below
324          * simply strip this prefix then evaluate the path as useual. pythons os.path.normpath() does this */
325         while((strncmp(dir, "/../", 4)==0)) {
326                 memmove( dir, dir + 4, strlen(dir + 4) + 1 );
327         }
328
329         while ( (start = strstr(dir, "/../")) ) {
330                 eind = start + (4 - 1) /* strlen("/../") - 1 */;
331                 a = start-dir-1;
332                 while (a>0) {
333                         if (dir[a] == '/') break;
334                         a--;
335                 }
336                 if (a<0) {
337                         break;
338                 } else {
339                         memmove( dir+a, eind, strlen(eind)+1 );
340                 }
341         }
342
343         while ( (start = strstr(dir,"/./")) ){
344                 eind = start + (3 - 1) /* strlen("/./") - 1 */;
345                 memmove( start, eind, strlen(eind)+1 );
346         }
347
348         while ( (start = strstr(dir,"//" )) ){
349                 eind = start + (2 - 1) /* strlen("//") - 1 */;
350                 memmove( start, eind, strlen(eind)+1 );
351         }
352
353         if( (a = strlen(dir)) ){                                /* remove all '/' at the end */
354                 while(dir[a-1] == '/'){
355                         a--;
356                         dir[a] = 0;
357                         if (a<=0) break;
358                 }
359         }
360 #endif
361 }
362
363
364 void BLI_path_rel(char *file, const char *relfile)
365 {
366         char * lslash;
367         char temp[FILE_MAXDIR+FILE_MAXFILE];
368         char res[FILE_MAXDIR+FILE_MAXFILE];
369         
370         /* if file is already relative, bail out */
371         if(file[0]=='/' && file[1]=='/') return;
372         
373         /* also bail out if relative path is not set */
374         if (relfile[0] == 0) return;
375
376 #ifdef WIN32 
377         if (strlen(relfile) > 2 && relfile[1] != ':') {
378                 char* ptemp;
379                 /* fix missing volume name in relative base,
380                    can happen with old recent-files.txt files */
381                 get_default_root(temp);
382                 ptemp = &temp[2];
383                 if (relfile[0] != '\\' && relfile[0] != '/') {
384                         ptemp++;
385                 }
386                 BLI_strncpy(ptemp, relfile, FILE_MAXDIR + FILE_MAXFILE-3);
387         } else {
388                 BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE);
389         }
390
391         if (strlen(file) > 2) {
392                 if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] )
393                         return;
394         }
395 #else
396         BLI_strncpy(temp, relfile, FILE_MAX);
397 #endif
398
399         BLI_char_switch(temp, '\\', '/');
400         BLI_char_switch(file, '\\', '/');
401         
402         /* remove /./ which confuse the following slash counting... */
403         BLI_cleanup_file(NULL, file);
404         BLI_cleanup_file(NULL, temp);
405         
406         /* the last slash in the file indicates where the path part ends */
407         lslash = BLI_last_slash(temp);
408
409         if (lslash) 
410         {       
411                 /* find the prefix of the filename that is equal for both filenames.
412                    This is replaced by the two slashes at the beginning */
413                 char *p= temp;
414                 char *q= file;
415
416                 while ((*p == *q)) {
417                         ++p; ++q;
418                         /* dont search beyond the end of the string
419                          * in the rare case they match */
420                         if ((*p=='\0') || (*q=='\0')) {
421                                 break;
422                         }
423                 }
424
425                 /* we might have passed the slash when the beginning of a dir matches 
426                    so we rewind. Only check on the actual filename
427                 */
428                 if (*q != '/') {
429                         while ( (q >= file) && (*q != '/') ) { --q; --p; }
430                 } 
431                 else if (*p != '/') {
432                         while ( (p >= temp) && (*p != '/') ) { --p; --q; }
433                 }
434                 
435                 strcpy(res,     "//");
436
437                 /* p now points to the slash that is at the beginning of the part
438                    where the path is different from the relative path. 
439                    We count the number of directories we need to go up in the
440                    hierarchy to arrive at the common 'prefix' of the path
441                 */                      
442                 while (p && p < lslash) {
443                         if (*p == '/') 
444                                 strcat(res,     "../");
445                         ++p;
446                 }
447
448                 strcat(res, q+1); /* don't copy the slash at the beginning */
449                 
450 #ifdef  WIN32
451                 BLI_char_switch(res+2, '/', '\\');
452 #endif
453                 strcpy(file, res);
454         }
455 }
456
457 int BLI_has_parent(char *path)
458 {
459         int len;
460         int slashes = 0;
461         BLI_clean(path);
462         len = BLI_add_slash(path) - 1;
463
464         while (len>=0) {
465                 if ((path[len] == '\\') || (path[len] == '/'))
466                         slashes++;
467                 len--;
468         }
469         return slashes > 1;
470 }
471
472 int BLI_parent_dir(char *path)
473 {
474 #ifdef WIN32
475         static char *parent_dir="..\\";
476 #else
477         static char *parent_dir="../";
478 #endif
479         char tmp[FILE_MAXDIR+FILE_MAXFILE+4];
480         BLI_strncpy(tmp, path, sizeof(tmp));
481         BLI_add_slash(tmp);
482         strcat(tmp, parent_dir);
483         BLI_cleanup_dir(NULL, tmp);
484         
485         if (!BLI_testextensie(tmp, parent_dir)) {
486                 BLI_strncpy(path, tmp, sizeof(tmp));    
487                 return 1;
488         } else {
489                 return 0;
490         }
491 }
492
493 static int stringframe_chars(char *path, int *char_start, int *char_end)
494 {
495         int ch_sta, ch_end, i;
496         /* Insert current frame: file### -> file001 */
497         ch_sta = ch_end = 0;
498         for (i = 0; path[i] != '\0'; i++) {
499                 if (path[i] == '\\' || path[i] == '/') {
500                         ch_end = 0; /* this is a directory name, dont use any hashes we found */
501                 } else if (path[i] == '#') {
502                         ch_sta = i;
503                         ch_end = ch_sta+1;
504                         while (path[ch_end] == '#') {
505                                 ch_end++;
506                         }
507                         i = ch_end-1; /* keep searching */
508                         
509                         /* dont break, there may be a slash after this that invalidates the previous #'s */
510                 }
511         }
512
513         if(ch_end) {
514                 *char_start= ch_sta;
515                 *char_end= ch_end;
516                 return 1;
517         }
518         else {
519                 *char_start= -1;
520                 *char_end= -1;
521                 return 0;
522         }
523 }
524
525 static void ensure_digits(char *path, int digits)
526 {
527         char *file= BLI_last_slash(path);
528
529         if(file==NULL)
530                 file= path;
531
532         if(strrchr(file, '#') == NULL) {
533                 int len= strlen(file);
534
535                 while(digits--) {
536                         file[len++]= '#';
537                 }
538                 file[len]= '\0';
539         }
540 }
541
542 int BLI_path_frame(char *path, int frame, int digits)
543 {
544         int ch_sta, ch_end;
545
546         if(digits)
547                 ensure_digits(path, digits);
548
549         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
550                 char tmp[FILE_MAX], format[64];
551                 sprintf(format, "%%.%ds%%.%dd%%s", ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d%s" */
552                 sprintf(tmp, format, path, frame, path+ch_end);
553                 strcpy(path, tmp);
554                 return 1;
555         }
556         return 0;
557 }
558
559 int BLI_path_frame_range(char *path, int sta, int end, int digits)
560 {
561         int ch_sta, ch_end;
562
563         if(digits)
564                 ensure_digits(path, digits);
565
566         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
567                 char tmp[FILE_MAX], format[64];
568                 sprintf(format, "%%.%ds%%.%dd_%%.%dd%%s", ch_sta, ch_end-ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d-%.5d%s" */
569                 sprintf(tmp, format, path, sta, end, path+ch_end);
570                 strcpy(path, tmp);
571                 return 1;
572         }
573         return 0;
574 }
575
576 int BLI_path_abs(char *path, const char *basepath)
577 {
578         int wasrelative = (strncmp(path, "//", 2)==0);
579         char tmp[FILE_MAX];
580         char base[FILE_MAX];
581 #ifdef WIN32
582         char vol[3] = {'\0', '\0', '\0'};
583
584         BLI_strncpy(vol, path, 3);
585         /* we are checking here if we have an absolute path that is not in the current
586            blend file as a lib main - we are basically checking for the case that a 
587            UNIX root '/' is passed.
588         */
589         if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
590                 char *p = path;
591                 get_default_root(tmp);
592                 // get rid of the slashes at the beginning of the path
593                 while (*p == '\\' || *p == '/') {
594                         p++;
595                 }
596                 strcat(tmp, p);
597         }
598         else {
599                 BLI_strncpy(tmp, path, FILE_MAX);
600         }
601 #else
602         BLI_strncpy(tmp, path, sizeof(tmp));
603         
604         /* Check for loading a windows path on a posix system
605          * in this case, there is no use in trying C:/ since it 
606          * will never exist on a unix os.
607          * 
608          * Add a / prefix and lowercase the driveletter, remove the :
609          * C:\foo.JPG -> /c/foo.JPG */
610         
611         if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) {
612                 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
613                 tmp[0] = '/'; 
614                 /* '\' the slash will be converted later */
615         }
616         
617 #endif
618
619         BLI_strncpy(base, basepath, sizeof(base));
620         
621         BLI_cleanup_file(NULL, base);
622         
623         /* push slashes into unix mode - strings entering this part are
624            potentially messed up: having both back- and forward slashes.
625            Here we push into one conform direction, and at the end we
626            push them into the system specific dir. This ensures uniformity
627            of paths and solving some problems (and prevent potential future
628            ones) -jesterKing. */
629         BLI_char_switch(tmp, '\\', '/');
630         BLI_char_switch(base, '\\', '/');       
631
632         /* Paths starting with // will get the blend file as their base,
633          * this isnt standard in any os but is uesed in blender all over the place */
634         if (wasrelative) {
635                 char *lslash= BLI_last_slash(base);
636                 if (lslash) {
637                         int baselen= (int) (lslash-base) + 1;
638                         /* use path for temp storage here, we copy back over it right away */
639                         BLI_strncpy(path, tmp+2, FILE_MAX);
640                         
641                         memcpy(tmp, base, baselen);
642                         BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen);
643                         BLI_strncpy(path, tmp, FILE_MAX);
644                 } else {
645                         BLI_strncpy(path, tmp+2, FILE_MAX);
646                 }
647         } else {
648                 BLI_strncpy(path, tmp, FILE_MAX);
649         }
650         
651         if (path[0]!='\0') {
652                 if ( path[strlen(path)-1]=='/') {
653                         /* remove the '/' so we avoid BLI_cleanup_dir adding an extra \ in WIN32 */
654                         path[strlen(path)-1] = '\0';
655                         BLI_cleanup_dir(NULL, path);
656                 } else {
657                         BLI_cleanup_file(NULL, path);
658                 }
659         }
660         
661 #ifdef WIN32
662         /* skip first two chars, which in case of
663            absolute path will be drive:/blabla and
664            in case of relpath //blabla/. So relpath
665            // will be retained, rest will be nice and
666            shiny win32 backward slashes :) -jesterKing
667         */
668         BLI_char_switch(path+2, '/', '\\');
669 #endif
670         
671         return wasrelative;
672 }
673
674
675 /*
676  * Should only be done with command line paths.
677  * this is NOT somthing blenders internal paths support like the // prefix
678  */
679 int BLI_path_cwd(char *path)
680 {
681         int wasrelative = 1;
682         int filelen = strlen(path);
683         
684 #ifdef WIN32
685         if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
686                 wasrelative = 0;
687 #else
688         if (filelen >= 2 && path[0] == '/')
689                 wasrelative = 0;
690 #endif
691         
692         if (wasrelative==1) {
693                 char cwd[FILE_MAXDIR + FILE_MAXFILE];
694                 BLI_getwdN(cwd); /* incase the full path to the blend isnt used */
695                 
696                 if (cwd[0] == '\0') {
697                         printf( "Could not get the current working directory - $PWD for an unknown reason.");
698                 } else {
699                         /* uses the blend path relative to cwd important for loading relative linked files.
700                         *
701                         * cwd should contain c:\ etc on win32 so the relbase can be NULL
702                         * relbase being NULL also prevents // being misunderstood as relative to the current
703                         * blend file which isnt a feature we want to use in this case since were dealing
704                         * with a path from the command line, rather then from inside Blender */
705                         
706                         char origpath[FILE_MAXDIR + FILE_MAXFILE];
707                         BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE);
708                         
709                         BLI_make_file_string(NULL, path, cwd, origpath); 
710                 }
711         }
712         
713         return wasrelative;
714 }
715
716
717 /* 'di's filename component is moved into 'fi', di is made a dir path */
718 void BLI_splitdirstring(char *di, char *fi)
719 {
720         char *lslash= BLI_last_slash(di);
721
722         if (lslash) {
723                 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
724                 *(lslash+1)=0;
725         } else {
726                 BLI_strncpy(fi, di, FILE_MAXFILE);
727                 di[0]= 0;
728         }
729 }
730
731 void BLI_getlastdir(const char* dir, char *last, int maxlen)
732 {
733         const char *s = dir;
734         const char *lslash = NULL;
735         const char *prevslash = NULL;
736         while (*s) {
737                 if ((*s == '\\') || (*s == '/')) {
738                         prevslash = lslash;
739                         lslash = s;
740                 }
741                 s++;
742         }
743         if (prevslash) {
744                 BLI_strncpy(last, prevslash+1, maxlen);
745         } else {
746                 BLI_strncpy(last, dir, maxlen);
747         }
748 }
749
750 /* This is now only used to really get the user's default document folder */
751 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
752    as default location to save documents */
753 char *BLI_getDefaultDocumentFolder(void) {
754         #if !defined(WIN32)
755                 return getenv("HOME");
756
757         #else /* Windows */
758                 char * ret;
759                 static char documentfolder[MAXPATHLEN];
760                 HRESULT hResult;
761
762                 /* Check for %HOME% env var */
763
764                 ret = getenv("HOME");
765                 if(ret) {
766                         if (BLI_is_dir(ret)) return ret;
767                 }
768                                 
769                 /* add user profile support for WIN 2K / NT.
770                  * This is %APPDATA%, which translates to either
771                  * %USERPROFILE%\Application Data or since Vista
772                  * to %USERPROFILE%\AppData\Roaming
773                  */
774                 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
775                 
776                 if (hResult == S_OK)
777                 {
778                         if (BLI_is_dir(documentfolder)) return documentfolder;
779                 }
780                 
781                 return NULL;
782         #endif
783 }
784
785 /* NEW stuff, to be cleaned up when fully migrated */
786 /* ************************************************************* */
787 /* ************************************************************* */
788
789 // #define PATH_DEBUG2
790
791 static char *blender_version_decimal(void)
792 {
793         static char version_str[5];
794         sprintf(version_str, "%d.%02d", BLENDER_VERSION/100, BLENDER_VERSION%100);
795         return version_str;
796 }
797
798 static int test_path(char *targetpath, char *path_base, char *path_sep, char *folder_name)
799 {
800         char tmppath[FILE_MAX];
801         
802         if(path_sep)    BLI_join_dirfile(tmppath, path_base, path_sep);
803         else                    BLI_strncpy(tmppath, path_base, sizeof(tmppath));
804         
805         BLI_make_file_string("/", targetpath, tmppath, folder_name);
806         
807         if (BLI_is_dir(targetpath)) {
808 #ifdef PATH_DEBUG2
809                 printf("\tpath found: %s\n", targetpath);
810 #endif
811                 return 1;
812         }
813         else {
814 #ifdef PATH_DEBUG2
815                 printf("\tpath missing: %s\n", targetpath);
816 #endif
817                 //targetpath[0] = '\0';
818                 return 0;
819         }
820 }
821
822 static int test_env_path(char *path, char *envvar)
823 {
824         char *env = envvar?getenv(envvar):NULL;
825         if (!env) return 0;
826         
827         if (BLI_is_dir(env)) {
828                 BLI_strncpy(path, env, FILE_MAX);
829                 return 1;
830         } else {
831                 path[0] = '\0';
832                 return 0;
833         }
834 }
835
836 static int get_path_local(char *targetpath, char *folder_name, char *subfolder_name)
837 {
838         extern char bprogname[]; /* argv[0] from creator.c */
839         char bprogdir[FILE_MAX];
840         char relfolder[FILE_MAX];
841         char cwd[FILE_MAX];
842         char *s;
843         int i;
844         
845 #ifdef PATH_DEBUG2
846         printf("get_path_local...\n");
847 #endif
848         
849         if (subfolder_name) {
850                 BLI_join_dirfile(relfolder, folder_name, subfolder_name);
851         } else {
852                 BLI_strncpy(relfolder, folder_name, FILE_MAX);
853         }
854         
855         /* use argv[0] (bprogname) to get the path to the executable */
856         s = BLI_last_slash(bprogname);
857         i = s - bprogname + 1;
858         BLI_strncpy(bprogdir, bprogname, i);
859         
860         /* try EXECUTABLE_DIR/folder_name */
861         if(test_path(targetpath, bprogdir, "", relfolder))
862                 return 1;
863         
864         /* try CWD/release/folder_name */
865         if(test_path(targetpath, BLI_getwdN(cwd), "release", relfolder))
866                 return 1;
867         
868         /* try EXECUTABLE_DIR/release/folder_name */
869         if(test_path(targetpath, bprogdir, "release", relfolder))
870                 return 1;
871         
872         /* try EXECUTABLE_DIR/2.5/folder_name - new default directory for local blender installed files */
873         if(test_path(targetpath, bprogdir, blender_version_decimal(), relfolder))
874                 return 1;
875
876         return 0;
877 }
878
879 static int get_path_user(char *targetpath, char *folder_name, char *subfolder_name, char *envvar)
880 {
881         char user_path[FILE_MAX];
882         const char *user_base_path;
883         
884         user_path[0] = '\0';
885
886         if (test_env_path(user_path, envvar)) {
887                 if (subfolder_name) {
888                         return test_path(targetpath, user_path, NULL, subfolder_name);
889                 } else {
890                         BLI_strncpy(targetpath, user_path, FILE_MAX);
891                         return 1;
892                 }
893         }
894
895         user_base_path = (const char *)GHOST_getUserDir();
896         if (user_base_path) {
897                 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal());
898         }
899
900         if(!user_path[0])
901                 return 0;
902         
903 #ifdef PATH_DEBUG2
904         printf("get_path_user: %s\n", user_path);
905 #endif
906         
907         if (subfolder_name) {
908                 /* try $HOME/folder_name/subfolder_name */
909                 return test_path(targetpath, user_path, folder_name, subfolder_name);
910         } else {
911                 /* try $HOME/folder_name */
912                 return test_path(targetpath, user_path, NULL, folder_name);
913         }
914 }
915
916 static int get_path_system(char *targetpath, char *folder_name, char *subfolder_name, char *envvar)
917 {
918         char system_path[FILE_MAX];
919         const char *system_base_path;
920
921         system_path[0] = '\0';
922
923         if (test_env_path(system_path, envvar)) {
924                 if (subfolder_name) {
925                         return test_path(targetpath, system_path, NULL, subfolder_name);
926                 } else {
927                         BLI_strncpy(targetpath, system_path, FILE_MAX);
928                         return 1;
929                 }
930         }
931
932         system_base_path = (const char *)GHOST_getSystemDir();
933         if (system_base_path) {
934                 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal());
935         }
936         
937         if(!system_path[0])
938                 return 0;
939         
940 #ifdef PATH_DEBUG2
941         printf("get_path_system: %s\n", system_path);
942 #endif
943         
944         if (subfolder_name) {
945                 /* try $BLENDERPATH/folder_name/subfolder_name */
946                 return test_path(targetpath, system_path, folder_name, subfolder_name);
947         } else {
948                 /* try $BLENDERPATH/folder_name */
949                 return test_path(targetpath, system_path, NULL, folder_name);
950         }
951 }
952
953 /* get a folder out of the 'folder_id' presets for paths */
954 /* returns the path if found, NULL string if not */
955 char *BLI_get_folder(int folder_id, char *subfolder)
956 {
957         static char path[FILE_MAX] = "";
958         
959         switch (folder_id) {
960                 case BLENDER_DATAFILES:         /* general case */
961                         if (get_path_local(path, "datafiles", subfolder)) break;
962                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
963                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES")) break;
964                         return NULL;
965                         
966                 case BLENDER_USER_DATAFILES:
967                         if (get_path_local(path, "datafiles", subfolder)) break;
968                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
969                         return NULL;
970                         
971                 case BLENDER_SYSTEM_DATAFILES:
972                         if (get_path_local(path, "datafiles", subfolder)) break;
973                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES"))  break;
974                         return NULL;
975                         
976                 case BLENDER_USER_AUTOSAVE:
977                         if (get_path_local(path, "autosave", subfolder)) break;
978                         if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES"))       break;
979                         return NULL;
980
981                 case BLENDER_CONFIG:            /* general case */
982                         if (get_path_local(path, "config", subfolder)) break;
983                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
984                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
985                         return NULL;
986                         
987                 case BLENDER_USER_CONFIG:
988                         if (get_path_local(path, "config", subfolder)) break;
989                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
990                         return NULL;
991                         
992                 case BLENDER_SYSTEM_CONFIG:
993                         if (get_path_local(path, "config", subfolder)) break;
994                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
995                         return NULL;
996                         
997                 case BLENDER_SCRIPTS:           /* general case */
998                         if (get_path_local(path, "scripts", subfolder)) break;
999                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;           
1000                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1001                         return NULL;
1002                         
1003                 case BLENDER_USER_SCRIPTS:
1004                         if (get_path_local(path, "scripts", subfolder)) break;
1005                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;
1006                         return NULL;
1007                         
1008                 case BLENDER_SYSTEM_SCRIPTS:
1009                         if (get_path_local(path, "scripts", subfolder)) break;
1010                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1011                         return NULL;
1012                         
1013                 case BLENDER_PYTHON:            /* general case */
1014                         if (get_path_local(path, "python", subfolder)) break;
1015                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1016                         return NULL;
1017                         
1018                 case BLENDER_SYSTEM_PYTHON:
1019                         if (get_path_local(path, "python", subfolder)) break;
1020                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1021                         return NULL;
1022         }
1023         
1024         return path;
1025 }
1026
1027 static char *BLI_get_user_folder_notest(int folder_id, char *subfolder)
1028 {
1029         static char path[FILE_MAX] = "";
1030
1031         switch (folder_id) {
1032                 case BLENDER_USER_DATAFILES:
1033                         get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES");
1034                         break;
1035                 case BLENDER_USER_CONFIG:
1036                         get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG");
1037                         break;
1038                 case BLENDER_USER_AUTOSAVE:
1039                         get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE");
1040                         break;
1041         }
1042         if ('\0' == path[0]) {
1043                 return NULL;
1044         }
1045         return path;
1046 }
1047
1048 char *BLI_get_folder_create(int folder_id, char *subfolder)
1049 {
1050         char *path;
1051
1052         /* only for user folders */
1053         if (!ELEM3(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_AUTOSAVE))
1054                 return NULL;
1055         
1056         path = BLI_get_folder(folder_id, subfolder);
1057         
1058         if (!path) {
1059                 path = BLI_get_user_folder_notest(folder_id, subfolder);
1060                 if (path) BLI_recurdir_fileops(path);
1061         }
1062         
1063         return path;
1064 }
1065
1066
1067 /* End new stuff */
1068 /* ************************************************************* */
1069 /* ************************************************************* */
1070
1071
1072
1073 #ifdef PATH_DEBUG
1074 #undef PATH_DEBUG
1075 #endif
1076
1077 void BLI_setenv(const char *env, const char*val)
1078 {
1079         /* SGI or free windows */
1080 #if (defined(__sgi) || ((defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)))
1081         char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1082
1083         sprintf(envstr, "%s=%s", env, val);
1084         putenv(envstr);
1085         MEM_freeN(envstr);
1086
1087         /* non-free windows */
1088 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1089         _putenv_s(env, val);
1090 #else
1091         /* linux/osx/bsd */
1092         setenv(env, val, 1);
1093 #endif
1094 }
1095
1096
1097 /**
1098  Only set an env var if already not there.
1099  Like Unix setenv(env, val, 0);
1100  */
1101 void BLI_setenv_if_new(const char *env, const char* val)
1102 {
1103         if(getenv(env) == NULL)
1104                 BLI_setenv(env, val);
1105 }
1106
1107
1108 void BLI_clean(char *path)
1109 {
1110         if(path==0) return;
1111 #ifdef WIN32
1112         if(path && strlen(path)>2) {
1113                 BLI_char_switch(path+2, '/', '\\');
1114         }
1115 #else
1116         BLI_char_switch(path, '\\', '/');
1117 #endif
1118 }
1119
1120 void BLI_char_switch(char *string, char from, char to) 
1121 {
1122         if(string==0) return;
1123         while (*string != 0) {
1124                 if (*string == from) *string = to;
1125                 string++;
1126         }
1127 }
1128
1129 void BLI_make_exist(char *dir) {
1130         int a;
1131
1132         #ifdef WIN32
1133                 BLI_char_switch(dir, '/', '\\');
1134         #else
1135                 BLI_char_switch(dir, '\\', '/');
1136         #endif  
1137         
1138         a = strlen(dir);
1139         
1140 #ifdef WIN32    
1141         while(BLI_is_dir(dir) == 0){
1142                 a --;
1143                 while(dir[a] != '\\'){
1144                         a--;
1145                         if (a <= 0) break;
1146                 }
1147                 if (a >= 0) dir[a+1] = 0;
1148                 else {
1149                         /* defaulting to drive (usually 'C:') of Windows installation */
1150                         get_default_root(dir);
1151                         break;
1152                 }
1153         }
1154 #else
1155         while(BLI_is_dir(dir) == 0){
1156                 a --;
1157                 while(dir[a] != '/'){
1158                         a--;
1159                         if (a <= 0) break;
1160                 }
1161                 if (a >= 0) dir[a+1] = 0;
1162                 else {
1163                         strcpy(dir,"/");
1164                         break;
1165                 }
1166         }
1167 #endif
1168 }
1169
1170 void BLI_make_existing_file(char *name)
1171 {
1172         char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1173
1174         BLI_strncpy(di, name, sizeof(di));
1175         BLI_splitdirstring(di, fi);
1176         
1177         /* test exist */
1178         if (BLI_exists(di) == 0) {
1179                 BLI_recurdir_fileops(di);
1180         }
1181 }
1182
1183
1184 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1185 {
1186         int sl;
1187
1188         if (!string || !dir || !file) return; /* We don't want any NULLs */
1189         
1190         string[0]= 0; /* ton */
1191
1192         /* we first push all slashes into unix mode, just to make sure we don't get
1193            any mess with slashes later on. -jesterKing */
1194         /* constant strings can be passed for those parameters - don't change them - elubie */
1195         /*
1196         BLI_char_switch(relabase, '\\', '/');
1197         BLI_char_switch(dir, '\\', '/');
1198         BLI_char_switch(file, '\\', '/');
1199         */
1200
1201         /* Resolve relative references */       
1202         if (relabase && dir[0] == '/' && dir[1] == '/') {
1203                 char *lslash;
1204                 
1205                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1206                 strcpy(string, relabase);
1207                 
1208                 lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\');
1209                 
1210                 if(lslash) *(lslash+1)= 0;
1211
1212                 dir+=2; /* Skip over the relative reference */
1213         }
1214 #ifdef WIN32
1215         else {
1216                 if (strlen(dir) >= 2 && dir[1] == ':' ) {
1217                         BLI_strncpy(string, dir, 3);
1218                         dir += 2;
1219                 }
1220                 else { /* no drive specified */
1221                         /* first option: get the drive from the relabase if it has one */
1222                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1223                                 BLI_strncpy(string, relabase, 3);       
1224                                 string[2] = '\\';
1225                                 string[3] = '\0';
1226                         }
1227                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1228                                 get_default_root(string);
1229                         }
1230                         
1231                         /* ignore leading slashes */
1232                         while (*dir == '/' || *dir == '\\') dir++;
1233                 }
1234         }
1235 #endif
1236
1237         strcat(string, dir);
1238
1239         /* Make sure string ends in one (and only one) slash */ 
1240         /* first trim all slashes from the end of the string */
1241         sl = strlen(string);
1242         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1243                 string[sl-1] = '\0';
1244                 sl--;
1245         }
1246         /* since we've now removed all slashes, put back one slash at the end. */
1247         strcat(string, "/");
1248         
1249         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1250                 file++;
1251                 
1252         strcat (string, file);
1253         
1254         /* Push all slashes to the system preferred direction */
1255         BLI_clean(string);
1256 }
1257
1258 int BLI_testextensie(const char *str, const char *ext)
1259 {
1260         short a, b;
1261         int retval;
1262
1263         a= strlen(str);
1264         b= strlen(ext);
1265
1266         if(a==0 || b==0 || b>=a) {
1267                 retval = 0;
1268         } else if (BLI_strcasecmp(ext, str + a - b)) {
1269                 retval = 0;     
1270         } else {
1271                 retval = 1;
1272         }
1273
1274         return (retval);
1275 }
1276
1277 int BLI_testextensie_array(const char *str, const char **ext_array)
1278 {
1279         int i=0;
1280         while(ext_array[i]) {
1281                 if(BLI_testextensie(str, ext_array[i])) {
1282                         return 1;
1283                 }
1284
1285                 i++;
1286         }
1287         return 0;
1288 }
1289
1290 /* semicolon separated wildcards, eg:
1291  *  '*.zip;*.py;*.exe' */
1292 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1293 {
1294         const char *ext_step= ext_fnmatch;
1295         char pattern[16];
1296
1297         while(ext_step[0]) {
1298                 char *ext_next;
1299                 int len_ext;
1300
1301                 if((ext_next=strchr(ext_step, ';'))) {
1302                         len_ext= (int)(ext_next - ext_step) + 1;
1303                 }
1304                 else {
1305                         len_ext= sizeof(pattern);
1306                 }
1307
1308                 BLI_strncpy(pattern, ext_step, len_ext);
1309
1310                 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1311                         return 1;
1312                 }
1313                 ext_step += len_ext;
1314         }
1315
1316         return 0;
1317 }
1318
1319
1320 int BLI_replace_extension(char *path, int maxlen, const char *ext)
1321 {
1322         int a;
1323
1324         for(a=strlen(path)-1; a>=0; a--)
1325                 if(path[a] == '.' || path[a] == '/' || path[a] == '\\')
1326                         break;
1327         
1328         if(path[a] != '.')
1329                 a= strlen(path);
1330
1331         if(a + strlen(ext) >= maxlen)
1332                 return 0;
1333
1334         strcpy(path+a, ext);
1335         return 1;
1336 }
1337
1338 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1339  * - wont change 'string'
1340  * - wont create any directories
1341  * - dosnt use CWD, or deal with relative paths.
1342  * - Only fill's in *dir and *file when they are non NULL
1343  * */
1344 void BLI_split_dirfile(const char *string, char *dir, char *file)
1345 {
1346         char *lslash_str = BLI_last_slash(string);
1347         int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0;
1348
1349         if (dir) {
1350                 if (lslash) {
1351                         BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */
1352                 } else {
1353                         dir[0] = '\0';
1354                 }
1355         }
1356         
1357         if (file) {
1358                 strcpy( file, string+lslash);
1359         }
1360 }
1361
1362 /* simple appending of filename to dir, does not check for valid path! */
1363 void BLI_join_dirfile(char *string, const char *dir, const char *file)
1364 {
1365         int sl_dir;
1366         
1367         if(string != dir) /* compare pointers */
1368                 BLI_strncpy(string, dir, FILE_MAX);
1369
1370         if (!file)
1371                 return;
1372         
1373         sl_dir= BLI_add_slash(string);
1374         
1375         if (sl_dir <FILE_MAX) {
1376                 BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
1377         }
1378 }
1379
1380 /* like pythons os.path.basename( ) */
1381 char *BLI_path_basename(char *path)
1382 {
1383         char *filename= BLI_last_slash(path);
1384         return filename ? filename + 1 : path;
1385 }
1386
1387 /*
1388   Produce image export path.
1389
1390   Fails returning 0 if image filename is empty or if destination path
1391   matches image path (i.e. both are the same file).
1392
1393   Trailing slash in dest_dir is optional.
1394
1395   Logic:
1396
1397   - if an image is "below" current .blend file directory, rebuild the
1398         same dir structure in dest_dir
1399
1400   For example //textures/foo/bar.png becomes
1401   [dest_dir]/textures/foo/bar.png.
1402
1403   - if an image is not "below" current .blend file directory,
1404   disregard it's path and copy it in the same directory where 3D file
1405   goes.
1406
1407   For example //../foo/bar.png becomes [dest_dir]/bar.png.
1408
1409   This logic will help ensure that all image paths are relative and
1410   that a user gets his images in one place. It'll also provide
1411   consistent behaviour across exporters.
1412  */
1413 int BKE_rebase_path(char *abs, int abs_size, char *rel, int rel_size, const char *base_dir, const char *src_dir, const char *dest_dir)
1414 {
1415         char path[FILE_MAX];
1416         char dir[FILE_MAX];
1417         char base[FILE_MAX];
1418         char blend_dir[FILE_MAX];       /* directory, where current .blend file resides */
1419         char dest_path[FILE_MAX];
1420         char rel_dir[FILE_MAX];
1421         int len;
1422
1423         if (abs)
1424                 abs[0]= 0;
1425
1426         if (rel)
1427                 rel[0]= 0;
1428
1429         BLI_split_dirfile(base_dir, blend_dir, NULL);
1430
1431         if (src_dir[0]=='\0')
1432                 return 0;
1433
1434         BLI_strncpy(path, src_dir, sizeof(path));
1435
1436         /* expand "//" in filename and get absolute path */
1437         BLI_path_abs(path, base_dir);
1438
1439         /* get the directory part */
1440         BLI_split_dirfile(path, dir, base);
1441
1442         len= strlen(blend_dir);
1443
1444         rel_dir[0] = 0;
1445
1446         /* if image is "below" current .blend file directory */
1447         if (!strncmp(path, blend_dir, len)) {
1448
1449                 /* if image is _in_ current .blend file directory */
1450                 if (!strcmp(dir, blend_dir)) {
1451                         BLI_join_dirfile(dest_path, dest_dir, base);
1452                 }
1453                 /* "below" */
1454                 else {
1455                         /* rel = image_path_dir - blend_dir */
1456                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1457
1458                         BLI_join_dirfile(dest_path, dest_dir, rel_dir);
1459                         BLI_join_dirfile(dest_path, dest_path, base);
1460                 }
1461
1462         }
1463         /* image is out of current directory */
1464         else {
1465                 BLI_join_dirfile(dest_path, dest_dir, base);
1466         }
1467
1468         if (abs)
1469                 BLI_strncpy(abs, dest_path, abs_size);
1470
1471         if (rel) {
1472                 strncat(rel, rel_dir, rel_size);
1473                 strncat(rel, base, rel_size);
1474         }
1475
1476         /* return 2 if src=dest */
1477         if (!strcmp(path, dest_path)) {
1478                 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1479                 return 2;
1480         }
1481
1482         return 1;
1483 }
1484
1485
1486 static int add_win32_extension(char *name)
1487 {
1488         int retval = 0;
1489         int type;
1490
1491         type = BLI_exist(name);
1492         if ((type == 0) || S_ISDIR(type)) {
1493 #ifdef _WIN32
1494                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1495                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1496                 char *extensions = getenv("PATHEXT");
1497                 if (extensions) {
1498                         char *temp;
1499                         do {
1500                                 strcpy(filename, name);
1501                                 temp = strstr(extensions, ";");
1502                                 if (temp) {
1503                                         strncpy(ext, extensions, temp - extensions);
1504                                         ext[temp - extensions] = 0;
1505                                         extensions = temp + 1;
1506                                         strcat(filename, ext);
1507                                 } else {
1508                                         strcat(filename, extensions);
1509                                 }
1510
1511                                 type = BLI_exist(filename);
1512                                 if (type && (! S_ISDIR(type))) {
1513                                         retval = 1;
1514                                         strcpy(name, filename);
1515                                         break;
1516                                 }
1517                         } while (temp);
1518                 }
1519 #endif
1520         } else {
1521                 retval = 1;
1522         }
1523
1524         return (retval);
1525 }
1526
1527 void BLI_where_am_i(char *fullname, const char *name)
1528 {
1529         char filename[FILE_MAXDIR+FILE_MAXFILE];
1530         char *path = NULL, *temp;
1531         
1532 #ifdef _WIN32
1533         char *separator = ";";
1534         char slash = '\\';
1535 #else
1536         char *separator = ":";
1537         char slash = '/';
1538 #endif
1539
1540         
1541 #ifdef __linux__
1542         /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1543         path = br_find_exe( NULL );
1544         if (path) {
1545                 BLI_strncpy(fullname, path, FILE_MAXDIR+FILE_MAXFILE);
1546                 free(path);
1547                 return;
1548         }
1549 #endif
1550
1551 #ifdef _WIN32
1552         if(GetModuleFileName(0, fullname, FILE_MAXDIR+FILE_MAXFILE)) {
1553                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1554                 return;
1555         }
1556 #endif
1557
1558         /* unix and non linux */
1559         if (name && fullname && strlen(name)) {
1560                 strcpy(fullname, name);
1561                 if (name[0] == '.') {
1562                         // relative path, prepend cwd
1563                         BLI_getwdN(fullname);
1564                         
1565                         // not needed but avoids annoying /./ in name
1566                         if(name && name[0]=='.' && name[1]==slash)
1567                                 BLI_join_dirfile(fullname, fullname, name+2);
1568                         else
1569                                 BLI_join_dirfile(fullname, fullname, name);
1570                         
1571                         add_win32_extension(fullname);
1572                 } else if (BLI_last_slash(name)) {
1573                         // full path
1574                         strcpy(fullname, name);
1575                         add_win32_extension(fullname);
1576                 } else {
1577                         // search for binary in $PATH
1578                         path = getenv("PATH");
1579                         if (path) {
1580                                 do {
1581                                         temp = strstr(path, separator);
1582                                         if (temp) {
1583                                                 strncpy(filename, path, temp - path);
1584                                                 filename[temp - path] = 0;
1585                                                 path = temp + 1;
1586                                         } else {
1587                                                 strncpy(filename, path, sizeof(filename));
1588                                         }
1589                                         BLI_join_dirfile(fullname, fullname, name);
1590                                         if (add_win32_extension(filename)) {
1591                                                 strcpy(fullname, filename);
1592                                                 break;
1593                                         }
1594                                 } while (temp);
1595                         }
1596                 }
1597 #ifndef NDEBUG
1598                 if (strcmp(name, fullname)) {
1599                         printf("guessing '%s' == '%s'\n", name, fullname);
1600                 }
1601 #endif
1602
1603 #ifdef _WIN32
1604                 // in windows change long filename to short filename because
1605                 // win2k doesn't know how to parse a commandline with lots of
1606                 // spaces and double-quotes. There's another solution to this
1607                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1608                 // that's even uglier
1609                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1610 #ifndef NDEBUG
1611                 printf("Shortname = '%s'\n", fullname);
1612 #endif
1613 #endif
1614         }
1615 }
1616
1617 void BLI_where_is_temp(char *fullname, int usertemp)
1618 {
1619         fullname[0] = '\0';
1620         
1621         if (usertemp && BLI_is_dir(U.tempdir)) {
1622                 strcpy(fullname, U.tempdir);
1623         }
1624         
1625         
1626 #ifdef WIN32
1627         if (fullname[0] == '\0') {
1628                 char *tmp = getenv("TEMP"); /* Windows */
1629                 if (tmp && BLI_is_dir(tmp)) {
1630                         strcpy(fullname, tmp);
1631                 }
1632         }
1633 #else
1634         /* Other OS's - Try TMP and TMPDIR */
1635         if (fullname[0] == '\0') {
1636                 char *tmp = getenv("TMP");
1637                 if (tmp && BLI_is_dir(tmp)) {
1638                         strcpy(fullname, tmp);
1639                 }
1640         }
1641         
1642         if (fullname[0] == '\0') {
1643                 char *tmp = getenv("TMPDIR");
1644                 if (tmp && BLI_is_dir(tmp)) {
1645                         strcpy(fullname, tmp);
1646                 }
1647         }
1648 #endif  
1649         
1650         if (fullname[0] == '\0') {
1651                 strcpy(fullname, "/tmp/");
1652         } else {
1653                 /* add a trailing slash if needed */
1654                 BLI_add_slash(fullname);
1655 #ifdef WIN32
1656                 strcpy(U.tempdir, fullname); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1657 #endif
1658         }
1659 }
1660
1661 char *get_install_dir(void) {
1662         extern char bprogname[];
1663         char *tmpname = BLI_strdup(bprogname);
1664         char *cut;
1665
1666 #ifdef __APPLE__
1667         cut = strstr(tmpname, ".app");
1668         if (cut) cut[0] = 0;
1669 #endif
1670
1671         cut = BLI_last_slash(tmpname);
1672
1673         if (cut) {
1674                 cut[0] = 0;
1675                 return tmpname;
1676         } else {
1677                 MEM_freeN(tmpname);
1678                 return NULL;
1679         }
1680 }
1681
1682 #ifdef WITH_ICONV
1683
1684 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1685 {
1686         size_t inbytesleft=strlen(original);
1687         size_t outbytesleft=512;
1688         size_t rv=0;
1689         iconv_t cd;
1690         
1691         if (NULL == code) {
1692                 code = locale_charset();
1693         }
1694         cd=iconv_open("UTF-8", code);
1695
1696         if (cd == (iconv_t)(-1)) {
1697                 printf("iconv_open Error");
1698                 *utf_8='\0';
1699                 return ;
1700         }
1701         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1702         if (rv == (size_t) -1) {
1703                 printf("iconv Error\n");
1704                 return ;
1705         }
1706         *utf_8 = '\0';
1707         iconv_close(cd);
1708 }
1709 #endif // WITH_ICONV
1710
1711