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