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