Move copying of %TEMP% to U.tempdir after slash adding. Otherwise path is handled...
[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         /* try ./.blender/folder_name -- DEPRECATED, need to update build systems */
877         if(test_path(targetpath, bprogdir, ".blender", relfolder))
878                 return 1;
879
880         return 0;
881 }
882
883 static int get_path_user(char *targetpath, char *folder_name, char *subfolder_name, char *envvar)
884 {
885         char user_path[FILE_MAX];
886         const char *user_base_path;
887         
888         user_path[0] = '\0';
889
890         if (test_env_path(user_path, envvar)) {
891                 if (subfolder_name) {
892                         return test_path(targetpath, user_path, NULL, subfolder_name);
893                 } else {
894                         BLI_strncpy(targetpath, user_path, FILE_MAX);
895                         return 1;
896                 }
897         }
898
899         user_base_path = (const char *)GHOST_getUserDir();
900         if (user_base_path) {
901                 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal());
902         }
903
904         if(!user_path[0])
905                 return 0;
906         
907 #ifdef PATH_DEBUG2
908         printf("get_path_user: %s\n", user_path);
909 #endif
910         
911         if (subfolder_name) {
912                 /* try $HOME/folder_name/subfolder_name */
913                 return test_path(targetpath, user_path, folder_name, subfolder_name);
914         } else {
915                 /* try $HOME/folder_name */
916                 return test_path(targetpath, user_path, NULL, folder_name);
917         }
918 }
919
920 static int get_path_system(char *targetpath, char *folder_name, char *subfolder_name, char *envvar)
921 {
922         char system_path[FILE_MAX];
923         const char *system_base_path;
924
925         system_path[0] = '\0';
926
927         if (test_env_path(system_path, envvar)) {
928                 if (subfolder_name) {
929                         return test_path(targetpath, system_path, NULL, subfolder_name);
930                 } else {
931                         BLI_strncpy(targetpath, system_path, FILE_MAX);
932                         return 1;
933                 }
934         }
935
936         system_base_path = (const char *)GHOST_getSystemDir();
937         if (system_base_path) {
938                 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal());
939         }
940         
941         if(!system_path[0])
942                 return 0;
943         
944 #ifdef PATH_DEBUG2
945         printf("get_path_system: %s\n", system_path);
946 #endif
947         
948         if (subfolder_name) {
949                 /* try $BLENDERPATH/folder_name/subfolder_name */
950                 return test_path(targetpath, system_path, folder_name, subfolder_name);
951         } else {
952                 /* try $BLENDERPATH/folder_name */
953                 return test_path(targetpath, system_path, NULL, folder_name);
954         }
955 }
956
957 /* get a folder out of the 'folder_id' presets for paths */
958 /* returns the path if found, NULL string if not */
959 char *BLI_get_folder(int folder_id, char *subfolder)
960 {
961         static char path[FILE_MAX] = "";
962         
963         switch (folder_id) {
964                 case BLENDER_DATAFILES:         /* general case */
965                         if (get_path_local(path, "datafiles", subfolder)) break;
966                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
967                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES")) break;
968                         return NULL;
969                         
970                 case BLENDER_USER_DATAFILES:
971                         if (get_path_local(path, "datafiles", subfolder)) break;
972                         if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES"))      break;
973                         return NULL;
974                         
975                 case BLENDER_SYSTEM_DATAFILES:
976                         if (get_path_local(path, "datafiles", subfolder)) break;
977                         if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES"))  break;
978                         return NULL;
979                         
980                 case BLENDER_USER_AUTOSAVE:
981                         if (get_path_local(path, "autosave", subfolder)) break;
982                         if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES"))       break;
983                         return NULL;
984
985                 case BLENDER_CONFIG:            /* general case */
986                         if (get_path_local(path, "config", subfolder)) break;
987                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
988                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
989                         return NULL;
990                         
991                 case BLENDER_USER_CONFIG:
992                         if (get_path_local(path, "config", subfolder)) break;
993                         if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG")) break;
994                         return NULL;
995                         
996                 case BLENDER_SYSTEM_CONFIG:
997                         if (get_path_local(path, "config", subfolder)) break;
998                         if (get_path_system(path, "config", subfolder, "BLENDER_SYSTEM_CONFIG")) break;
999                         return NULL;
1000                         
1001                 case BLENDER_SCRIPTS:           /* general case */
1002                         if (get_path_local(path, "scripts", subfolder)) break;
1003                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;           
1004                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1005                         return NULL;
1006                         
1007                 case BLENDER_USER_SCRIPTS:
1008                         if (get_path_local(path, "scripts", subfolder)) break;
1009                         if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS")) break;
1010                         return NULL;
1011                         
1012                 case BLENDER_SYSTEM_SCRIPTS:
1013                         if (get_path_local(path, "scripts", subfolder)) break;
1014                         if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS")) break;
1015                         return NULL;
1016                         
1017                 case BLENDER_PYTHON:            /* general case */
1018                         if (get_path_local(path, "python", subfolder)) break;
1019                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1020                         return NULL;
1021                         
1022                 case BLENDER_SYSTEM_PYTHON:
1023                         if (get_path_local(path, "python", subfolder)) break;
1024                         if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON")) break;
1025                         return NULL;
1026         }
1027         
1028         return path;
1029 }
1030
1031 static char *BLI_get_user_folder_notest(int folder_id, char *subfolder)
1032 {
1033         static char path[FILE_MAX] = "";
1034
1035         switch (folder_id) {
1036                 case BLENDER_USER_DATAFILES:
1037                         get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES");
1038                         break;
1039                 case BLENDER_USER_CONFIG:
1040                         get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG");
1041                         break;
1042                 case BLENDER_USER_AUTOSAVE:
1043                         get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE");
1044                         break;
1045         }
1046         if ('\0' == path[0]) {
1047                 return NULL;
1048         }
1049         return path;
1050 }
1051
1052 char *BLI_get_folder_create(int folder_id, char *subfolder)
1053 {
1054         char *path;
1055
1056         /* only for user folders */
1057         if (!ELEM3(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_AUTOSAVE))
1058                 return NULL;
1059         
1060         path = BLI_get_folder(folder_id, subfolder);
1061         
1062         if (!path) {
1063                 path = BLI_get_user_folder_notest(folder_id, subfolder);
1064                 if (path) BLI_recurdir_fileops(path);
1065         }
1066         
1067         return path;
1068 }
1069
1070
1071 /* End new stuff */
1072 /* ************************************************************* */
1073 /* ************************************************************* */
1074
1075
1076
1077 #ifdef PATH_DEBUG
1078 #undef PATH_DEBUG
1079 #endif
1080
1081 void BLI_setenv(const char *env, const char*val)
1082 {
1083         /* SGI or free windows */
1084 #if (defined(__sgi) || ((defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)))
1085         char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1086
1087         sprintf(envstr, "%s=%s", env, val);
1088         putenv(envstr);
1089         MEM_freeN(envstr);
1090
1091         /* non-free windows */
1092 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1093         _putenv_s(env, val);
1094 #else
1095         /* linux/osx/bsd */
1096         setenv(env, val, 1);
1097 #endif
1098 }
1099
1100
1101 /**
1102  Only set an env var if already not there.
1103  Like Unix setenv(env, val, 0);
1104  */
1105 void BLI_setenv_if_new(const char *env, const char* val)
1106 {
1107         if(getenv(env) == NULL)
1108                 BLI_setenv(env, val);
1109 }
1110
1111
1112 void BLI_clean(char *path)
1113 {
1114         if(path==0) return;
1115 #ifdef WIN32
1116         if(path && strlen(path)>2) {
1117                 BLI_char_switch(path+2, '/', '\\');
1118         }
1119 #else
1120         BLI_char_switch(path, '\\', '/');
1121 #endif
1122 }
1123
1124 void BLI_char_switch(char *string, char from, char to) 
1125 {
1126         if(string==0) return;
1127         while (*string != 0) {
1128                 if (*string == from) *string = to;
1129                 string++;
1130         }
1131 }
1132
1133 void BLI_make_exist(char *dir) {
1134         int a;
1135
1136         #ifdef WIN32
1137                 BLI_char_switch(dir, '/', '\\');
1138         #else
1139                 BLI_char_switch(dir, '\\', '/');
1140         #endif  
1141         
1142         a = strlen(dir);
1143         
1144 #ifdef WIN32    
1145         while(BLI_is_dir(dir) == 0){
1146                 a --;
1147                 while(dir[a] != '\\'){
1148                         a--;
1149                         if (a <= 0) break;
1150                 }
1151                 if (a >= 0) dir[a+1] = 0;
1152                 else {
1153                         /* defaulting to drive (usually 'C:') of Windows installation */
1154                         get_default_root(dir);
1155                         break;
1156                 }
1157         }
1158 #else
1159         while(BLI_is_dir(dir) == 0){
1160                 a --;
1161                 while(dir[a] != '/'){
1162                         a--;
1163                         if (a <= 0) break;
1164                 }
1165                 if (a >= 0) dir[a+1] = 0;
1166                 else {
1167                         strcpy(dir,"/");
1168                         break;
1169                 }
1170         }
1171 #endif
1172 }
1173
1174 void BLI_make_existing_file(char *name)
1175 {
1176         char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1177
1178         BLI_strncpy(di, name, sizeof(di));
1179         BLI_splitdirstring(di, fi);
1180         
1181         /* test exist */
1182         if (BLI_exists(di) == 0) {
1183                 BLI_recurdir_fileops(di);
1184         }
1185 }
1186
1187
1188 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1189 {
1190         int sl;
1191
1192         if (!string || !dir || !file) return; /* We don't want any NULLs */
1193         
1194         string[0]= 0; /* ton */
1195
1196         /* we first push all slashes into unix mode, just to make sure we don't get
1197            any mess with slashes later on. -jesterKing */
1198         /* constant strings can be passed for those parameters - don't change them - elubie */
1199         /*
1200         BLI_char_switch(relabase, '\\', '/');
1201         BLI_char_switch(dir, '\\', '/');
1202         BLI_char_switch(file, '\\', '/');
1203         */
1204
1205         /* Resolve relative references */       
1206         if (relabase && dir[0] == '/' && dir[1] == '/') {
1207                 char *lslash;
1208                 
1209                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1210                 strcpy(string, relabase);
1211                 
1212                 lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\');
1213                 
1214                 if(lslash) *(lslash+1)= 0;
1215
1216                 dir+=2; /* Skip over the relative reference */
1217         }
1218 #ifdef WIN32
1219         else {
1220                 if (strlen(dir) >= 2 && dir[1] == ':' ) {
1221                         BLI_strncpy(string, dir, 3);
1222                         dir += 2;
1223                 }
1224                 else { /* no drive specified */
1225                         /* first option: get the drive from the relabase if it has one */
1226                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1227                                 BLI_strncpy(string, relabase, 3);       
1228                                 string[2] = '\\';
1229                                 string[3] = '\0';
1230                         }
1231                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1232                                 get_default_root(string);
1233                         }
1234                         
1235                         /* ignore leading slashes */
1236                         while (*dir == '/' || *dir == '\\') dir++;
1237                 }
1238         }
1239 #endif
1240
1241         strcat(string, dir);
1242
1243         /* Make sure string ends in one (and only one) slash */ 
1244         /* first trim all slashes from the end of the string */
1245         sl = strlen(string);
1246         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1247                 string[sl-1] = '\0';
1248                 sl--;
1249         }
1250         /* since we've now removed all slashes, put back one slash at the end. */
1251         strcat(string, "/");
1252         
1253         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1254                 file++;
1255                 
1256         strcat (string, file);
1257         
1258         /* Push all slashes to the system preferred direction */
1259         BLI_clean(string);
1260 }
1261
1262 int BLI_testextensie(const char *str, const char *ext)
1263 {
1264         short a, b;
1265         int retval;
1266
1267         a= strlen(str);
1268         b= strlen(ext);
1269
1270         if(a==0 || b==0 || b>=a) {
1271                 retval = 0;
1272         } else if (BLI_strcasecmp(ext, str + a - b)) {
1273                 retval = 0;     
1274         } else {
1275                 retval = 1;
1276         }
1277
1278         return (retval);
1279 }
1280
1281 int BLI_testextensie_array(const char *str, const char **ext_array)
1282 {
1283         int i=0;
1284         while(ext_array[i]) {
1285                 if(BLI_testextensie(str, ext_array[i])) {
1286                         return 1;
1287                 }
1288
1289                 i++;
1290         }
1291         return 0;
1292 }
1293
1294 /* semicolon separated wildcards, eg:
1295  *  '*.zip;*.py;*.exe' */
1296 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1297 {
1298         const char *ext_step= ext_fnmatch;
1299         char pattern[16];
1300
1301         while(ext_step[0]) {
1302                 char *ext_next;
1303                 int len_ext;
1304
1305                 if((ext_next=strchr(ext_step, ';'))) {
1306                         len_ext= (int)(ext_next - ext_step) + 1;
1307                 }
1308                 else {
1309                         len_ext= sizeof(pattern);
1310                 }
1311
1312                 BLI_strncpy(pattern, ext_step, len_ext);
1313
1314                 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1315                         return 1;
1316                 }
1317                 ext_step += len_ext;
1318         }
1319
1320         return 0;
1321 }
1322
1323
1324 int BLI_replace_extension(char *path, int maxlen, const char *ext)
1325 {
1326         int a;
1327
1328         for(a=strlen(path)-1; a>=0; a--)
1329                 if(path[a] == '.' || path[a] == '/' || path[a] == '\\')
1330                         break;
1331         
1332         if(path[a] != '.')
1333                 a= strlen(path);
1334
1335         if(a + strlen(ext) >= maxlen)
1336                 return 0;
1337
1338         strcpy(path+a, ext);
1339         return 1;
1340 }
1341
1342 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1343  * - wont change 'string'
1344  * - wont create any directories
1345  * - dosnt use CWD, or deal with relative paths.
1346  * - Only fill's in *dir and *file when they are non NULL
1347  * */
1348 void BLI_split_dirfile(const char *string, char *dir, char *file)
1349 {
1350         char *lslash_str = BLI_last_slash(string);
1351         int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0;
1352
1353         if (dir) {
1354                 if (lslash) {
1355                         BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */
1356                 } else {
1357                         dir[0] = '\0';
1358                 }
1359         }
1360         
1361         if (file) {
1362                 strcpy( file, string+lslash);
1363         }
1364 }
1365
1366 /* simple appending of filename to dir, does not check for valid path! */
1367 void BLI_join_dirfile(char *string, const char *dir, const char *file)
1368 {
1369         int sl_dir;
1370         
1371         if(string != dir) /* compare pointers */
1372                 BLI_strncpy(string, dir, FILE_MAX);
1373
1374         if (!file)
1375                 return;
1376         
1377         sl_dir= BLI_add_slash(string);
1378         
1379         if (sl_dir <FILE_MAX) {
1380                 BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
1381         }
1382 }
1383
1384 /* like pythons os.path.basename( ) */
1385 char *BLI_path_basename(char *path)
1386 {
1387         char *filename= BLI_last_slash(path);
1388         return filename ? filename + 1 : path;
1389 }
1390
1391 /*
1392   Produce image export path.
1393
1394   Fails returning 0 if image filename is empty or if destination path
1395   matches image path (i.e. both are the same file).
1396
1397   Trailing slash in dest_dir is optional.
1398
1399   Logic:
1400
1401   - if an image is "below" current .blend file directory, rebuild the
1402         same dir structure in dest_dir
1403
1404   For example //textures/foo/bar.png becomes
1405   [dest_dir]/textures/foo/bar.png.
1406
1407   - if an image is not "below" current .blend file directory,
1408   disregard it's path and copy it in the same directory where 3D file
1409   goes.
1410
1411   For example //../foo/bar.png becomes [dest_dir]/bar.png.
1412
1413   This logic will help ensure that all image paths are relative and
1414   that a user gets his images in one place. It'll also provide
1415   consistent behaviour across exporters.
1416  */
1417 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)
1418 {
1419         char path[FILE_MAX];
1420         char dir[FILE_MAX];
1421         char base[FILE_MAX];
1422         char blend_dir[FILE_MAX];       /* directory, where current .blend file resides */
1423         char dest_path[FILE_MAX];
1424         char rel_dir[FILE_MAX];
1425         int len;
1426
1427         if (abs)
1428                 abs[0]= 0;
1429
1430         if (rel)
1431                 rel[0]= 0;
1432
1433         BLI_split_dirfile(base_dir, blend_dir, NULL);
1434
1435         if (src_dir[0]=='\0')
1436                 return 0;
1437
1438         BLI_strncpy(path, src_dir, sizeof(path));
1439
1440         /* expand "//" in filename and get absolute path */
1441         BLI_path_abs(path, base_dir);
1442
1443         /* get the directory part */
1444         BLI_split_dirfile(path, dir, base);
1445
1446         len= strlen(blend_dir);
1447
1448         rel_dir[0] = 0;
1449
1450         /* if image is "below" current .blend file directory */
1451         if (!strncmp(path, blend_dir, len)) {
1452
1453                 /* if image is _in_ current .blend file directory */
1454                 if (!strcmp(dir, blend_dir)) {
1455                         BLI_join_dirfile(dest_path, dest_dir, base);
1456                 }
1457                 /* "below" */
1458                 else {
1459                         /* rel = image_path_dir - blend_dir */
1460                         BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1461
1462                         BLI_join_dirfile(dest_path, dest_dir, rel_dir);
1463                         BLI_join_dirfile(dest_path, dest_path, base);
1464                 }
1465
1466         }
1467         /* image is out of current directory */
1468         else {
1469                 BLI_join_dirfile(dest_path, dest_dir, base);
1470         }
1471
1472         if (abs)
1473                 BLI_strncpy(abs, dest_path, abs_size);
1474
1475         if (rel) {
1476                 strncat(rel, rel_dir, rel_size);
1477                 strncat(rel, base, rel_size);
1478         }
1479
1480         /* return 2 if src=dest */
1481         if (!strcmp(path, dest_path)) {
1482                 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1483                 return 2;
1484         }
1485
1486         return 1;
1487 }
1488
1489
1490 static int add_win32_extension(char *name)
1491 {
1492         int retval = 0;
1493         int type;
1494
1495         type = BLI_exist(name);
1496         if ((type == 0) || S_ISDIR(type)) {
1497 #ifdef _WIN32
1498                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1499                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1500                 char *extensions = getenv("PATHEXT");
1501                 if (extensions) {
1502                         char *temp;
1503                         do {
1504                                 strcpy(filename, name);
1505                                 temp = strstr(extensions, ";");
1506                                 if (temp) {
1507                                         strncpy(ext, extensions, temp - extensions);
1508                                         ext[temp - extensions] = 0;
1509                                         extensions = temp + 1;
1510                                         strcat(filename, ext);
1511                                 } else {
1512                                         strcat(filename, extensions);
1513                                 }
1514
1515                                 type = BLI_exist(filename);
1516                                 if (type && (! S_ISDIR(type))) {
1517                                         retval = 1;
1518                                         strcpy(name, filename);
1519                                         break;
1520                                 }
1521                         } while (temp);
1522                 }
1523 #endif
1524         } else {
1525                 retval = 1;
1526         }
1527
1528         return (retval);
1529 }
1530
1531 void BLI_where_am_i(char *fullname, const char *name)
1532 {
1533         char filename[FILE_MAXDIR+FILE_MAXFILE];
1534         char *path = NULL, *temp;
1535         
1536 #ifdef _WIN32
1537         char *separator = ";";
1538         char slash = '\\';
1539 #else
1540         char *separator = ":";
1541         char slash = '/';
1542 #endif
1543
1544         
1545 #ifdef __linux__
1546         /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1547         path = br_find_exe( NULL );
1548         if (path) {
1549                 BLI_strncpy(fullname, path, FILE_MAXDIR+FILE_MAXFILE);
1550                 free(path);
1551                 return;
1552         }
1553 #endif
1554
1555 #ifdef _WIN32
1556         if(GetModuleFileName(0, fullname, FILE_MAXDIR+FILE_MAXFILE)) {
1557                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1558                 return;
1559         }
1560 #endif
1561
1562         /* unix and non linux */
1563         if (name && fullname && strlen(name)) {
1564                 strcpy(fullname, name);
1565                 if (name[0] == '.') {
1566                         // relative path, prepend cwd
1567                         BLI_getwdN(fullname);
1568                         
1569                         // not needed but avoids annoying /./ in name
1570                         if(name && name[0]=='.' && name[1]==slash)
1571                                 BLI_join_dirfile(fullname, fullname, name+2);
1572                         else
1573                                 BLI_join_dirfile(fullname, fullname, name);
1574                         
1575                         add_win32_extension(fullname);
1576                 } else if (BLI_last_slash(name)) {
1577                         // full path
1578                         strcpy(fullname, name);
1579                         add_win32_extension(fullname);
1580                 } else {
1581                         // search for binary in $PATH
1582                         path = getenv("PATH");
1583                         if (path) {
1584                                 do {
1585                                         temp = strstr(path, separator);
1586                                         if (temp) {
1587                                                 strncpy(filename, path, temp - path);
1588                                                 filename[temp - path] = 0;
1589                                                 path = temp + 1;
1590                                         } else {
1591                                                 strncpy(filename, path, sizeof(filename));
1592                                         }
1593                                         BLI_join_dirfile(fullname, fullname, name);
1594                                         if (add_win32_extension(filename)) {
1595                                                 strcpy(fullname, filename);
1596                                                 break;
1597                                         }
1598                                 } while (temp);
1599                         }
1600                 }
1601 #ifndef NDEBUG
1602                 if (strcmp(name, fullname)) {
1603                         printf("guessing '%s' == '%s'\n", name, fullname);
1604                 }
1605 #endif
1606
1607 #ifdef _WIN32
1608                 // in windows change long filename to short filename because
1609                 // win2k doesn't know how to parse a commandline with lots of
1610                 // spaces and double-quotes. There's another solution to this
1611                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1612                 // that's even uglier
1613                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1614 #ifndef NDEBUG
1615                 printf("Shortname = '%s'\n", fullname);
1616 #endif
1617 #endif
1618         }
1619 }
1620
1621 void BLI_where_is_temp(char *fullname, int usertemp)
1622 {
1623         fullname[0] = '\0';
1624         
1625         if (usertemp && BLI_is_dir(U.tempdir)) {
1626                 strcpy(fullname, U.tempdir);
1627         }
1628         
1629         
1630 #ifdef WIN32
1631         if (fullname[0] == '\0') {
1632                 char *tmp = getenv("TEMP"); /* Windows */
1633                 if (tmp && BLI_is_dir(tmp)) {
1634                         strcpy(fullname, tmp);
1635                 }
1636         }
1637 #else
1638         /* Other OS's - Try TMP and TMPDIR */
1639         if (fullname[0] == '\0') {
1640                 char *tmp = getenv("TMP");
1641                 if (tmp && BLI_is_dir(tmp)) {
1642                         strcpy(fullname, tmp);
1643                 }
1644         }
1645         
1646         if (fullname[0] == '\0') {
1647                 char *tmp = getenv("TMPDIR");
1648                 if (tmp && BLI_is_dir(tmp)) {
1649                         strcpy(fullname, tmp);
1650                 }
1651         }
1652 #endif  
1653         
1654         if (fullname[0] == '\0') {
1655                 strcpy(fullname, "/tmp/");
1656         } else {
1657                 /* add a trailing slash if needed */
1658                 BLI_add_slash(fullname);
1659 #ifdef WIN32
1660                 strcpy(U.tempdir, fullname); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1661 #endif
1662         }
1663 }
1664
1665 char *get_install_dir(void) {
1666         extern char bprogname[];
1667         char *tmpname = BLI_strdup(bprogname);
1668         char *cut;
1669
1670 #ifdef __APPLE__
1671         cut = strstr(tmpname, ".app");
1672         if (cut) cut[0] = 0;
1673 #endif
1674
1675         cut = BLI_last_slash(tmpname);
1676
1677         if (cut) {
1678                 cut[0] = 0;
1679                 return tmpname;
1680         } else {
1681                 MEM_freeN(tmpname);
1682                 return NULL;
1683         }
1684 }
1685
1686 #ifdef WITH_ICONV
1687
1688 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1689 {
1690         size_t inbytesleft=strlen(original);
1691         size_t outbytesleft=512;
1692         size_t rv=0;
1693         iconv_t cd;
1694         
1695         if (NULL == code) {
1696                 code = locale_charset();
1697         }
1698         cd=iconv_open("UTF-8", code);
1699
1700         if (cd == (iconv_t)(-1)) {
1701                 printf("iconv_open Error");
1702                 *utf_8='\0';
1703                 return ;
1704         }
1705         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1706         if (rv == (size_t) -1) {
1707                 printf("iconv Error\n");
1708                 return ;
1709         }
1710         *utf_8 = '\0';
1711         iconv_close(cd);
1712 }
1713 #endif // WITH_ICONV
1714
1715