Convenience defines SEP and ALTSEP (python has these), move BLI_*_slash function...
[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         static char parent_dir[]= {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
475         char tmp[FILE_MAXDIR+FILE_MAXFILE+4];
476         BLI_strncpy(tmp, path, sizeof(tmp)-4);
477         BLI_add_slash(tmp);
478         strcat(tmp, parent_dir);
479         BLI_cleanup_dir(NULL, tmp);
480         
481         if (!BLI_testextensie(tmp, parent_dir)) {
482                 BLI_strncpy(path, tmp, sizeof(tmp));    
483                 return 1;
484         } else {
485                 return 0;
486         }
487 }
488
489 static int stringframe_chars(char *path, int *char_start, int *char_end)
490 {
491         int ch_sta, ch_end, i;
492         /* Insert current frame: file### -> file001 */
493         ch_sta = ch_end = 0;
494         for (i = 0; path[i] != '\0'; i++) {
495                 if (path[i] == '\\' || path[i] == '/') {
496                         ch_end = 0; /* this is a directory name, dont use any hashes we found */
497                 } else if (path[i] == '#') {
498                         ch_sta = i;
499                         ch_end = ch_sta+1;
500                         while (path[ch_end] == '#') {
501                                 ch_end++;
502                         }
503                         i = ch_end-1; /* keep searching */
504                         
505                         /* dont break, there may be a slash after this that invalidates the previous #'s */
506                 }
507         }
508
509         if(ch_end) {
510                 *char_start= ch_sta;
511                 *char_end= ch_end;
512                 return 1;
513         }
514         else {
515                 *char_start= -1;
516                 *char_end= -1;
517                 return 0;
518         }
519 }
520
521 static void ensure_digits(char *path, int digits)
522 {
523         char *file= BLI_last_slash(path);
524
525         if(file==NULL)
526                 file= path;
527
528         if(strrchr(file, '#') == NULL) {
529                 int len= strlen(file);
530
531                 while(digits--) {
532                         file[len++]= '#';
533                 }
534                 file[len]= '\0';
535         }
536 }
537
538 int BLI_path_frame(char *path, int frame, int digits)
539 {
540         int ch_sta, ch_end;
541
542         if(digits)
543                 ensure_digits(path, digits);
544
545         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
546                 char tmp[FILE_MAX], format[64];
547                 sprintf(format, "%%.%ds%%.%dd%%s", ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d%s" */
548                 sprintf(tmp, format, path, frame, path+ch_end);
549                 strcpy(path, tmp);
550                 return 1;
551         }
552         return 0;
553 }
554
555 int BLI_path_frame_range(char *path, int sta, int end, int digits)
556 {
557         int ch_sta, ch_end;
558
559         if(digits)
560                 ensure_digits(path, digits);
561
562         if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
563                 char tmp[FILE_MAX], format[64];
564                 sprintf(format, "%%.%ds%%.%dd_%%.%dd%%s", ch_sta, ch_end-ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d-%.5d%s" */
565                 sprintf(tmp, format, path, sta, end, path+ch_end);
566                 strcpy(path, tmp);
567                 return 1;
568         }
569         return 0;
570 }
571
572 int BLI_path_abs(char *path, const char *basepath)
573 {
574         int wasrelative = (strncmp(path, "//", 2)==0);
575         char tmp[FILE_MAX];
576         char base[FILE_MAX];
577 #ifdef WIN32
578         char vol[3] = {'\0', '\0', '\0'};
579
580         BLI_strncpy(vol, path, 3);
581         /* we are checking here if we have an absolute path that is not in the current
582            blend file as a lib main - we are basically checking for the case that a 
583            UNIX root '/' is passed.
584         */
585         if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
586                 char *p = path;
587                 get_default_root(tmp);
588                 // get rid of the slashes at the beginning of the path
589                 while (*p == '\\' || *p == '/') {
590                         p++;
591                 }
592                 strcat(tmp, p);
593         }
594         else {
595                 BLI_strncpy(tmp, path, FILE_MAX);
596         }
597 #else
598         BLI_strncpy(tmp, path, sizeof(tmp));
599         
600         /* Check for loading a windows path on a posix system
601          * in this case, there is no use in trying C:/ since it 
602          * will never exist on a unix os.
603          * 
604          * Add a / prefix and lowercase the driveletter, remove the :
605          * C:\foo.JPG -> /c/foo.JPG */
606         
607         if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) {
608                 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
609                 tmp[0] = '/'; 
610                 /* '\' the slash will be converted later */
611         }
612         
613 #endif
614
615         BLI_strncpy(base, basepath, sizeof(base));
616         
617         BLI_cleanup_file(NULL, base);
618         
619         /* push slashes into unix mode - strings entering this part are
620            potentially messed up: having both back- and forward slashes.
621            Here we push into one conform direction, and at the end we
622            push them into the system specific dir. This ensures uniformity
623            of paths and solving some problems (and prevent potential future
624            ones) -jesterKing. */
625         BLI_char_switch(tmp, '\\', '/');
626         BLI_char_switch(base, '\\', '/');       
627
628         /* Paths starting with // will get the blend file as their base,
629          * this isnt standard in any os but is uesed in blender all over the place */
630         if (wasrelative) {
631                 char *lslash= BLI_last_slash(base);
632                 if (lslash) {
633                         int baselen= (int) (lslash-base) + 1;
634                         /* use path for temp storage here, we copy back over it right away */
635                         BLI_strncpy(path, tmp+2, FILE_MAX);
636                         
637                         memcpy(tmp, base, baselen);
638                         BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen);
639                         BLI_strncpy(path, tmp, FILE_MAX);
640                 } else {
641                         BLI_strncpy(path, tmp+2, FILE_MAX);
642                 }
643         } else {
644                 BLI_strncpy(path, tmp, FILE_MAX);
645         }
646         
647         if (path[0]!='\0') {
648                 if ( path[strlen(path)-1]=='/') {
649                         /* remove the '/' so we avoid BLI_cleanup_dir adding an extra \ in WIN32 */
650                         path[strlen(path)-1] = '\0';
651                         BLI_cleanup_dir(NULL, path);
652                 } else {
653                         BLI_cleanup_file(NULL, path);
654                 }
655         }
656         
657 #ifdef WIN32
658         /* skip first two chars, which in case of
659            absolute path will be drive:/blabla and
660            in case of relpath //blabla/. So relpath
661            // will be retained, rest will be nice and
662            shiny win32 backward slashes :) -jesterKing
663         */
664         BLI_char_switch(path+2, '/', '\\');
665 #endif
666         
667         return wasrelative;
668 }
669
670
671 /*
672  * Should only be done with command line paths.
673  * this is NOT somthing blenders internal paths support like the // prefix
674  */
675 int BLI_path_cwd(char *path)
676 {
677         int wasrelative = 1;
678         int filelen = strlen(path);
679         
680 #ifdef WIN32
681         if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
682                 wasrelative = 0;
683 #else
684         if (filelen >= 2 && path[0] == '/')
685                 wasrelative = 0;
686 #endif
687         
688         if (wasrelative==1) {
689                 char cwd[FILE_MAXDIR + FILE_MAXFILE];
690                 BLI_getwdN(cwd); /* incase the full path to the blend isnt used */
691                 
692                 if (cwd[0] == '\0') {
693                         printf( "Could not get the current working directory - $PWD for an unknown reason.");
694                 } else {
695                         /* uses the blend path relative to cwd important for loading relative linked files.
696                         *
697                         * cwd should contain c:\ etc on win32 so the relbase can be NULL
698                         * relbase being NULL also prevents // being misunderstood as relative to the current
699                         * blend file which isnt a feature we want to use in this case since were dealing
700                         * with a path from the command line, rather then from inside Blender */
701                         
702                         char origpath[FILE_MAXDIR + FILE_MAXFILE];
703                         BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE);
704                         
705                         BLI_make_file_string(NULL, path, cwd, origpath); 
706                 }
707         }
708         
709         return wasrelative;
710 }
711
712
713 /* 'di's filename component is moved into 'fi', di is made a dir path */
714 void BLI_splitdirstring(char *di, char *fi)
715 {
716         char *lslash= BLI_last_slash(di);
717
718         if (lslash) {
719                 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
720                 *(lslash+1)=0;
721         } else {
722                 BLI_strncpy(fi, di, FILE_MAXFILE);
723                 di[0]= 0;
724         }
725 }
726
727 void BLI_getlastdir(const char* dir, char *last, int maxlen)
728 {
729         const char *s = dir;
730         const char *lslash = NULL;
731         const char *prevslash = NULL;
732         while (*s) {
733                 if ((*s == '\\') || (*s == '/')) {
734                         prevslash = lslash;
735                         lslash = s;
736                 }
737                 s++;
738         }
739         if (prevslash) {
740                 BLI_strncpy(last, prevslash+1, maxlen);
741         } else {
742                 BLI_strncpy(last, dir, maxlen);
743         }
744 }
745
746 /* This is now only used to really get the user's default document folder */
747 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
748    as default location to save documents */
749 char *BLI_getDefaultDocumentFolder(void) {
750         #if !defined(WIN32)
751                 return getenv("HOME");
752
753         #else /* Windows */
754                 char * ret;
755                 static char documentfolder[MAXPATHLEN];
756                 HRESULT hResult;
757
758                 /* Check for %HOME% env var */
759
760                 ret = getenv("HOME");
761                 if(ret) {
762                         if (BLI_is_dir(ret)) return ret;
763                 }
764                                 
765                 /* add user profile support for WIN 2K / NT.
766                  * This is %APPDATA%, which translates to either
767                  * %USERPROFILE%\Application Data or since Vista
768                  * to %USERPROFILE%\AppData\Roaming
769                  */
770                 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
771                 
772                 if (hResult == S_OK)
773                 {
774                         if (BLI_is_dir(documentfolder)) return documentfolder;
775                 }
776                 
777                 return NULL;
778         #endif
779 }
780
781 /* NEW stuff, to be cleaned up when fully migrated */
782 /* ************************************************************* */
783 /* ************************************************************* */
784
785 // #define PATH_DEBUG2
786
787 static char *blender_version_decimal(void)
788 {
789         static char version_str[5];
790         sprintf(version_str, "%d.%02d", BLENDER_VERSION/100, BLENDER_VERSION%100);
791         return version_str;
792 }
793
794 static int test_path(char *targetpath, char *path_base, char *path_sep, char *folder_name)
795 {
796         char tmppath[FILE_MAX];
797         
798         if(path_sep)    BLI_join_dirfile(tmppath, path_base, path_sep);
799         else                    BLI_strncpy(tmppath, path_base, sizeof(tmppath));
800         
801         BLI_make_file_string("/", targetpath, tmppath, folder_name);
802         
803         if (BLI_is_dir(targetpath)) {
804 #ifdef PATH_DEBUG2
805                 printf("\tpath found: %s\n", targetpath);
806 #endif
807                 return 1;
808         }
809         else {
810 #ifdef PATH_DEBUG2
811                 printf("\tpath missing: %s\n", targetpath);
812 #endif
813                 //targetpath[0] = '\0';
814                 return 0;
815         }
816 }
817
818 static int test_env_path(char *path, char *envvar)
819 {
820         char *env = envvar?getenv(envvar):NULL;
821         if (!env) return 0;
822         
823         if (BLI_is_dir(env)) {
824                 BLI_strncpy(path, env, FILE_MAX);
825                 return 1;
826         } else {
827                 path[0] = '\0';
828                 return 0;
829         }
830 }
831
832 static int get_path_local(char *targetpath, char *folder_name, char *subfolder_name)
833 {
834         extern char bprogname[]; /* argv[0] from creator.c */
835         char bprogdir[FILE_MAX];
836         char relfolder[FILE_MAX];
837         
838 #ifdef PATH_DEBUG2
839         printf("get_path_local...\n");
840 #endif
841         
842         if (subfolder_name) {
843                 BLI_join_dirfile(relfolder, folder_name, subfolder_name);
844         } else {
845                 BLI_strncpy(relfolder, folder_name, FILE_MAX);
846         }
847         
848         /* use argv[0] (bprogname) to get the path to the executable */
849         BLI_split_dirfile(bprogname, bprogdir, NULL);
850         
851         /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
852         if(test_path(targetpath, bprogdir, blender_version_decimal(), relfolder))
853                 return 1;
854
855         return 0;
856 }
857
858 static int get_path_user(char *targetpath, char *folder_name, char *subfolder_name, char *envvar)
859 {
860         char user_path[FILE_MAX];
861         const char *user_base_path;
862         
863         user_path[0] = '\0';
864
865         if (test_env_path(user_path, envvar)) {
866                 if (subfolder_name) {
867                         return test_path(targetpath, user_path, NULL, subfolder_name);
868                 } else {
869                         BLI_strncpy(targetpath, user_path, FILE_MAX);
870                         return 1;
871                 }
872         }
873
874         user_base_path = (const char *)GHOST_getUserDir();
875         if (user_base_path) {
876                 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal());
877         }
878
879         if(!user_path[0])
880                 return 0;
881         
882 #ifdef PATH_DEBUG2
883         printf("get_path_user: %s\n", user_path);
884 #endif
885         
886         if (subfolder_name) {
887                 /* try $HOME/folder_name/subfolder_name */
888                 return test_path(targetpath, user_path, folder_name, subfolder_name);
889         } else {
890                 /* try $HOME/folder_name */
891                 return test_path(targetpath, user_path, NULL, folder_name);
892         }
893 }
894
895 static int get_path_system(char *targetpath, char *folder_name, char *subfolder_name, char *envvar)
896 {
897         char system_path[FILE_MAX];
898         const char *system_base_path;
899
900
901         /* first allow developer only overrides to the system path
902          * these are only used when running blender from source */
903         extern char bprogname[]; /* argv[0] from creator.c */
904         char cwd[FILE_MAX];
905         char relfolder[FILE_MAX];
906         char bprogdir[FILE_MAX];
907
908         /* use argv[0] (bprogname) to get the path to the executable */
909         BLI_split_dirfile(bprogname, bprogdir, NULL);
910
911         if (subfolder_name) {
912                 BLI_join_dirfile(relfolder, folder_name, subfolder_name);
913         } else {
914                 BLI_strncpy(relfolder, folder_name, FILE_MAX);
915         }
916
917         /* try CWD/release/folder_name */
918         if(test_path(targetpath, BLI_getwdN(cwd), "release", relfolder))
919                 return 1;
920         
921         /* try EXECUTABLE_DIR/release/folder_name */
922         if(test_path(targetpath, bprogdir, "release", relfolder))
923                 return 1;
924         /* end developer overrides */
925
926
927
928         system_path[0] = '\0';
929
930         if (test_env_path(system_path, envvar)) {
931                 if (subfolder_name) {
932                         return test_path(targetpath, system_path, NULL, subfolder_name);
933                 } else {
934                         BLI_strncpy(targetpath, system_path, FILE_MAX);
935                         return 1;
936                 }
937         }
938
939         system_base_path = (const char *)GHOST_getSystemDir();
940         if (system_base_path) {
941                 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal());
942         }
943         
944         if(!system_path[0])
945                 return 0;
946         
947 #ifdef PATH_DEBUG2
948         printf("get_path_system: %s\n", system_path);
949 #endif
950         
951         if (subfolder_name) {
952                 /* try $BLENDERPATH/folder_name/subfolder_name */
953                 return test_path(targetpath, system_path, folder_name, subfolder_name);
954         } else {
955                 /* try $BLENDERPATH/folder_name */
956                 return test_path(targetpath, system_path, NULL, folder_name);
957         }
958 }
959
960 /* get a folder out of the 'folder_id' presets for paths */
961 /* returns the path if found, NULL string if not */
962 char *BLI_get_folder(int folder_id, char *subfolder)
963 {
964         static char path[FILE_MAX] = "";
965         
966         switch (folder_id) {
967                 case BLENDER_DATAFILES:         /* general case */
968                         if (get_path_local(path, "datafiles", subfolder)) break;
969                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
970                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES")) break;
971                         return NULL;
972                         
973                 case BLENDER_USER_DATAFILES:
974                         if (get_path_local(path, "datafiles", subfolder)) break;
975                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
976                         return NULL;
977                         
978                 case BLENDER_SYSTEM_DATAFILES:
979                         if (get_path_local(path, "datafiles", subfolder)) break;
980                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES"))  break;
981                         return NULL;
982                         
983                 case BLENDER_USER_AUTOSAVE:
984                         if (get_path_local(path, "autosave", subfolder)) break;
985                         if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES"))       break;
986                         return NULL;
987
988                 case BLENDER_CONFIG:            /* general case */
989                         if (get_path_local(path, "config", subfolder)) break;
990                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
991                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
992                         return NULL;
993                         
994                 case BLENDER_USER_CONFIG:
995                         if (get_path_local(path, "config", subfolder)) break;
996                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
997                         return NULL;
998                         
999                 case BLENDER_SYSTEM_CONFIG:
1000                         if (get_path_local(path, "config", subfolder)) break;
1001                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
1002                         return NULL;
1003                         
1004                 case BLENDER_SCRIPTS:           /* general case */
1005                         if (get_path_local(path, "scripts", subfolder)) break;
1006                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;           
1007                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1008                         return NULL;
1009                         
1010                 case BLENDER_USER_SCRIPTS:
1011                         if (get_path_local(path, "scripts", subfolder)) break;
1012                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;
1013                         return NULL;
1014                         
1015                 case BLENDER_SYSTEM_SCRIPTS:
1016                         if (get_path_local(path, "scripts", subfolder)) break;
1017                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1018                         return NULL;
1019                         
1020                 case BLENDER_PYTHON:            /* general case */
1021                         if (get_path_local(path, "python", subfolder)) break;
1022                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1023                         return NULL;
1024                         
1025                 case BLENDER_SYSTEM_PYTHON:
1026                         if (get_path_local(path, "python", subfolder)) break;
1027                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1028                         return NULL;
1029         }
1030         
1031         return path;
1032 }
1033
1034 char *BLI_get_user_folder_notest(int folder_id, char *subfolder)
1035 {
1036         static char path[FILE_MAX] = "";
1037
1038         switch (folder_id) {
1039                 case BLENDER_USER_DATAFILES:
1040                         get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES");
1041                         break;
1042                 case BLENDER_USER_CONFIG:
1043                         get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG");
1044                         break;
1045                 case BLENDER_USER_AUTOSAVE:
1046                         get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE");
1047                         break;
1048                 case BLENDER_USER_SCRIPTS:
1049                         get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS");
1050                         break;
1051         }
1052         if ('\0' == path[0]) {
1053                 return NULL;
1054         }
1055         return path;
1056 }
1057
1058 char *BLI_get_folder_create(int folder_id, char *subfolder)
1059 {
1060         char *path;
1061
1062         /* only for user folders */
1063         if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1064                 return NULL;
1065         
1066         path = BLI_get_folder(folder_id, subfolder);
1067         
1068         if (!path) {
1069                 path = BLI_get_user_folder_notest(folder_id, subfolder);
1070                 if (path) BLI_recurdir_fileops(path);
1071         }
1072         
1073         return path;
1074 }
1075
1076
1077 /* End new stuff */
1078 /* ************************************************************* */
1079 /* ************************************************************* */
1080
1081
1082
1083 #ifdef PATH_DEBUG
1084 #undef PATH_DEBUG
1085 #endif
1086
1087 void BLI_setenv(const char *env, const char*val)
1088 {
1089         /* SGI or free windows */
1090 #if (defined(__sgi) || ((defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)))
1091         char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1092
1093         sprintf(envstr, "%s=%s", env, val);
1094         putenv(envstr);
1095         MEM_freeN(envstr);
1096
1097         /* non-free windows */
1098 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1099         _putenv_s(env, val);
1100 #else
1101         /* linux/osx/bsd */
1102         setenv(env, val, 1);
1103 #endif
1104 }
1105
1106
1107 /**
1108  Only set an env var if already not there.
1109  Like Unix setenv(env, val, 0);
1110  */
1111 void BLI_setenv_if_new(const char *env, const char* val)
1112 {
1113         if(getenv(env) == NULL)
1114                 BLI_setenv(env, val);
1115 }
1116
1117
1118 void BLI_clean(char *path)
1119 {
1120         if(path==0) return;
1121 #ifdef WIN32
1122         if(path && strlen(path)>2) {
1123                 BLI_char_switch(path+2, '/', '\\');
1124         }
1125 #else
1126         BLI_char_switch(path, '\\', '/');
1127 #endif
1128 }
1129
1130 void BLI_char_switch(char *string, char from, char to) 
1131 {
1132         if(string==0) return;
1133         while (*string != 0) {
1134                 if (*string == from) *string = to;
1135                 string++;
1136         }
1137 }
1138
1139 void BLI_make_exist(char *dir) {
1140         int a;
1141
1142         BLI_char_switch(dir, ALTSEP, SEP);
1143
1144         a = strlen(dir);
1145
1146         while(BLI_is_dir(dir) == 0){
1147                 a --;
1148                 while(dir[a] != SEP){
1149                         a--;
1150                         if (a <= 0) break;
1151                 }
1152                 if (a >= 0) {
1153                         dir[a+1] = '\0';
1154                 }
1155                 else {
1156 #ifdef WIN32
1157                         get_default_root(dir);
1158 #else
1159                         strcpy(dir,"/");
1160 #endif
1161                         break;
1162                 }
1163         }
1164 }
1165
1166 void BLI_make_existing_file(char *name)
1167 {
1168         char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1169
1170         BLI_strncpy(di, name, sizeof(di));
1171         BLI_splitdirstring(di, fi);
1172         
1173         /* test exist */
1174         if (BLI_exists(di) == 0) {
1175                 BLI_recurdir_fileops(di);
1176         }
1177 }
1178
1179
1180 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1181 {
1182         int sl;
1183
1184         if (!string || !dir || !file) return; /* We don't want any NULLs */
1185         
1186         string[0]= 0; /* ton */
1187
1188         /* we first push all slashes into unix mode, just to make sure we don't get
1189            any mess with slashes later on. -jesterKing */
1190         /* constant strings can be passed for those parameters - don't change them - elubie */
1191         /*
1192         BLI_char_switch(relabase, '\\', '/');
1193         BLI_char_switch(dir, '\\', '/');
1194         BLI_char_switch(file, '\\', '/');
1195         */
1196
1197         /* Resolve relative references */       
1198         if (relabase && dir[0] == '/' && dir[1] == '/') {
1199                 char *lslash;
1200                 
1201                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1202                 strcpy(string, relabase);
1203                 
1204                 lslash= BLI_last_slash(string);
1205                 if(lslash) *(lslash+1)= 0;
1206
1207                 dir+=2; /* Skip over the relative reference */
1208         }
1209 #ifdef WIN32
1210         else {
1211                 if (strlen(dir) >= 2 && dir[1] == ':' ) {
1212                         BLI_strncpy(string, dir, 3);
1213                         dir += 2;
1214                 }
1215                 else { /* no drive specified */
1216                         /* first option: get the drive from the relabase if it has one */
1217                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1218                                 BLI_strncpy(string, relabase, 3);       
1219                                 string[2] = '\\';
1220                                 string[3] = '\0';
1221                         }
1222                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1223                                 get_default_root(string);
1224                         }
1225                         
1226                         /* ignore leading slashes */
1227                         while (*dir == '/' || *dir == '\\') dir++;
1228                 }
1229         }
1230 #endif
1231
1232         strcat(string, dir);
1233
1234         /* Make sure string ends in one (and only one) slash */ 
1235         /* first trim all slashes from the end of the string */
1236         sl = strlen(string);
1237         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1238                 string[sl-1] = '\0';
1239                 sl--;
1240         }
1241         /* since we've now removed all slashes, put back one slash at the end. */
1242         strcat(string, "/");
1243         
1244         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1245                 file++;
1246                 
1247         strcat (string, file);
1248         
1249         /* Push all slashes to the system preferred direction */
1250         BLI_clean(string);
1251 }
1252
1253 int BLI_testextensie(const char *str, const char *ext)
1254 {
1255         short a, b;
1256         int retval;
1257
1258         a= strlen(str);
1259         b= strlen(ext);
1260
1261         if(a==0 || b==0 || b>=a) {
1262                 retval = 0;
1263         } else if (BLI_strcasecmp(ext, str + a - b)) {
1264                 retval = 0;     
1265         } else {
1266                 retval = 1;
1267         }
1268
1269         return (retval);
1270 }
1271
1272 int BLI_testextensie_array(const char *str, const char **ext_array)
1273 {
1274         int i=0;
1275         while(ext_array[i]) {
1276                 if(BLI_testextensie(str, ext_array[i])) {
1277                         return 1;
1278                 }
1279
1280                 i++;
1281         }
1282         return 0;
1283 }
1284
1285 /* semicolon separated wildcards, eg:
1286  *  '*.zip;*.py;*.exe' */
1287 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1288 {
1289         const char *ext_step= ext_fnmatch;
1290         char pattern[16];
1291
1292         while(ext_step[0]) {
1293                 char *ext_next;
1294                 int len_ext;
1295
1296                 if((ext_next=strchr(ext_step, ';'))) {
1297                         len_ext= (int)(ext_next - ext_step) + 1;
1298                 }
1299                 else {
1300                         len_ext= sizeof(pattern);
1301                 }
1302
1303                 BLI_strncpy(pattern, ext_step, len_ext);
1304
1305                 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1306                         return 1;
1307                 }
1308                 ext_step += len_ext;
1309         }
1310
1311         return 0;
1312 }
1313
1314
1315 int BLI_replace_extension(char *path, int maxlen, const char *ext)
1316 {
1317         int a;
1318
1319         for(a=strlen(path)-1; a>=0; a--)
1320                 if(path[a] == '.' || path[a] == '/' || path[a] == '\\')
1321                         break;
1322         
1323         if(path[a] != '.')
1324                 a= strlen(path);
1325
1326         if(a + strlen(ext) >= maxlen)
1327                 return 0;
1328
1329         strcpy(path+a, ext);
1330         return 1;
1331 }
1332
1333 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1334  * - wont change 'string'
1335  * - wont create any directories
1336  * - dosnt use CWD, or deal with relative paths.
1337  * - Only fill's in *dir and *file when they are non NULL
1338  * */
1339 void BLI_split_dirfile(const char *string, char *dir, char *file)
1340 {
1341         char *lslash_str = BLI_last_slash(string);
1342         int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0;
1343
1344         if (dir) {
1345                 if (lslash) {
1346                         BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */
1347                 } else {
1348                         dir[0] = '\0';
1349                 }
1350         }
1351         
1352         if (file) {
1353                 strcpy( file, string+lslash);
1354         }
1355 }
1356
1357 /* simple appending of filename to dir, does not check for valid path! */
1358 void BLI_join_dirfile(char *string, const char *dir, const char *file)
1359 {
1360         int sl_dir;
1361         
1362         if(string != dir) /* compare pointers */
1363                 BLI_strncpy(string, dir, FILE_MAX);
1364
1365         if (!file)
1366                 return;
1367         
1368         sl_dir= BLI_add_slash(string);
1369         
1370         if (sl_dir <FILE_MAX) {
1371                 BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
1372         }
1373 }
1374
1375 /* like pythons os.path.basename( ) */
1376 char *BLI_path_basename(char *path)
1377 {
1378         char *filename= BLI_last_slash(path);
1379         return filename ? filename + 1 : path;
1380 }
1381
1382 /*
1383   Produce image export path.
1384
1385   Fails returning 0 if image filename is empty or if destination path
1386   matches image path (i.e. both are the same file).
1387
1388   Trailing slash in dest_dir is optional.
1389
1390   Logic:
1391
1392   - if an image is "below" current .blend file directory, rebuild the
1393         same dir structure in dest_dir
1394
1395   For example //textures/foo/bar.png becomes
1396   [dest_dir]/textures/foo/bar.png.
1397
1398   - if an image is not "below" current .blend file directory,
1399   disregard it's path and copy it in the same directory where 3D file
1400   goes.
1401
1402   For example //../foo/bar.png becomes [dest_dir]/bar.png.
1403
1404   This logic will help ensure that all image paths are relative and
1405   that a user gets his images in one place. It'll also provide
1406   consistent behaviour across exporters.
1407  */
1408 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)
1409 {
1410         char path[FILE_MAX];
1411         char dir[FILE_MAX];
1412         char base[FILE_MAX];
1413         char blend_dir[FILE_MAX];       /* directory, where current .blend file resides */
1414         char dest_path[FILE_MAX];
1415         char rel_dir[FILE_MAX];
1416         int len;
1417
1418         if (abs)
1419                 abs[0]= 0;
1420
1421         if (rel)
1422                 rel[0]= 0;
1423
1424         BLI_split_dirfile(base_dir, blend_dir, NULL);
1425
1426         if (src_dir[0]=='\0')
1427                 return 0;
1428
1429         BLI_strncpy(path, src_dir, sizeof(path));
1430
1431         /* expand "//" in filename and get absolute path */
1432         BLI_path_abs(path, base_dir);
1433
1434         /* get the directory part */
1435         BLI_split_dirfile(path, dir, base);
1436
1437         len= strlen(blend_dir);
1438
1439         rel_dir[0] = 0;
1440
1441         /* if image is "below" current .blend file directory */
1442         if (!strncmp(path, blend_dir, len)) {
1443
1444                 /* if image is _in_ current .blend file directory */
1445                 if (!strcmp(dir, blend_dir)) {
1446                         BLI_join_dirfile(dest_path, dest_dir, base);
1447                 }
1448                 /* "below" */
1449                 else {
1450                         /* rel = image_path_dir - blend_dir */
1451                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1452
1453                         BLI_join_dirfile(dest_path, dest_dir, rel_dir);
1454                         BLI_join_dirfile(dest_path, dest_path, base);
1455                 }
1456
1457         }
1458         /* image is out of current directory */
1459         else {
1460                 BLI_join_dirfile(dest_path, dest_dir, base);
1461         }
1462
1463         if (abs)
1464                 BLI_strncpy(abs, dest_path, abs_size);
1465
1466         if (rel) {
1467                 strncat(rel, rel_dir, rel_size);
1468                 strncat(rel, base, rel_size);
1469         }
1470
1471         /* return 2 if src=dest */
1472         if (!strcmp(path, dest_path)) {
1473                 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1474                 return 2;
1475         }
1476
1477         return 1;
1478 }
1479
1480 char *BLI_first_slash(char *string) {
1481         char *ffslash, *fbslash;
1482         
1483         ffslash= strchr(string, '/');   
1484         fbslash= strchr(string, '\\');
1485         
1486         if (!ffslash) return fbslash;
1487         else if (!fbslash) return ffslash;
1488         
1489         if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1490         else return fbslash;
1491 }
1492
1493 char *BLI_last_slash(const char *string) {
1494         char *lfslash, *lbslash;
1495         
1496         lfslash= strrchr(string, '/');  
1497         lbslash= strrchr(string, '\\');
1498
1499         if (!lfslash) return lbslash; 
1500         else if (!lbslash) return lfslash;
1501         
1502         if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1503         else return lfslash;
1504 }
1505
1506 /* adds a slash if there isnt one there already */
1507 int BLI_add_slash(char *string) {
1508         int len = strlen(string);
1509 #ifdef WIN32
1510         if (len==0 || string[len-1]!='\\') {
1511                 string[len] = '\\';
1512                 string[len+1] = '\0';
1513                 return len+1;
1514         }
1515 #else
1516         if (len==0 || string[len-1]!='/') {
1517                 string[len] = '/';
1518                 string[len+1] = '\0';
1519                 return len+1;
1520         }
1521 #endif
1522         return len;
1523 }
1524
1525 /* removes a slash if there is one */
1526 void BLI_del_slash(char *string) {
1527         int len = strlen(string);
1528         while (len) {
1529 #ifdef WIN32
1530                 if (string[len-1]=='\\') {
1531 #else
1532                 if (string[len-1]=='/') {
1533 #endif
1534                         string[len-1] = '\0';
1535                         len--;
1536                 } else {
1537                         break;
1538                 }
1539         }
1540 }
1541
1542 static int add_win32_extension(char *name)
1543 {
1544         int retval = 0;
1545         int type;
1546
1547         type = BLI_exist(name);
1548         if ((type == 0) || S_ISDIR(type)) {
1549 #ifdef _WIN32
1550                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1551                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1552                 char *extensions = getenv("PATHEXT");
1553                 if (extensions) {
1554                         char *temp;
1555                         do {
1556                                 strcpy(filename, name);
1557                                 temp = strstr(extensions, ";");
1558                                 if (temp) {
1559                                         strncpy(ext, extensions, temp - extensions);
1560                                         ext[temp - extensions] = 0;
1561                                         extensions = temp + 1;
1562                                         strcat(filename, ext);
1563                                 } else {
1564                                         strcat(filename, extensions);
1565                                 }
1566
1567                                 type = BLI_exist(filename);
1568                                 if (type && (! S_ISDIR(type))) {
1569                                         retval = 1;
1570                                         strcpy(name, filename);
1571                                         break;
1572                                 }
1573                         } while (temp);
1574                 }
1575 #endif
1576         } else {
1577                 retval = 1;
1578         }
1579
1580         return (retval);
1581 }
1582
1583 void BLI_where_am_i(char *fullname, const char *name)
1584 {
1585         char filename[FILE_MAXDIR+FILE_MAXFILE];
1586         char *path = NULL, *temp;
1587         
1588 #ifdef _WIN32
1589         char *separator = ";";
1590         char slash = '\\';
1591 #else
1592         char *separator = ":";
1593         char slash = '/';
1594 #endif
1595
1596         
1597 #ifdef __linux__
1598         /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1599         path = br_find_exe( NULL );
1600         if (path) {
1601                 BLI_strncpy(fullname, path, FILE_MAXDIR+FILE_MAXFILE);
1602                 free(path);
1603                 return;
1604         }
1605 #endif
1606
1607 #ifdef _WIN32
1608         if(GetModuleFileName(0, fullname, FILE_MAXDIR+FILE_MAXFILE)) {
1609                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1610                 return;
1611         }
1612 #endif
1613
1614         /* unix and non linux */
1615         if (name && fullname && strlen(name)) {
1616                 strcpy(fullname, name);
1617                 if (name[0] == '.') {
1618                         // relative path, prepend cwd
1619                         BLI_getwdN(fullname);
1620                         
1621                         // not needed but avoids annoying /./ in name
1622                         if(name && name[0]=='.' && name[1]==slash)
1623                                 BLI_join_dirfile(fullname, fullname, name+2);
1624                         else
1625                                 BLI_join_dirfile(fullname, fullname, name);
1626                         
1627                         add_win32_extension(fullname);
1628                 } else if (BLI_last_slash(name)) {
1629                         // full path
1630                         strcpy(fullname, name);
1631                         add_win32_extension(fullname);
1632                 } else {
1633                         // search for binary in $PATH
1634                         path = getenv("PATH");
1635                         if (path) {
1636                                 do {
1637                                         temp = strstr(path, separator);
1638                                         if (temp) {
1639                                                 strncpy(filename, path, temp - path);
1640                                                 filename[temp - path] = 0;
1641                                                 path = temp + 1;
1642                                         } else {
1643                                                 strncpy(filename, path, sizeof(filename));
1644                                         }
1645                                         BLI_join_dirfile(fullname, fullname, name);
1646                                         if (add_win32_extension(filename)) {
1647                                                 strcpy(fullname, filename);
1648                                                 break;
1649                                         }
1650                                 } while (temp);
1651                         }
1652                 }
1653 #if defined(DEBUG)
1654                 if (strcmp(name, fullname)) {
1655                         printf("guessing '%s' == '%s'\n", name, fullname);
1656                 }
1657 #endif
1658
1659 #ifdef _WIN32
1660                 // in windows change long filename to short filename because
1661                 // win2k doesn't know how to parse a commandline with lots of
1662                 // spaces and double-quotes. There's another solution to this
1663                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1664                 // that's even uglier
1665                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1666 #if defined(DEBUG)
1667                 printf("Shortname = '%s'\n", fullname);
1668 #endif
1669 #endif
1670         }
1671 }
1672
1673 void BLI_where_is_temp(char *fullname, int usertemp)
1674 {
1675         fullname[0] = '\0';
1676         
1677         if (usertemp && BLI_is_dir(U.tempdir)) {
1678                 strcpy(fullname, U.tempdir);
1679         }
1680         
1681         
1682 #ifdef WIN32
1683         if (fullname[0] == '\0') {
1684                 char *tmp = getenv("TEMP"); /* Windows */
1685                 if (tmp && BLI_is_dir(tmp)) {
1686                         strcpy(fullname, tmp);
1687                 }
1688         }
1689 #else
1690         /* Other OS's - Try TMP and TMPDIR */
1691         if (fullname[0] == '\0') {
1692                 char *tmp = getenv("TMP");
1693                 if (tmp && BLI_is_dir(tmp)) {
1694                         strcpy(fullname, tmp);
1695                 }
1696         }
1697         
1698         if (fullname[0] == '\0') {
1699                 char *tmp = getenv("TMPDIR");
1700                 if (tmp && BLI_is_dir(tmp)) {
1701                         strcpy(fullname, tmp);
1702                 }
1703         }
1704 #endif  
1705         
1706         if (fullname[0] == '\0') {
1707                 strcpy(fullname, "/tmp/");
1708         } else {
1709                 /* add a trailing slash if needed */
1710                 BLI_add_slash(fullname);
1711 #ifdef WIN32
1712                 strcpy(U.tempdir, fullname); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1713 #endif
1714         }
1715 }
1716
1717 char *get_install_dir(void) {
1718         extern char bprogname[];
1719         char *tmpname = BLI_strdup(bprogname);
1720         char *cut;
1721
1722 #ifdef __APPLE__
1723         cut = strstr(tmpname, ".app");
1724         if (cut) cut[0] = 0;
1725 #endif
1726
1727         cut = BLI_last_slash(tmpname);
1728
1729         if (cut) {
1730                 cut[0] = 0;
1731                 return tmpname;
1732         } else {
1733                 MEM_freeN(tmpname);
1734                 return NULL;
1735         }
1736 }
1737
1738 #ifdef WITH_ICONV
1739
1740 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1741 {
1742         size_t inbytesleft=strlen(original);
1743         size_t outbytesleft=512;
1744         size_t rv=0;
1745         iconv_t cd;
1746         
1747         if (NULL == code) {
1748                 code = locale_charset();
1749         }
1750         cd=iconv_open("UTF-8", code);
1751
1752         if (cd == (iconv_t)(-1)) {
1753                 printf("iconv_open Error");
1754                 *utf_8='\0';
1755                 return ;
1756         }
1757         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1758         if (rv == (size_t) -1) {
1759                 printf("iconv Error\n");
1760                 return ;
1761         }
1762         *utf_8 = '\0';
1763         iconv_close(cd);
1764 }
1765 #endif // WITH_ICONV
1766
1767