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