* renamed BKE_sequence.h and sequence.c --> sequencer
[blender.git] / source / blender / blenlib / intern / path_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, const 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
996 /**
997  Only set an env var if already not there.
998  Like Unix setenv(env, val, 0);
999  */
1000 void BLI_setenv_if_new(const char *env, const char* val)
1001 {
1002         if(getenv(env) == NULL)
1003                 BLI_setenv(env, val);
1004 }
1005
1006
1007 void BLI_clean(char *path)
1008 {
1009         if(path==0) return;
1010 #ifdef WIN32
1011         if(path && strlen(path)>2) {
1012                 BLI_char_switch(path+2, '/', '\\');
1013         }
1014 #else
1015         BLI_char_switch(path, '\\', '/');
1016 #endif
1017 }
1018
1019 void BLI_char_switch(char *string, char from, char to) 
1020 {
1021         if(string==0) return;
1022         while (*string != 0) {
1023                 if (*string == from) *string = to;
1024                 string++;
1025         }
1026 }
1027
1028 void BLI_make_exist(char *dir) {
1029         int a;
1030
1031         #ifdef WIN32
1032                 BLI_char_switch(dir, '/', '\\');
1033         #else
1034                 BLI_char_switch(dir, '\\', '/');
1035         #endif  
1036         
1037         a = strlen(dir);
1038         
1039 #ifdef WIN32    
1040         while(BLI_exists(dir) == 0){
1041                 a --;
1042                 while(dir[a] != '\\'){
1043                         a--;
1044                         if (a <= 0) break;
1045                 }
1046                 if (a >= 0) dir[a+1] = 0;
1047                 else {
1048                         /* defaulting to drive (usually 'C:') of Windows installation */
1049                         get_default_root(dir);
1050                         break;
1051                 }
1052         }
1053 #else
1054         while(BLI_exist(dir) == 0){
1055                 a --;
1056                 while(dir[a] != '/'){
1057                         a--;
1058                         if (a <= 0) break;
1059                 }
1060                 if (a >= 0) dir[a+1] = 0;
1061                 else {
1062                         strcpy(dir,"/");
1063                         break;
1064                 }
1065         }
1066 #endif
1067 }
1068
1069 void BLI_make_existing_file(char *name)
1070 {
1071         char di[FILE_MAXDIR], fi[FILE_MAXFILE];
1072         
1073         strcpy(di, name);
1074         BLI_splitdirstring(di, fi);
1075         
1076         /* test exist */
1077         if (BLI_exists(di) == 0) {
1078                 BLI_recurdir_fileops(di);
1079         }
1080 }
1081
1082
1083 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1084 {
1085         int sl;
1086
1087         if (!string || !dir || !file) return; /* We don't want any NULLs */
1088         
1089         string[0]= 0; /* ton */
1090
1091         /* we first push all slashes into unix mode, just to make sure we don't get
1092            any mess with slashes later on. -jesterKing */
1093         /* constant strings can be passed for those parameters - don't change them - elubie */
1094         /*
1095         BLI_char_switch(relabase, '\\', '/');
1096         BLI_char_switch(dir, '\\', '/');
1097         BLI_char_switch(file, '\\', '/');
1098         */
1099
1100         /* Resolve relative references */       
1101         if (relabase && dir[0] == '/' && dir[1] == '/') {
1102                 char *lslash;
1103                 
1104                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1105                 strcpy(string, relabase);
1106                 
1107                 lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\');
1108                 
1109                 if(lslash) *(lslash+1)= 0;
1110
1111                 dir+=2; /* Skip over the relative reference */
1112         }
1113 #ifdef WIN32
1114         else {
1115                 if (strlen(dir) >= 2 && dir[1] == ':' ) {
1116                         BLI_strncpy(string, dir, 3);
1117                         dir += 2;
1118                 }
1119                 else { /* no drive specified */
1120                         /* first option: get the drive from the relabase if it has one */
1121                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1122                                 BLI_strncpy(string, relabase, 3);       
1123                                 string[2] = '\\';
1124                                 string[3] = '\0';
1125                         }
1126                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1127                                 get_default_root(string);
1128                         }
1129                         
1130                         /* ignore leading slashes */
1131                         while (*dir == '/' || *dir == '\\') dir++;
1132                 }
1133         }
1134 #endif
1135
1136         strcat(string, dir);
1137
1138         /* Make sure string ends in one (and only one) slash */ 
1139         /* first trim all slashes from the end of the string */
1140         sl = strlen(string);
1141         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1142                 string[sl-1] = '\0';
1143                 sl--;
1144         }
1145         /* since we've now removed all slashes, put back one slash at the end. */
1146         strcat(string, "/");
1147         
1148         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1149                 file++;
1150                 
1151         strcat (string, file);
1152         
1153         /* Push all slashes to the system preferred direction */
1154         BLI_clean(string);
1155 }
1156
1157 int BLI_testextensie(const char *str, const char *ext)
1158 {
1159         short a, b;
1160         int retval;
1161
1162         a= strlen(str);
1163         b= strlen(ext);
1164
1165         if(a==0 || b==0 || b>=a) {
1166                 retval = 0;
1167         } else if (BLI_strcasecmp(ext, str + a - b)) {
1168                 retval = 0;     
1169         } else {
1170                 retval = 1;
1171         }
1172
1173         return (retval);
1174 }
1175
1176 /*
1177  * This is a simple version of BLI_split_dirfile that has the following advantages...
1178  * 
1179  * Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1180  * - wont change 'string'
1181  * - wont create any directories
1182  * - dosnt use CWD, or deal with relative paths.
1183  * - Only fill's in *dir and *file when they are non NULL
1184  * */
1185 void BLI_split_dirfile_basic(const char *string, char *dir, char *file)
1186 {
1187         int lslash=0, i = 0;
1188         for (i=0; string[i]!='\0'; i++) {
1189                 if (string[i]=='\\' || string[i]=='/')
1190                         lslash = i+1;
1191         }
1192         if (dir) {
1193                 if (lslash) {
1194                         BLI_strncpy( dir, string, lslash+1); /* +1 to include the slash and the last char */
1195                 } else {
1196                         dir[0] = '\0';
1197                 }
1198         }
1199         
1200         if (file) {
1201                 strcpy( file, string+lslash);
1202         }
1203 }
1204
1205
1206 /* Warning,
1207  * - May modify 'string' variable
1208  * - May create the directory if it dosnt exist
1209  * if this is not needed use BLI_split_dirfile_basic(...)
1210  */
1211 void BLI_split_dirfile(char *string, char *dir, char *file)
1212 {
1213         int a;
1214 #ifdef WIN32
1215         int sl;
1216         short is_relative = 0;
1217         char path[FILE_MAX];
1218 #endif
1219
1220         dir[0]= 0;
1221         file[0]= 0;
1222
1223 #ifdef WIN32
1224         BLI_strncpy(path, string, FILE_MAX);
1225         BLI_char_switch(path, '/', '\\'); /* make sure we have a valid path format */
1226         sl = strlen(path);
1227         if (sl) {
1228                 int len;
1229                 if (path[0] == '/' || path[0] == '\\') { 
1230                         BLI_strncpy(dir, path, FILE_MAXDIR);
1231                         if (sl > 1 && path[0] == '\\' && path[1] == '\\') is_relative = 1;
1232                 } else if (sl > 2 && path[1] == ':' && path[2] == '\\') {
1233                         BLI_strncpy(dir, path, FILE_MAXDIR);
1234                 } else {
1235                         BLI_getwdN(dir);
1236                         strcat(dir,"\\");
1237                         strcat(dir,path);
1238                         BLI_strncpy(path,dir,FILE_MAXDIR+FILE_MAXFILE);
1239                 }
1240                 
1241                 // BLI_exist doesn't recognize a slashed dirname as a dir
1242                 //  check if a trailing slash exists, and remove it. Do not do this
1243                 //  when we are already at root. -jesterKing
1244                 a = strlen(dir);
1245                 if(a>=4 && dir[a-1]=='\\') dir[a-1] = 0;
1246
1247                 if (is_relative) {
1248                         printf("WARNING: BLI_split_dirfile needs absolute dir\n");
1249                 }
1250                 else {
1251                         BLI_make_exist(dir);
1252                 }
1253
1254                 if (S_ISDIR(BLI_exist(dir))) {
1255
1256                         /* copy from end of string into file, to ensure filename itself isn't truncated 
1257                         if string is too long. (aphex) */
1258
1259                         len = FILE_MAXFILE - strlen(path);
1260
1261                         if (len < 0)
1262                                 BLI_strncpy(file,path + abs(len),FILE_MAXFILE);
1263                         else
1264                                 BLI_strncpy(file,path,FILE_MAXFILE);
1265                     
1266                         if (strrchr(path,'\\')) {
1267                                 BLI_strncpy(file,strrchr(path,'\\')+1,FILE_MAXFILE);
1268                         }
1269                         
1270                         if ( (a = strlen(dir)) ) {
1271                                 if (dir[a-1] != '\\') strcat(dir,"\\");
1272                         }
1273                 }
1274                 else {
1275                         a = strlen(dir) - 1;
1276                         while(a>0 && dir[a] != '\\') a--;
1277                         dir[a + 1] = 0;
1278                         BLI_strncpy(file, path + strlen(dir),FILE_MAXFILE);
1279                 }
1280
1281         }
1282         else {
1283                 /* defaulting to first valid drive hoping it's not empty CD and DVD drives */
1284                 get_default_root(dir);
1285                 file[0]=0;
1286         }
1287 #else
1288         if (strlen(string)) {
1289                 if (string[0] == '/') { 
1290                         strcpy(dir, string);
1291                 } else if (string[1] == ':' && string[2] == '\\') {
1292                         string+=2;
1293                         strcpy(dir, string);
1294                 } else {
1295                         BLI_getwdN(dir);
1296                         strcat(dir,"/");
1297                         strcat(dir,string);
1298                         strcpy((char *)string,dir);
1299                 }
1300
1301                 BLI_make_exist(dir);
1302                         
1303                 if (S_ISDIR(BLI_exist(dir))) {
1304                         strcpy(file,string + strlen(dir));
1305
1306                         if (strrchr(file,'/')) strcpy(file,strrchr(file,'/')+1);
1307                 
1308                         if ( (a = strlen(dir)) ) {
1309                                 if (dir[a-1] != '/') strcat(dir,"/");
1310                         }
1311                 }
1312                 else {
1313                         a = strlen(dir) - 1;
1314                         while(dir[a] != '/') a--;
1315                         dir[a + 1] = 0;
1316                         strcpy(file, string + strlen(dir));
1317                 }
1318         }
1319         else {
1320                 BLI_getwdN(dir);
1321                 strcat(dir, "/");
1322                 file[0] = 0;
1323         }
1324 #endif
1325 }
1326
1327 /* simple appending of filename to dir, does not check for valid path! */
1328 void BLI_join_dirfile(char *string, const char *dir, const char *file)
1329 {
1330         int sl_dir;
1331         
1332         if(string != dir) /* compare pointers */
1333                 BLI_strncpy(string, dir, FILE_MAX);
1334         
1335         sl_dir= BLI_add_slash(string);
1336         
1337         if (sl_dir <FILE_MAX) {
1338                 BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
1339         }
1340 }
1341
1342 static int add_win32_extension(char *name)
1343 {
1344         int retval = 0;
1345         int type;
1346
1347         type = BLI_exist(name);
1348         if ((type == 0) || S_ISDIR(type)) {
1349 #ifdef _WIN32
1350                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1351                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1352                 char *extensions = getenv("PATHEXT");
1353                 if (extensions) {
1354                         char *temp;
1355                         do {
1356                                 strcpy(filename, name);
1357                                 temp = strstr(extensions, ";");
1358                                 if (temp) {
1359                                         strncpy(ext, extensions, temp - extensions);
1360                                         ext[temp - extensions] = 0;
1361                                         extensions = temp + 1;
1362                                         strcat(filename, ext);
1363                                 } else {
1364                                         strcat(filename, extensions);
1365                                 }
1366
1367                                 type = BLI_exist(filename);
1368                                 if (type && (! S_ISDIR(type))) {
1369                                         retval = 1;
1370                                         strcpy(name, filename);
1371                                         break;
1372                                 }
1373                         } while (temp);
1374                 }
1375 #endif
1376         } else {
1377                 retval = 1;
1378         }
1379
1380         return (retval);
1381 }
1382
1383 void BLI_where_am_i(char *fullname, const char *name)
1384 {
1385         char filename[FILE_MAXDIR+FILE_MAXFILE];
1386         char *path = NULL, *temp;
1387         
1388 #ifdef _WIN32
1389         char *separator = ";";
1390         char slash = '\\';
1391 #else
1392         char *separator = ":";
1393         char slash = '/';
1394 #endif
1395
1396         
1397 #ifdef __linux__
1398         /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1399         path = br_find_exe( NULL );
1400         if (path) {
1401                 strcpy(fullname, path);
1402                 free(path);
1403                 return;
1404         }
1405 #endif
1406
1407 #ifdef _WIN32
1408         if(GetModuleFileName(0, fullname, FILE_MAXDIR+FILE_MAXFILE)) {
1409                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1410                 return;
1411         }
1412 #endif
1413
1414         /* unix and non linux */
1415         if (name && fullname && strlen(name)) {
1416                 strcpy(fullname, name);
1417                 if (name[0] == '.') {
1418                         // relative path, prepend cwd
1419                         BLI_getwdN(fullname);
1420                         
1421                         // not needed but avoids annoying /./ in name
1422                         if(name && name[0]=='.' && name[1]==slash)
1423                                 BLI_join_dirfile(fullname, fullname, name+2);
1424                         else
1425                                 BLI_join_dirfile(fullname, fullname, name);
1426                         
1427                         add_win32_extension(fullname);
1428                 } else if (BLI_last_slash(name)) {
1429                         // full path
1430                         strcpy(fullname, name);
1431                         add_win32_extension(fullname);
1432                 } else {
1433                         // search for binary in $PATH
1434                         path = getenv("PATH");
1435                         if (path) {
1436                                 do {
1437                                         temp = strstr(path, separator);
1438                                         if (temp) {
1439                                                 strncpy(filename, path, temp - path);
1440                                                 filename[temp - path] = 0;
1441                                                 path = temp + 1;
1442                                         } else {
1443                                                 strncpy(filename, path, sizeof(filename));
1444                                         }
1445                                         BLI_join_dirfile(fullname, fullname, name);
1446                                         if (add_win32_extension(filename)) {
1447                                                 strcpy(fullname, filename);
1448                                                 break;
1449                                         }
1450                                 } while (temp);
1451                         }
1452                 }
1453 #ifndef NDEBUG
1454                 if (strcmp(name, fullname)) {
1455                         printf("guessing '%s' == '%s'\n", name, fullname);
1456                 }
1457 #endif
1458
1459 #ifdef _WIN32
1460                 // in windows change long filename to short filename because
1461                 // win2k doesn't know how to parse a commandline with lots of
1462                 // spaces and double-quotes. There's another solution to this
1463                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1464                 // that's even uglier
1465                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1466 #ifndef NDEBUG
1467                 printf("Shortname = '%s'\n", fullname);
1468 #endif
1469 #endif
1470         }
1471 }
1472
1473 void BLI_where_is_temp(char *fullname, int usertemp)
1474 {
1475         fullname[0] = '\0';
1476         
1477         if (usertemp && BLI_exists(U.tempdir)) {
1478                 strcpy(fullname, U.tempdir);
1479         }
1480         
1481         
1482 #ifdef WIN32
1483         if (fullname[0] == '\0') {
1484                 char *tmp = getenv("TEMP"); /* Windows */
1485                 if (tmp && BLI_exists(tmp)) {
1486                         strcpy(fullname, tmp);
1487                 }
1488         }
1489 #else
1490         /* Other OS's - Try TMP and TMPDIR */
1491         if (fullname[0] == '\0') {
1492                 char *tmp = getenv("TMP");
1493                 if (tmp && BLI_exists(tmp)) {
1494                         strcpy(fullname, tmp);
1495                 }
1496         }
1497         
1498         if (fullname[0] == '\0') {
1499                 char *tmp = getenv("TMPDIR");
1500                 if (tmp && BLI_exists(tmp)) {
1501                         strcpy(fullname, tmp);
1502                 }
1503         }
1504 #endif  
1505         
1506         if (fullname[0] == '\0') {
1507                 strcpy(fullname, "/tmp/");
1508         } else {
1509                 /* add a trailing slash if needed */
1510                 BLI_add_slash(fullname);
1511         }
1512 }
1513
1514 char *get_install_dir(void) {
1515         extern char bprogname[];
1516         char *tmpname = BLI_strdup(bprogname);
1517         char *cut;
1518
1519 #ifdef __APPLE__
1520         cut = strstr(tmpname, ".app");
1521         if (cut) cut[0] = 0;
1522 #endif
1523
1524         cut = BLI_last_slash(tmpname);
1525
1526         if (cut) {
1527                 cut[0] = 0;
1528                 return tmpname;
1529         } else {
1530                 MEM_freeN(tmpname);
1531                 return NULL;
1532         }
1533 }
1534
1535 /* 
1536  * returns absolute path to the app bundle
1537  * only useful on OS X 
1538  */
1539 #ifdef __APPLE__
1540 char* BLI_getbundle(void) {
1541         CFURLRef bundleURL;
1542         CFStringRef pathStr;
1543         static char path[MAXPATHLEN];
1544         CFBundleRef mainBundle = CFBundleGetMainBundle();
1545
1546         bundleURL = CFBundleCopyBundleURL(mainBundle);
1547         pathStr = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
1548         CFStringGetCString(pathStr, path, MAXPATHLEN, kCFStringEncodingASCII);
1549         CFRelease(pathStr);
1550         CFRelease(bundleURL);
1551         return path;
1552 }
1553 #endif
1554
1555 #ifdef WITH_ICONV
1556 #include "iconv.h"
1557 #include "localcharset.h"
1558
1559 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1560 {
1561         size_t inbytesleft=strlen(original);
1562         size_t outbytesleft=512;
1563         size_t rv=0;
1564         iconv_t cd;
1565         
1566         if (NULL == code) {
1567                 code = locale_charset();
1568         }
1569         cd=iconv_open("UTF-8", code);
1570
1571         if (cd == (iconv_t)(-1)) {
1572                 printf("iconv_open Error");
1573                 *utf_8='\0';
1574                 return ;
1575         }
1576         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1577         if (rv == (size_t) -1) {
1578                 printf("iconv Error\n");
1579                 return ;
1580         }
1581         *utf_8 = '\0';
1582         iconv_close(cd);
1583 }
1584 #endif // WITH_ICONV
1585
1586