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