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