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