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