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