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