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