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