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