BLI_split_dirfile was being used in cases it should not have been,
[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 /* Ripped this from blender.c */
106 void addlisttolist(ListBase *list1, ListBase *list2)
107 {
108         if (list2->first==0) return;
109
110         if (list1->first==0) {
111                 list1->first= list2->first;
112                 list1->last= list2->last;
113         }
114         else {
115                 ((Link *)list1->last)->next= list2->first;
116                 ((Link *)list2->first)->prev= list1->last;
117                 list1->last= list2->last;
118         }
119         list2->first= list2->last= 0;
120 }
121
122 int BLI_stringdec(char *string, char *kop, char *start, unsigned short *numlen)
123 {
124         unsigned short len, len2, nums = 0, nume = 0;
125         short i, found = 0;
126
127         len2 = len = strlen(string);
128         
129         if (len > 6) {
130                 if (BLI_strncasecmp(string + len - 6, ".blend", 6) == 0) len -= 6;
131                 else if (BLI_strncasecmp(string + len - 6, ".trace", 6) == 0) len -= 6;
132         }
133         
134         if (len > 9) {
135                 if (BLI_strncasecmp(string + len - 9, ".blend.gz", 9) == 0) len -= 9;
136         }
137                 
138         if (len == len2) {
139                 if (len > 4) {
140                         /* handle .jf0 en .jf1 for jstreams */
141                         if (BLI_strncasecmp(string + len - 4, ".jf", 3) == 0) len -= 4;
142                         else if (BLI_strncasecmp(string + len - 4, ".tga", 4) == 0) len -= 4;
143                         else if (BLI_strncasecmp(string + len - 4, ".jpg", 4) == 0) len -= 4;
144                         else if (BLI_strncasecmp(string + len - 4, ".png", 4) == 0) len -= 4;
145                         else if (BLI_strncasecmp(string + len - 4, ".txt", 4) == 0) len -= 4;
146                         else if (BLI_strncasecmp(string + len - 4, ".cyc", 4) == 0) len -= 4;
147                         else if (BLI_strncasecmp(string + len - 4, ".enh", 4) == 0) len -= 4;
148                         else if (BLI_strncasecmp(string + len - 4, ".rgb", 4) == 0) len -= 4;
149                         else if (BLI_strncasecmp(string + len - 4, ".psx", 4) == 0) len -= 4;
150                         else if (BLI_strncasecmp(string + len - 4, ".ble", 4) == 0) len -= 4;
151                         else if (BLI_strncasecmp(string + len - 4, ".exr", 4) == 0) len -= 4;
152                 }
153         }
154         
155         for (i = len - 1; i >= 0; i--) {
156                 if (string[i] == '/') break;
157                 if (isdigit(string[i])) {
158                         if (found){
159                                 nums = i;
160                         }
161                         else{
162                                 nume = i;
163                                 nums = i;
164                                 found = 1;
165                         }
166                 }
167                 else {
168                         if (found) break;
169                 }
170         }
171         if (found){
172                 if (start) strcpy(start,&string[nume+1]);
173                 if (kop) {
174                         strcpy(kop,string);
175                         kop[nums]=0;
176                 }
177                 if (numlen) *numlen = nume-nums+1;
178                 return ((int)atoi(&(string[nums])));
179         }
180         if (start) strcpy(start, string + len);
181         if (kop) {
182                 strncpy(kop, string, len);
183                 kop[len] = 0;
184         }
185         if (numlen) *numlen=0;
186         return 0;
187 }
188
189
190 void BLI_stringenc(char *string, char *kop, char *start, unsigned short numlen, int pic)
191 {
192         char numstr[10]="";
193         unsigned short len,i;
194
195         strcpy(string,kop);
196         
197         if (pic>0 || numlen==4) {
198                 len= sprintf(numstr,"%d",pic);
199                 
200                 for(i=len;i<numlen;i++){
201                         strcat(string,"0");
202                 }
203                 strcat(string,numstr);
204         }
205         strcat(string, start);
206 }
207
208
209 void BLI_newname(char *name, int add)
210 {
211         char head[128], tail[128];
212         int pic;
213         unsigned short digits;
214         
215         pic = BLI_stringdec(name, head, tail, &digits);
216         
217         /* are we going from 100 -> 99 or from 10 -> 9 */
218         if (add < 0 && digits < 4 && digits > 0) {
219                 int i, exp;
220                 exp = 1;
221                 for (i = digits; i > 1; i--) exp *= 10;
222                 if (pic >= exp && (pic + add) < exp) digits--;
223         }
224         
225         pic += add;
226         
227         if (digits==4 && pic<0) pic= 0;
228         BLI_stringenc(name, head, tail, digits, pic);
229 }
230
231 /* little helper macro for BLI_uniquename */
232 #ifndef GIVE_STRADDR
233         #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset )
234 #endif
235
236 /* Generic function to set a unique name. It is only designed to be used in situations
237  * where the name is part of the struct, and also that the name is at most 128 chars long.
238  * 
239  * For places where this is used, see constraint.c for example...
240  *
241  *      name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
242  *      len: maximum length of string (to prevent overflows, etc.)
243  *      defname: the name that should be used by default if none is specified already
244  */
245 void BLI_uniquename(ListBase *list, void *vlink, char defname[], short name_offs, short len)
246 {
247         Link *link;
248         char tempname[128];
249         int     number = 1, exists = 0;
250         char *dot;
251         
252         /* Make sure length can be handled */
253         if ((len < 0) || (len > 128))
254                 return;
255         
256         /* See if we are given an empty string */
257         if (ELEM(NULL, vlink, defname))
258                 return;
259         
260         if (GIVE_STRADDR(vlink, name_offs) == '\0') {
261                 /* give it default name first */
262                 BLI_strncpy(GIVE_STRADDR(vlink, name_offs), defname, len);
263         }
264         
265         /* See if we even need to do this */
266         if (list == NULL)
267                 return;
268         
269         for (link = list->first; link; link= link->next) {
270                 if (link != vlink) {
271                         if (!strcmp(GIVE_STRADDR(link, name_offs), GIVE_STRADDR(vlink, name_offs))) {
272                                 exists = 1;
273                                 break;
274                         }
275                 }
276         }
277         if (exists == 0)
278                 return;
279
280         /* Strip off the suffix */
281         dot = strchr(GIVE_STRADDR(vlink, name_offs), '.');
282         if (dot)
283                 *dot=0;
284         
285         for (number = 1; number <= 999; number++) {
286                 BLI_snprintf(tempname, 128, "%s.%03d", GIVE_STRADDR(vlink, name_offs), number);
287                 
288                 exists = 0;
289                 for (link= list->first; link; link= link->next) {
290                         if (vlink != link) {
291                                 if (!strcmp(GIVE_STRADDR(link, name_offs), tempname)) {
292                                         exists = 1;
293                                         break;
294                                 }
295                         }
296                 }
297                 if (exists == 0) {
298                         BLI_strncpy(GIVE_STRADDR(vlink, name_offs), tempname, len);
299                         return;
300                 }
301         }
302 }
303
304
305 void BLI_addhead(ListBase *listbase, void *vlink)
306 {
307         Link *link= vlink;
308
309         if (link == NULL) return;
310         if (listbase == NULL) return;
311
312         link->next = listbase->first;
313         link->prev = NULL;
314
315         if (listbase->first) ((Link *)listbase->first)->prev = link;
316         if (listbase->last == NULL) listbase->last = link;
317         listbase->first = link;
318 }
319
320
321 void BLI_addtail(ListBase *listbase, void *vlink)
322 {
323         Link *link= vlink;
324
325         if (link == NULL) return;
326         if (listbase == NULL) return;
327
328         link->next = NULL;
329         link->prev = listbase->last;
330
331         if (listbase->last) ((Link *)listbase->last)->next = link;
332         if (listbase->first == 0) listbase->first = link;
333         listbase->last = link;
334 }
335
336
337 void BLI_remlink(ListBase *listbase, void *vlink)
338 {
339         Link *link= vlink;
340
341         if (link == NULL) return;
342         if (listbase == NULL) return;
343
344         if (link->next) link->next->prev = link->prev;
345         if (link->prev) link->prev->next = link->next;
346
347         if (listbase->last == link) listbase->last = link->prev;
348         if (listbase->first == link) listbase->first = link->next;
349 }
350
351
352 void BLI_freelinkN(ListBase *listbase, void *vlink)
353 {
354         Link *link= vlink;
355
356         if (link == NULL) return;
357         if (listbase == NULL) return;
358
359         BLI_remlink(listbase,link);
360         MEM_freeN(link);
361 }
362
363
364 void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink)
365 {
366         Link *prevlink= vprevlink;
367         Link *newlink= vnewlink;
368
369         /* newlink comes after prevlink */
370         if (newlink == NULL) return;
371         if (listbase == NULL) return;
372         
373         /* empty list */
374         if (listbase->first == NULL) { 
375                 
376                 listbase->first= newlink;
377                 listbase->last= newlink;
378                 return;
379         }
380         
381         /* insert before first element */
382         if (prevlink == NULL) { 
383                 newlink->next= listbase->first;
384                 newlink->prev= 0;
385                 newlink->next->prev= newlink;
386                 listbase->first= newlink;
387                 return;
388         }
389
390         /* at end of list */
391         if (listbase->last== prevlink) 
392                 listbase->last = newlink;
393
394         newlink->next= prevlink->next;
395         prevlink->next= newlink;
396         if (newlink->next) newlink->next->prev= newlink;
397         newlink->prev= prevlink;
398 }
399
400 /* This uses insertion sort, so NOT ok for large list */
401 void BLI_sortlist(ListBase *listbase, int (*cmp)(void *, void *))
402 {
403         Link *current = NULL;
404         Link *previous = NULL;
405         Link *next = NULL;
406         
407         if (cmp == NULL) return;
408         if (listbase == NULL) return;
409
410         if (listbase->first != listbase->last)
411         {
412                 for( previous = listbase->first, current = previous->next; current; current = next )
413                 {
414                         next = current->next;
415                         previous = current->prev;
416                         
417                         BLI_remlink(listbase, current);
418                         
419                         while(previous && cmp(previous, current) == 1)
420                         {
421                                 previous = previous->prev;
422                         }
423                         
424                         BLI_insertlinkafter(listbase, previous, current);
425                 }
426         }
427 }
428
429 void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink)
430 {
431         Link *prevlink= vprevlink;
432         Link *newlink= vnewlink;
433
434         /* newlink before nextlink */
435         if (newlink == NULL) return;
436         if (listbase == NULL) return;
437
438         /* empty list */
439         if (listbase->first == NULL) { 
440                 listbase->first= newlink;
441                 listbase->last= newlink;
442                 return;
443         }
444         
445         /* insert at head of list */
446         if (prevlink == NULL) { 
447                 newlink->prev = NULL;
448                 newlink->next = listbase->first;
449                 ((Link *)listbase->first)->prev = newlink;
450                 listbase->first = newlink;
451                 return;
452         }
453
454         /* at end of list */
455         if (listbase->last == prevlink) 
456                 listbase->last = newlink;
457
458         newlink->next = prevlink->next;
459         newlink->prev = prevlink;
460         prevlink->next = newlink;
461         if (newlink->next) newlink->next->prev = newlink;
462 }
463
464 void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
465 {
466         Link *nextlink= vnextlink;
467         Link *newlink= vnewlink;
468
469         /* newlink before nextlink */
470         if (newlink == NULL) return;
471         if (listbase == NULL) return;
472
473         /* empty list */
474         if (listbase->first == NULL) { 
475                 listbase->first= newlink;
476                 listbase->last= newlink;
477                 return;
478         }
479         
480         /* insert at end of list */
481         if (nextlink == NULL) { 
482                 newlink->prev= listbase->last;
483                 newlink->next= 0;
484                 ((Link *)listbase->last)->next= newlink;
485                 listbase->last= newlink;
486                 return;
487         }
488
489         /* at beginning of list */
490         if (listbase->first== nextlink) 
491                 listbase->first = newlink;
492
493         newlink->next= nextlink;
494         newlink->prev= nextlink->prev;
495         nextlink->prev= newlink;
496         if (newlink->prev) newlink->prev->next= newlink;
497 }
498
499
500 void BLI_freelist(ListBase *listbase)
501 {
502         Link *link, *next;
503
504         if (listbase == NULL) 
505                 return;
506         
507         link= listbase->first;
508         while (link) {
509                 next= link->next;
510                 free(link);
511                 link= next;
512         }
513         
514         listbase->first= NULL;
515         listbase->last= NULL;
516 }
517
518 void BLI_freelistN(ListBase *listbase)
519 {
520         Link *link, *next;
521
522         if (listbase == NULL) return;
523         
524         link= listbase->first;
525         while (link) {
526                 next= link->next;
527                 MEM_freeN(link);
528                 link= next;
529         }
530         
531         listbase->first= NULL;
532         listbase->last= NULL;
533 }
534
535
536 int BLI_countlist(ListBase *listbase)
537 {
538         Link *link;
539         int count = 0;
540         
541         if (listbase) {
542                 link = listbase->first;
543                 while (link) {
544                         count++;
545                         link= link->next;
546                 }
547         }
548         return count;
549 }
550
551 void *BLI_findlink(ListBase *listbase, int number)
552 {
553         Link *link = NULL;
554
555         if (number >= 0) {
556                 link = listbase->first;
557                 while (link != NULL && number != 0) {
558                         number--;
559                         link = link->next;
560                 }
561         }
562
563         return link;
564 }
565
566 int BLI_findindex(ListBase *listbase, void *vlink)
567 {
568         Link *link= NULL;
569         int number= 0;
570         
571         if (listbase == NULL) return -1;
572         if (vlink == NULL) return -1;
573         
574         link= listbase->first;
575         while (link) {
576                 if (link == vlink)
577                         return number;
578                 
579                 number++;
580                 link= link->next;
581         }
582         
583         return -1;
584 }
585
586 /*=====================================================================================*/
587 /* Methods for access array (realloc) */
588 /*=====================================================================================*/
589
590 /* remove item with index */
591 static void rem_array_item(struct DynamicArray *da, unsigned int index)
592 {
593         da->items[index]=NULL;
594         da->count--;
595         if(index==da->last_item_index){
596                 while((!da->items[da->last_item_index]) && (da->last_item_index>0)){
597                         da->last_item_index--;
598                 }
599         }
600 }
601
602 /* add array (if needed, then realloc) */
603 static void add_array_item(struct DynamicArray *da, void *item, unsigned int index)
604 {
605         /* realloc of access array */
606         if(da->max_item_index < index){
607                 unsigned int i, max = da->max_item_index;
608                 void **nitems;
609
610                 do {
611                         da->max_item_index += PAGE_SIZE;        /* OS can allocate only PAGE_SIZE Bytes */
612                 } while(da->max_item_index<=index);
613
614                 nitems = (void**)MEM_mallocN(sizeof(void*)*(da->max_item_index+1), "dlist access array");
615                 for(i=0;i<=max;i++)
616                         nitems[i] = da->items[i];
617
618                 /* set rest pointers to the NULL */
619                 for(i=max+1; i<=da->max_item_index; i++)
620                         nitems[i]=NULL;
621
622                 MEM_freeN(da->items);           /* free old access array */
623                 da->items = nitems;
624         }
625
626         da->items[index] = item;
627         da->count++;
628         if(index > da->last_item_index) da->last_item_index = index;
629 }
630
631 /* free access array */
632 static void destroy_array(DynamicArray *da)
633 {
634         da->count=0;
635         da->last_item_index=0;
636         da->max_item_index=0;
637         MEM_freeN(da->items);
638         da->items = NULL;
639 }
640
641 /* initialize dynamic array */
642 static void init_array(DynamicArray *da)
643 {
644         unsigned int i;
645
646         da->count=0;
647         da->last_item_index=0;
648         da->max_item_index = PAGE_SIZE-1;
649         da->items = (void*)MEM_mallocN(sizeof(void*)*(da->max_item_index+1), "dlist access array");
650         for(i=0; i<=da->max_item_index; i++) da->items[i]=NULL;
651 }
652
653 /* reinitialize dynamic array */
654 static void reinit_array(DynamicArray *da)
655 {
656         destroy_array(da);
657         init_array(da);
658 }
659
660 /*=====================================================================================*/
661 /* Methods for two way dynamic list with access array */
662 /*=====================================================================================*/
663
664 /* create new two way dynamic list with access array from two way dynamic list
665  * it doesn't copy any items to new array or something like this It is strongly
666  * recomended to use BLI_dlist_ methods for adding/removing items from dynamic list
667  * unless you can end with inconsistence system !!! */
668 DynamicList *BLI_dlist_from_listbase(ListBase *lb)
669 {
670         DynamicList *dlist;
671         Link *item;
672         int i=0, count;
673         
674         if(!lb) return NULL;
675         
676         count = BLI_countlist(lb);
677
678         dlist = MEM_mallocN(sizeof(DynamicList), "temp dynamic list");
679         /* ListBase stuff */
680         dlist->lb.first = lb->first;
681         dlist->lb.last = lb->last;
682         /* access array stuff */
683         dlist->da.count=count;
684         dlist->da.max_item_index = count-1;
685         dlist->da.last_item_index = count -1;
686         dlist->da.items = (void*)MEM_mallocN(sizeof(void*)*count, "temp dlist access array");
687
688         item = (Link*)lb->first;
689         while(item){
690                 dlist->da.items[i] = (void*)item;
691                 item = item->next;
692                 i++;
693         }
694
695         /* to prevent you of using original ListBase :-) */
696         lb->first = lb->last = NULL;
697
698         return dlist;
699 }
700
701 /* take out ListBase from DynamicList and destroy all temporary structures of DynamicList */
702 ListBase *BLI_listbase_from_dlist(DynamicList *dlist, ListBase *lb)
703 {
704         if(!dlist) return NULL;
705
706         if(!lb) lb = (ListBase*)MEM_mallocN(sizeof(ListBase), "ListBase");
707         
708         lb->first = dlist->lb.first;
709         lb->last = dlist->lb.last;
710
711         /* free all items of access array */
712         MEM_freeN(dlist->da.items);
713         /* free DynamicList*/
714         MEM_freeN(dlist);
715
716         return lb;
717 }
718
719 /* return pointer at item from th dynamic list with access array */
720 void *BLI_dlist_find_link(DynamicList *dlist, unsigned int index)
721 {
722         if(!dlist || !dlist->da.items) return NULL;
723
724         if((index <= dlist->da.last_item_index) && (index >= 0) && (dlist->da.count>0)){
725                 return dlist->da.items[index];
726         }
727         else {
728                 return NULL;
729         }
730 }
731
732 /* return count of items in the dynamic list with access array */
733 unsigned int BLI_count_items(DynamicList *dlist)
734 {
735         if(!dlist) return 0;
736
737         return dlist->da.count;
738 }
739
740 /* free item from the dynamic list with access array */
741 void BLI_dlist_free_item(DynamicList *dlist, unsigned int index)
742 {
743         if(!dlist || !dlist->da.items) return;
744         
745         if((index <= dlist->da.last_item_index) && (dlist->da.items[index])){
746                 BLI_freelinkN(&(dlist->lb), dlist->da.items[index]);
747                 rem_array_item(&(dlist->da), index);
748         }
749 }
750
751 /* remove item from the dynamic list with access array */
752 void BLI_dlist_rem_item(DynamicList *dlist, unsigned int index)
753 {
754         if(!dlist || !dlist->da.items) return;
755         
756         if((index <= dlist->da.last_item_index) && (dlist->da.items[index])){
757                 BLI_remlink(&(dlist->lb), dlist->da.items[index]);
758                 rem_array_item(&(dlist->da), index);
759         }
760 }
761
762 /* add item to the dynamic list with access array (index) */
763 void* BLI_dlist_add_item_index(DynamicList *dlist, void *item, unsigned int index)
764 {
765         if(!dlist || !dlist->da.items) return NULL;
766
767         if((index <= dlist->da.max_item_index) && (dlist->da.items[index])) {
768                 /* you can't place item at used index */
769                 return NULL;
770         }
771         else {
772                 add_array_item(&(dlist->da), item, index);
773                 BLI_addtail(&(dlist->lb), item);
774                 return item;
775         }
776 }
777
778 /* destroy dynamic list with access array */
779 void BLI_dlist_destroy(DynamicList *dlist)
780 {
781         if(!dlist) return;
782
783         BLI_freelistN(&(dlist->lb));
784         destroy_array(&(dlist->da));
785 }
786
787 /* initialize dynamic list with access array */
788 void BLI_dlist_init(DynamicList *dlist)
789 {
790         if(!dlist) return;
791
792         dlist->lb.first = NULL;
793         dlist->lb.last = NULL;
794
795         init_array(&(dlist->da));
796 }
797
798 /* reinitialize dynamic list with acces array */
799 void BLI_dlist_reinit(DynamicList *dlist)
800 {
801         if(!dlist) return;
802         
803         BLI_freelistN(&(dlist->lb));
804         reinit_array(&(dlist->da));
805 }
806
807 /*=====================================================================================*/
808
809 char *BLI_strdupn(const char *str, int len) {
810         char *n= MEM_mallocN(len+1, "strdup");
811         memcpy(n, str, len);
812         n[len]= '\0';
813         
814         return n;
815 }
816 char *BLI_strdup(const char *str) {
817         return BLI_strdupn(str, strlen(str));
818 }
819
820 char *BLI_strncpy(char *dst, const char *src, int maxncpy) {
821         int srclen= strlen(src);
822         int cpylen= (srclen>(maxncpy-1))?(maxncpy-1):srclen;
823         
824         memcpy(dst, src, cpylen);
825         dst[cpylen]= '\0';
826         
827         return dst;
828 }
829
830 int BLI_snprintf(char *buffer, size_t count, const char *format, ...)
831 {
832         int n;
833         va_list arg;
834
835         va_start(arg, format);
836         n = vsnprintf(buffer, count, format, arg);
837         
838         if (n != -1 && n < count) {
839                 buffer[n] = '\0';
840         } else {
841                 buffer[count-1] = '\0';
842         }
843         
844         va_end(arg);
845         return n;
846 }
847
848 int BLI_streq(char *a, char *b) {
849         return (strcmp(a, b)==0);
850 }
851 int BLI_strcaseeq(char *a, char *b) {
852         return (BLI_strcasecmp(a, b)==0);
853 }
854
855 /* ******************** string encoding ***************** */
856
857 /* This is quite an ugly function... its purpose is to
858  * take the dir name, make it absolute, and clean it up, replacing
859  * excess file entry stuff (like /tmp/../tmp/../)
860  * note that dir isn't protected for max string names... 
861  */
862
863 void BLI_cleanup_dir(const char *relabase, char *dir)
864 {
865         BLI_cleanup_file(relabase, dir);
866 #ifdef WIN32
867         strcat(dir, "\\");
868 #else
869         strcat(dir, "/");
870 #endif
871 }
872
873 void BLI_cleanup_file(const char *relabase, char *dir)
874 {
875         short a;
876         char *start, *eind;
877         
878         BLI_convertstringcode(dir, relabase, 0);
879         
880 #ifdef WIN32
881         if(dir[0]=='.') {       /* happens for example in FILE_MAIN */
882            get_default_root(dir);
883            return;
884         }       
885
886         while ( (start = strstr(dir, "\\..\\")) ) {
887                 eind = start + strlen("\\..\\") - 1;
888                 a = start-dir-1;
889                 while (a>0) {
890                         if (dir[a] == '\\') break;
891                         a--;
892                 }
893                 strcpy(dir+a,eind);
894         }
895
896         while ( (start = strstr(dir,"\\.\\")) ){
897                 eind = start + strlen("\\.\\") - 1;
898                 strcpy(start,eind);
899         }
900
901         while ( (start = strstr(dir,"\\\\" )) ){
902                 eind = start + strlen("\\\\") - 1;
903                 strcpy(start,eind);
904         }
905
906         if((a = strlen(dir))){                          /* remove the '\\' at the end */
907                 while(a>0 && dir[a-1] == '\\'){
908                         a--;
909                         dir[a] = 0;
910                 }
911         }
912 #else
913         if(dir[0]=='.') {       /* happens, for example in FILE_MAIN */
914            dir[0]= '/';
915            dir[1]= 0;
916            return;
917         }       
918
919         while ( (start = strstr(dir, "/../")) ) {
920                 eind = start + strlen("/../") - 1;
921                 a = start-dir-1;
922                 while (a>0) {
923                         if (dir[a] == '/') break;
924                         a--;
925                 }
926                 strcpy(dir+a,eind);
927         }
928
929         while ( (start = strstr(dir,"/./")) ){
930                 eind = start + strlen("/./") - 1;
931                 strcpy(start,eind);
932         }
933
934         while ( (start = strstr(dir,"//" )) ){
935                 eind = start + strlen("//") - 1;
936                 strcpy(start,eind);
937         }
938
939         if( (a = strlen(dir)) ){                                /* remove all '/' at the end */
940                 while(dir[a-1] == '/'){
941                         a--;
942                         dir[a] = 0;
943                         if (a<=0) break;
944                 }
945         }
946 #endif
947 }
948
949
950 void BLI_makestringcode(const char *relfile, char *file)
951 {
952         char * p;
953         char * q;
954         char * lslash;
955         char temp[FILE_MAXDIR+FILE_MAXFILE];
956         char res[FILE_MAXDIR+FILE_MAXFILE];
957
958         /* if file is already relative, bail out */
959         if(file[0]=='/' && file[1]=='/') return;
960         
961         /* also bail out if relative path is not set */
962         if (relfile[0] == 0) return;
963
964 #ifdef WIN32 
965         if (strlen(relfile) > 2 && relfile[1] != ':') {
966                 char* ptemp;
967                 /* fix missing volume name in relative base,
968                    can happen with old .Blog files */
969                 get_default_root(temp);
970                 ptemp = &temp[2];
971                 if (relfile[0] != '\\' && relfile[0] != '/') {
972                         ptemp++;
973                 }
974                 BLI_strncpy(ptemp, relfile, FILE_MAXDIR + FILE_MAXFILE-3);
975         } else {
976                 BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE);
977         }
978
979         if (strlen(file) > 2) {
980                 if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] )
981                         return;
982         }
983 #else
984         BLI_strncpy(temp, relfile, FILE_MAX);
985 #endif
986
987         BLI_char_switch(temp, '\\', '/');
988         BLI_char_switch(file, '\\', '/');
989
990         /* the last slash in the file indicates where the path part ends */
991         lslash = BLI_last_slash(temp);
992
993         if (lslash) 
994         {       
995                 /* find the prefix of the filename that is equal for both filenames.
996                    This is replaced by the two slashes at the beginning */
997                 p = temp;
998                 q = file;
999                 while (*p == *q) {
1000                         ++p; ++q;
1001                 }
1002                 /* we might have passed the slash when the beginning of a dir matches 
1003                    so we rewind. Only check on the actual filename
1004                 */
1005                 if (*q != '/') {
1006                         while ( (q >= file) && (*q != '/') ) { --q; --p; }
1007                 } 
1008                 else if (*p != '/') {
1009                         while ( (p >= temp) && (*p != '/') ) { --p; --q; }
1010                 }
1011                 
1012                 strcpy(res,     "//");
1013
1014                 /* p now points to the slash that is at the beginning of the part
1015                    where the path is different from the relative path. 
1016                    We count the number of directories we need to go up in the
1017                    hierarchy to arrive at the common 'prefix' of the path
1018                 */                      
1019                 while (p && p < lslash) {
1020                         if (*p == '/') 
1021                                 strcat(res,     "../");
1022                         ++p;
1023                 }
1024
1025                 strcat(res, q+1); /* don't copy the slash at the beginning */
1026                 
1027 #ifdef  WIN32
1028                 BLI_char_switch(res+2, '/', '\\');
1029 #endif
1030                 strcpy(file, res);
1031         }
1032 }
1033
1034 int BLI_convertstringcode(char *path, const char *basepath, int framenum)
1035 {
1036         int wasrelative;
1037         int ch_sta, ch_end;
1038         char tmp[FILE_MAX];
1039         char base[FILE_MAX];
1040         char vol[3] = {'\0', '\0', '\0'};
1041
1042         BLI_strncpy(vol, path, 3);
1043         wasrelative= (strncmp(vol, "//", 2)==0);
1044
1045 #ifdef WIN32
1046         /* we are checking here if we have an absolute path that is not in the current
1047            blend file as a lib main - we are basically checking for the case that a 
1048            UNIX root '/' is passed.
1049         */
1050         if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
1051                 char *p = path;
1052                 get_default_root(tmp);
1053                 // get rid of the slashes at the beginning of the path
1054                 while (*p == '\\' || *p == '/') {
1055                         p++;
1056                 }
1057                 strcat(tmp, p);
1058         }
1059         else {
1060                 BLI_strncpy(tmp, path, FILE_MAX);
1061         }
1062 #else
1063         BLI_strncpy(tmp, path, FILE_MAX);
1064 #endif
1065
1066         BLI_strncpy(base, basepath, FILE_MAX);
1067         
1068         /* push slashes into unix mode - strings entering this part are
1069            potentially messed up: having both back- and forward slashes.
1070            Here we push into one conform direction, and at the end we
1071            push them into the system specific dir. This ensures uniformity
1072            of paths and solving some problems (and prevent potential future
1073            ones) -jesterKing. */
1074         BLI_char_switch(tmp, '\\', '/');
1075         BLI_char_switch(base, '\\', '/');       
1076
1077         if (tmp[0] == '/' && tmp[1] == '/') {
1078                 char *filepart= BLI_strdup(tmp+2); /* skip code */
1079                 char *lslash= BLI_last_slash(base);
1080
1081                 if (lslash) {
1082                         int baselen= (int) (lslash-base) + 1;
1083
1084                         memcpy(tmp, base, baselen);
1085                         strcpy(tmp+baselen, filepart);
1086                 } else {
1087                         strcpy(tmp, filepart);
1088                 }
1089                 
1090                 MEM_freeN(filepart);
1091         }
1092         
1093         
1094         /* Insert current frame: file### -> file001 */
1095         ch_end = 0;
1096         for (ch_sta = 0; tmp[ch_sta] != '\0'; ch_sta++) {
1097                 if (tmp[ch_sta] == '#') {
1098                         ch_end = ch_sta+1;
1099                         while (tmp[ch_end] == '#') {
1100                                 ch_end++;
1101                         }                       
1102                         break;
1103                 }
1104         }
1105         if (ch_end) { /* warning, ch_end is the last # +1 */
1106                 /* Add the frame number? */
1107                 short numlen, hashlen;
1108                 char format[16]; /* 6 is realistically the maxframe (300000), so 8 should be enough, but 16 to be safe. */
1109                 
1110                 numlen = 1 + (int)log10((double)framenum); /* this is the number of chars in the number */
1111                 hashlen = ch_end - ch_sta;
1112                 
1113                 sprintf(format, "%d", framenum);
1114                 
1115                 if (numlen==hashlen) { /* simple case */
1116                         memcpy(tmp+ch_sta, format, numlen);
1117                 } else if (numlen < hashlen) {
1118                         memcpy(tmp+ch_sta + (hashlen-numlen), format, numlen); /*dont copy the string terminator */
1119                         memset(tmp+ch_sta, '0', hashlen-numlen);
1120                 } else {
1121                         /* number is longer then number of #'s */
1122                         if (tmp[ch_end] == '\0') { /* hashes are last, no need to move any string*/
1123                                 /* bad juju - not testing string length here :/ */
1124                                 memcpy(tmp+ch_sta, format, numlen+1); /* add 1 to get the string terminator \0 */
1125                         } else {
1126                                 /* we need to move the end characters */
1127                                 int i = strlen(tmp); /* +1 to copy the string terminator */
1128                                 int j = i + (numlen-hashlen); /* from/to */
1129                                 while (i >= ch_end) {
1130                                         tmp[j] = tmp[i]; 
1131                                         i--;
1132                                         j--;
1133                                 }
1134                                 memcpy(tmp + ch_sta, format, numlen);
1135                         }
1136                 }       
1137         }
1138         /* done with file### stuff */
1139         
1140         strcpy(path, tmp);
1141 #ifdef WIN32
1142         /* skip first two chars, which in case of
1143            absolute path will be drive:/blabla and
1144            in case of relpath //blabla/. So relpath
1145            // will be retained, rest will be nice and
1146            shiny win32 backward slashes :) -jesterKing
1147         */
1148         BLI_char_switch(path+2, '/', '\\');
1149 #endif
1150
1151         return wasrelative;
1152 }
1153
1154 /* copy di to fi, filename only */
1155 void BLI_splitdirstring(char *di, char *fi)
1156 {
1157         char *lslash= BLI_last_slash(di);
1158
1159         if (lslash) {
1160                 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
1161                 *(lslash+1)=0;
1162         } else {
1163                 BLI_strncpy(fi, di, FILE_MAXFILE);
1164                 di[0]= 0;
1165         }
1166 }
1167
1168 char *BLI_gethome(void) {
1169         #ifdef __BeOS
1170                 return "/boot/home/";           /* BeOS 4.5: doubleclick at icon doesnt give home env */
1171
1172         #elif !defined(WIN32)
1173                 return getenv("HOME");
1174
1175         #else /* Windows */
1176                 char * ret;
1177                 static char dir[512];
1178                 static char appdatapath[MAXPATHLEN];
1179                 HRESULT hResult;
1180
1181                 /* Check for %HOME% env var */
1182
1183                 ret = getenv("HOME");
1184                 if(ret) {
1185                         sprintf(dir, "%s\\.blender", ret);
1186                         if (BLI_exists(dir)) return dir;
1187                 }
1188
1189                 /* else, check install dir (path containing blender.exe) */
1190
1191                 BLI_getInstallationDir(dir);
1192
1193                 if (BLI_exists(dir))
1194                 {
1195                         strcat(dir,"\\.blender");
1196                         if (BLI_exists(dir)) return(dir);
1197                 }
1198
1199                                 
1200                 /* add user profile support for WIN 2K / NT */
1201                 hResult = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdatapath);
1202                 
1203                 if (hResult == S_OK)
1204                 {
1205                         if (BLI_exists(appdatapath)) { /* from fop, also below... */
1206                                 sprintf(dir, "%s\\Blender Foundation\\Blender", appdatapath);
1207                                 BLI_recurdir_fileops(dir);
1208                                 if (BLI_exists(dir)) {
1209                                         strcat(dir,"\\.blender");
1210                                         if(BLI_exists(dir)) return(dir);
1211                                 }
1212                         }
1213                         hResult = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdatapath);
1214                         if (hResult == S_OK)
1215                         {
1216                                 if (BLI_exists(appdatapath)) 
1217                                 { /* from fop, also below... */
1218                                         sprintf(dir, "%s\\Blender Foundation\\Blender", appdatapath);
1219                                         BLI_recurdir_fileops(dir);
1220                                         if (BLI_exists(dir)) {
1221                                                 strcat(dir,"\\.blender");
1222                                                 if(BLI_exists(dir)) return(dir);
1223                                         }
1224                                 }
1225                         }
1226                 }
1227 #if 0
1228                 ret = getenv("USERPROFILE");
1229                 if (ret) {
1230                         if (BLI_exists(ret)) { /* from fop, also below...  */
1231                                 sprintf(dir, "%s\\Application Data\\Blender Foundation\\Blender", ret);
1232                                 BLI_recurdir_fileops(dir);
1233                                 if (BLI_exists(dir)) {
1234                                         strcat(dir,"\\.blender");
1235                                         if(BLI_exists(dir)) return(dir);
1236                                 }
1237                         }
1238                 }
1239 #endif
1240
1241                 /* 
1242                    Saving in the Windows dir is less than desirable. 
1243                    Use as a last resort ONLY! (aphex)
1244                 */
1245                 
1246                 ret = getenv("WINDOWS");                
1247                 if (ret) {
1248                         if(BLI_exists(ret)) return ret;
1249                 }
1250
1251                 ret = getenv("WINDIR"); 
1252                 if (ret) {
1253                         if(BLI_exists(ret)) return ret;
1254                 }
1255                 
1256                 return "C:\\Temp";      /* sheesh! bad, bad, bad! (aphex) */
1257         #endif
1258 }
1259
1260 void BLI_clean(char *path)
1261 {
1262         if(path==0) return;
1263 #ifdef WIN32
1264         if(path && strlen(path)>2) {
1265                 BLI_char_switch(path+2, '/', '\\');
1266         }
1267 #else
1268         BLI_char_switch(path, '\\', '/');
1269 #endif
1270 }
1271
1272 void BLI_char_switch(char *string, char from, char to) 
1273 {
1274         if(string==0) return;
1275         while (*string != 0) {
1276                 if (*string == from) *string = to;
1277                 string++;
1278         }
1279 }
1280
1281 void BLI_make_exist(char *dir) {
1282         int a;
1283
1284         #ifdef WIN32
1285                 BLI_char_switch(dir, '/', '\\');
1286         #else
1287                 BLI_char_switch(dir, '\\', '/');
1288         #endif  
1289         
1290         a = strlen(dir);
1291         
1292 #ifdef WIN32    
1293         while(BLI_exists(dir) == 0){
1294                 a --;
1295                 while(dir[a] != '\\'){
1296                         a--;
1297                         if (a <= 0) break;
1298                 }
1299                 if (a >= 0) dir[a+1] = 0;
1300                 else {
1301                         /* defaulting to drive (usually 'C:') of Windows installation */
1302                         get_default_root(dir);
1303                         break;
1304                 }
1305         }
1306 #else
1307         while(BLI_exist(dir) == 0){
1308                 a --;
1309                 while(dir[a] != '/'){
1310                         a--;
1311                         if (a <= 0) break;
1312                 }
1313                 if (a >= 0) dir[a+1] = 0;
1314                 else {
1315                         strcpy(dir,"/");
1316                         break;
1317                 }
1318         }
1319 #endif
1320 }
1321
1322 void BLI_make_existing_file(char *name)
1323 {
1324         char di[FILE_MAXDIR], fi[FILE_MAXFILE];
1325         
1326         strcpy(di, name);
1327         BLI_splitdirstring(di, fi);
1328         
1329         /* test exist */
1330         if (BLI_exists(di) == 0) {
1331                 BLI_recurdir_fileops(di);
1332         }
1333 }
1334
1335
1336 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1337 {
1338         int sl;
1339
1340         if (!string || !dir || !file) return; /* We don't want any NULLs */
1341         
1342         string[0]= 0; /* ton */
1343
1344         /* we first push all slashes into unix mode, just to make sure we don't get
1345            any mess with slashes later on. -jesterKing */
1346         /* constant strings can be passed for those parameters - don't change them - elubie */
1347         /*
1348         BLI_char_switch(relabase, '\\', '/');
1349         BLI_char_switch(dir, '\\', '/');
1350         BLI_char_switch(file, '\\', '/');
1351         */
1352
1353         /* Resolve relative references */       
1354         if (relabase && dir[0] == '/' && dir[1] == '/') {
1355                 char *lslash;
1356                 
1357                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1358                 strcpy(string, relabase);
1359                 
1360                 lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\');
1361                 
1362                 if(lslash) *(lslash+1)= 0;
1363
1364                 dir+=2; /* Skip over the relative reference */
1365         }
1366 #ifdef WIN32
1367         else {
1368                 if (strlen(dir) >= 2 && dir[1] == ':' ) {
1369                         BLI_strncpy(string, dir, 3);
1370                         dir += 2;
1371                 }
1372                 else { /* no drive specified */
1373                         /* first option: get the drive from the relabase if it has one */
1374                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1375                                 BLI_strncpy(string, relabase, 3);       
1376                                 string[2] = '\\';
1377                                 string[3] = '\0';
1378                         }
1379                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1380                                 get_default_root(string);
1381                         }
1382                         
1383                         /* ignore leading slashes */
1384                         while (*dir == '/' || *dir == '\\') dir++;
1385                 }
1386         }
1387 #endif
1388
1389         strcat(string, dir);
1390
1391         /* Make sure string ends in one (and only one) slash */ 
1392         /* first trim all slashes from the end of the string */
1393         sl = strlen(string);
1394         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1395                 string[sl-1] = '\0';
1396                 sl--;
1397         }
1398         /* since we've now removed all slashes, put back one slash at the end. */
1399         strcat(string, "/");
1400         
1401         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1402                 file++;
1403                 
1404         strcat (string, file);
1405         
1406         /* Push all slashes to the system preferred direction */
1407         BLI_clean(string);
1408 }
1409
1410 int BLI_testextensie(const char *str, const char *ext)
1411 {
1412         short a, b;
1413         int retval;
1414
1415         a= strlen(str);
1416         b= strlen(ext);
1417
1418         if(a==0 || b==0 || b>=a) {
1419                 retval = 0;
1420         } else if (BLI_strcasecmp(ext, str + a - b)) {
1421                 retval = 0;     
1422         } else {
1423                 retval = 1;
1424         }
1425
1426         return (retval);
1427 }
1428
1429 /*
1430  * This is a simple version of BLI_split_dirfile that has the following advantages...
1431  * 
1432  * Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1433  * - wont change 'string'
1434  * - wont create any directories
1435  * - dosnt use CWD, or deal with relative paths.
1436  * - Only fill's in *dir and *file when they are non NULL
1437  * */
1438 void BLI_split_dirfile_basic(const char *string, char *dir, char *file)
1439 {
1440         int lslash=0, i = 0;
1441         for (i=0; string[i]!='\0'; i++) {
1442                 if (string[i]=='\\' || string[i]=='/')
1443                         lslash = i+1;
1444         }
1445         if (dir) {
1446                 if (lslash) {
1447                         BLI_strncpy( dir, string, lslash+1); /* +1 to include the slash and the last char */
1448                 } else {
1449                         dir[0] = '\0';
1450                 }
1451         }
1452         
1453         if (file) {
1454                 strcpy( file, string+lslash);
1455         }
1456 }
1457
1458
1459 /* Warning,
1460  * - May modify 'string' variable
1461  * - May create the directory if it dosnt exist
1462  * if this is not needed use BLI_split_dirfile_basic(...)
1463  */
1464 void BLI_split_dirfile(char *string, char *dir, char *file)
1465 {
1466         int a;
1467 #ifdef WIN32
1468         int sl;
1469         short is_relative = 0;
1470         char path[FILE_MAX];
1471 #endif
1472
1473         dir[0]= 0;
1474         file[0]= 0;
1475
1476 #ifdef WIN32
1477         BLI_strncpy(path, string, FILE_MAX);
1478         BLI_char_switch(path, '/', '\\'); /* make sure we have a valid path format */
1479         sl = strlen(path);
1480         if (sl) {
1481                 int len;
1482                 if (path[0] == '/' || path[0] == '\\') { 
1483                         BLI_strncpy(dir, path, FILE_MAXDIR);
1484                         if (sl > 1 && path[0] == '\\' && path[1] == '\\') is_relative = 1;
1485                 } else if (sl > 2 && path[1] == ':' && path[2] == '\\') {
1486                         BLI_strncpy(dir, path, FILE_MAXDIR);
1487                 } else {
1488                         BLI_getwdN(dir);
1489                         strcat(dir,"\\");
1490                         strcat(dir,path);
1491                         BLI_strncpy(path,dir,FILE_MAXDIR+FILE_MAXFILE);
1492                 }
1493                 
1494                 // BLI_exist doesn't recognize a slashed dirname as a dir
1495                 //  check if a trailing slash exists, and remove it. Do not do this
1496                 //  when we are already at root. -jesterKing
1497                 a = strlen(dir);
1498                 if(a>=4 && dir[a-1]=='\\') dir[a-1] = 0;
1499
1500                 if (is_relative) {
1501                         printf("WARNING: BLI_split_dirfile needs absolute dir\n");
1502                 }
1503                 else {
1504                         BLI_make_exist(dir);
1505                 }
1506
1507                 if (S_ISDIR(BLI_exist(dir))) {
1508
1509                         /* copy from end of string into file, to ensure filename itself isn't truncated 
1510                         if string is too long. (aphex) */
1511
1512                         len = FILE_MAXFILE - strlen(path);
1513
1514                         if (len < 0)
1515                                 BLI_strncpy(file,path + abs(len),FILE_MAXFILE);
1516                         else
1517                                 BLI_strncpy(file,path,FILE_MAXFILE);
1518                     
1519                         if (strrchr(path,'\\')) {
1520                                 BLI_strncpy(file,strrchr(path,'\\')+1,FILE_MAXFILE);
1521                         }
1522                         
1523                         if ( (a = strlen(dir)) ) {
1524                                 if (dir[a-1] != '\\') strcat(dir,"\\");
1525                         }
1526                 }
1527                 else {
1528                         a = strlen(dir) - 1;
1529                         while(a>0 && dir[a] != '\\') a--;
1530                         dir[a + 1] = 0;
1531                         BLI_strncpy(file, path + strlen(dir),FILE_MAXFILE);
1532                 }
1533
1534         }
1535         else {
1536                 /* defaulting to first valid drive hoping it's not empty CD and DVD drives */
1537                 get_default_root(dir);
1538                 file[0]=0;
1539         }
1540 #else
1541         if (strlen(string)) {
1542                 if (string[0] == '/') { 
1543                         strcpy(dir, string);
1544                 } else if (string[1] == ':' && string[2] == '\\') {
1545                         string+=2;
1546                         strcpy(dir, string);
1547                 } else {
1548                         BLI_getwdN(dir);
1549                         strcat(dir,"/");
1550                         strcat(dir,string);
1551                         strcpy((char *)string,dir);
1552                 }
1553
1554                 BLI_make_exist(dir);
1555                         
1556                 if (S_ISDIR(BLI_exist(dir))) {
1557                         strcpy(file,string + strlen(dir));
1558
1559                         if (strrchr(file,'/')) strcpy(file,strrchr(file,'/')+1);
1560                 
1561                         if ( (a = strlen(dir)) ) {
1562                                 if (dir[a-1] != '/') strcat(dir,"/");
1563                         }
1564                 }
1565                 else {
1566                         a = strlen(dir) - 1;
1567                         while(dir[a] != '/') a--;
1568                         dir[a + 1] = 0;
1569                         strcpy(file, string + strlen(dir));
1570                 }
1571         }
1572         else {
1573                 BLI_getwdN(dir);
1574                 strcat(dir, "/");
1575                 file[0] = 0;
1576         }
1577 #endif
1578 }
1579
1580 /* simple appending of filename to dir, does not check for valid path! */
1581 void BLI_join_dirfile(char *string, const char *dir, const char *file)
1582 {
1583         int sl_dir = strlen(dir);
1584         BLI_strncpy(string, dir, FILE_MAX);
1585         if (sl_dir > FILE_MAX-1) sl_dir = FILE_MAX-1;
1586         
1587         /* only add seperator if needed */
1588 #ifdef WIN32
1589         if (string[sl_dir-1] != '\\') {
1590                 string[sl_dir] = '\\';
1591                 sl_dir++;
1592         }
1593 #else
1594         if (string[sl_dir-1] != '/') {
1595                 string[sl_dir] = '/';
1596                 sl_dir++;
1597         }
1598 #endif
1599         
1600         if (sl_dir <FILE_MAX) {
1601                 BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
1602         }
1603 }
1604
1605 static int add_win32_extension(char *name)
1606 {
1607         int retval = 0;
1608         int type;
1609
1610         type = BLI_exist(name);
1611         if ((type == 0) || S_ISDIR(type)) {
1612 #ifdef _WIN32
1613                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1614                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1615                 char *extensions = getenv("PATHEXT");
1616                 if (extensions) {
1617                         char *temp;
1618                         do {
1619                                 strcpy(filename, name);
1620                                 temp = strstr(extensions, ";");
1621                                 if (temp) {
1622                                         strncpy(ext, extensions, temp - extensions);
1623                                         ext[temp - extensions] = 0;
1624                                         extensions = temp + 1;
1625                                         strcat(filename, ext);
1626                                 } else {
1627                                         strcat(filename, extensions);
1628                                 }
1629
1630                                 type = BLI_exist(filename);
1631                                 if (type && (! S_ISDIR(type))) {
1632                                         retval = 1;
1633                                         strcpy(name, filename);
1634                                         break;
1635                                 }
1636                         } while (temp);
1637                 }
1638 #endif
1639         } else {
1640                 retval = 1;
1641         }
1642
1643         return (retval);
1644 }
1645
1646 void BLI_where_am_i(char *fullname, const char *name)
1647 {
1648         char filename[FILE_MAXDIR+FILE_MAXFILE];
1649         char *path = NULL, *temp;
1650         int len;
1651 #ifdef _WIN32
1652         char *seperator = ";";
1653         char *slash = "\\";
1654 #else
1655         char *seperator = ":";
1656         char *slash = "/";
1657 #endif
1658
1659         
1660 #ifdef __linux__
1661         /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1662         path = br_find_exe( NULL );
1663         if (path) {
1664                 strcpy(fullname, path);
1665                 return;
1666         }
1667 #endif
1668         
1669         /* unix and non linux */
1670         if (name && fullname && strlen(name)) {
1671                 strcpy(fullname, name);
1672                 if (name[0] == '.') {
1673                         // relative path, prepend cwd
1674                         BLI_getwdN(fullname);
1675                         len = strlen(fullname);
1676                         if (len && fullname[len -1] != slash[0]) {
1677                                 strcat(fullname, slash);
1678                         }
1679                         strcat(fullname, name);
1680                         add_win32_extension(fullname);
1681                 } else if (BLI_last_slash(name)) {
1682                         // full path
1683                         strcpy(fullname, name);
1684                         add_win32_extension(fullname);
1685                 } else {
1686                         // search for binary in $PATH
1687                         path = getenv("PATH");
1688                         if (path) {
1689                                 do {
1690                                         temp = strstr(path, seperator);
1691                                         if (temp) {
1692                                                 strncpy(filename, path, temp - path);
1693                                                 filename[temp - path] = 0;
1694                                                 path = temp + 1;
1695                                         } else {
1696                                                 strncpy(filename, path, sizeof(filename));
1697                                         }
1698                                         len = strlen(filename);
1699                                         if (len && filename[len - 1] != slash[0]) {
1700                                                 strcat(filename, slash);
1701                                         }
1702                                         strcat(filename, name);
1703                                         if (add_win32_extension(filename)) {
1704                                                 strcpy(fullname, filename);
1705                                                 break;
1706                                         }
1707                                 } while (temp);
1708                         }
1709                 }
1710 #ifndef NDEBUG
1711                 if (strcmp(name, fullname)) {
1712                         printf("guessing '%s' == '%s'\n", name, fullname);
1713                 }
1714 #endif
1715
1716 #ifdef _WIN32
1717                 // in windows change long filename to short filename because
1718                 // win2k doesn't know how to parse a commandline with lots of
1719                 // spaces and double-quotes. There's another solution to this
1720                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1721                 // that's even uglier
1722                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1723 #ifndef NDEBUG
1724                 printf("Shortname = '%s'\n", fullname);
1725 #endif
1726 #endif
1727         }
1728 }
1729
1730 void BLI_where_is_temp(char *fullname, int usertemp)
1731 {
1732         fullname[0] = '\0';
1733         
1734         if (usertemp && BLI_exists(U.tempdir)) {
1735                 strcpy(fullname, U.tempdir);
1736         }
1737         
1738         
1739 #ifdef WIN32
1740         if (fullname[0] == '\0') {
1741                 char *tmp = getenv("TEMP"); /* Windows */
1742                 if (tmp && BLI_exists(tmp)) {
1743                         strcpy(fullname, tmp);
1744                 }
1745         }
1746 #else
1747         /* Other OS's - Try TMP and TMPDIR */
1748         if (fullname[0] == '\0') {
1749                 char *tmp = getenv("TMP");
1750                 if (tmp && BLI_exists(tmp)) {
1751                         strcpy(fullname, tmp);
1752                 }
1753         }
1754         
1755         if (fullname[0] == '\0') {
1756                 char *tmp = getenv("TMPDIR");
1757                 if (tmp && BLI_exists(tmp)) {
1758                         strcpy(fullname, tmp);
1759                 }
1760         }
1761 #endif  
1762         
1763         if (fullname[0] == '\0') {
1764                 strcpy(fullname, "/tmp/");
1765         } else {
1766                 /* add a trailing slash if needed */
1767                 BLI_add_slash(fullname);
1768         }
1769 }
1770
1771 /* 
1772  * returns absolute path to the app bundle
1773  * only useful on OS X 
1774  */
1775 #ifdef __APPLE__
1776 char* BLI_getbundle(void) {
1777         CFURLRef bundleURL;
1778         CFStringRef pathStr;
1779         static char path[MAXPATHLEN];
1780         CFBundleRef mainBundle = CFBundleGetMainBundle();
1781
1782         bundleURL = CFBundleCopyBundleURL(mainBundle);
1783         pathStr = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
1784         CFStringGetCString(pathStr, path, MAXPATHLEN, kCFStringEncodingASCII);
1785         return path;
1786 }
1787 #endif
1788
1789 /* strcasestr not available in MSVC */
1790 char *BLI_strcasestr(const char *s, const char *find)
1791 {
1792     register char c, sc;
1793     register size_t len;
1794         
1795     if ((c = *find++) != 0) {
1796                 c= tolower(c);
1797                 len = strlen(find);
1798                 do {
1799                         do {
1800                                 if ((sc = *s++) == 0)
1801                                         return (NULL);
1802                                 sc= tolower(sc);
1803                         } while (sc != c);
1804                 } while (BLI_strncasecmp(s, find, len) != 0);
1805                 s--;
1806     }
1807     return ((char *) s);
1808 }
1809
1810
1811 int BLI_strcasecmp(const char *s1, const char *s2) {
1812         int i;
1813
1814         for (i=0; ; i++) {
1815                 char c1 = tolower(s1[i]);
1816                 char c2 = tolower(s2[i]);
1817
1818                 if (c1<c2) {
1819                         return -1;
1820                 } else if (c1>c2) {
1821                         return 1;
1822                 } else if (c1==0) {
1823                         break;
1824                 }
1825         }
1826
1827         return 0;
1828 }
1829
1830 int BLI_strncasecmp(const char *s1, const char *s2, int n) {
1831         int i;
1832
1833         for (i=0; i<n; i++) {
1834                 char c1 = tolower(s1[i]);
1835                 char c2 = tolower(s2[i]);
1836
1837                 if (c1<c2) {
1838                         return -1;
1839                 } else if (c1>c2) {
1840                         return 1;
1841                 } else if (c1==0) {
1842                         break;
1843                 }
1844         }
1845
1846         return 0;
1847 }
1848
1849
1850 #ifdef WITH_ICONV
1851 #include "iconv.h"
1852 #include "localcharset.h"
1853
1854 void BLI_string_to_utf8(char *original, char *utf_8, char *code)
1855 {
1856         size_t inbytesleft=strlen(original);
1857         size_t outbytesleft=512;
1858         size_t rv=0;
1859         iconv_t cd;
1860         
1861         if (NULL == code) {
1862                 code = locale_charset();
1863         }
1864         cd=iconv_open("UTF-8", code);
1865
1866         if (cd == (iconv_t)(-1)) {
1867                 printf("iconv_open Error");
1868                 *utf_8='\0';
1869                 return ;
1870         }
1871         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1872         if (rv == (size_t) -1) {
1873                 printf("iconv Error\n");
1874                 return ;
1875         }
1876         *utf_8 = '\0';
1877         iconv_close(cd);
1878 }
1879 #endif // WITH_ICONV
1880
1881 void BLI_timestr(double _time, char *str)
1882 {
1883         /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */
1884         int  hr= ( (int)  _time) / (60*60);
1885         int min= (((int)  _time) / 60 ) % 60;
1886         int sec= ( (int) (_time)) % 60;
1887         int hun= ( (int) (_time   * 100.0)) % 100;
1888         
1889         if (hr) {
1890                 sprintf(str, "%.2d:%.2d:%.2d.%.2d",hr,min,sec,hun);
1891         } else {
1892                 sprintf(str, "%.2d:%.2d.%.2d",min,sec,hun);
1893         }
1894         
1895         str[11]=0;
1896 }
1897
1898 /* ************** 64 bits magic, trick to support up to 32 gig of address space *************** */
1899 /*                only works for malloced pointers (8 aligned)                   */
1900
1901 #ifdef __LP64__ 
1902
1903 #if defined(WIN32) && !defined(FREE_WINDOWS)
1904 #define PMASK           0x07FFFFFFFFi64
1905 #else
1906 #define PMASK           0x07FFFFFFFFll
1907 #endif
1908
1909
1910 int BLI_int_from_pointer(void *poin)
1911 {
1912         long lval= (long)poin;
1913         
1914         return (int)(lval>>3);
1915 }
1916
1917 void *BLI_pointer_from_int(int val)
1918 {
1919         static int firsttime= 1;
1920         static long basevalue= 0;
1921         
1922         if(firsttime) {
1923                 void *poin= malloc(10000);
1924                 basevalue= (long)poin;
1925                 basevalue &= ~PMASK;
1926                 printf("base: %d pointer %p\n", basevalue, poin); /* debug */
1927                 firsttime= 0;
1928                 free(poin);
1929         }
1930         return (void *)(basevalue | (((long)val)<<3));
1931 }
1932
1933 #else
1934
1935 int BLI_int_from_pointer(void *poin)
1936 {
1937         return (int)poin;
1938 }
1939 void *BLI_pointer_from_int(int val)
1940 {
1941         return (void *)val;
1942 }
1943
1944 #endif
1945