svn merge -r 15392:15551 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[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         BLI_add_slash(dir);
869
870 }
871
872 void BLI_cleanup_file(const char *relabase, char *dir)
873 {
874         short a;
875         char *start, *eind;
876         if (relabase) {
877                 BLI_convertstringcode(dir, relabase);
878         } else {
879                 if (dir[0]=='/' && dir[1]=='/') {
880                         if (dir[2]== '\0') {
881                                 return; /* path is "//" - cant clean it */
882                         }
883                         dir = dir+2; /* skip the first // */
884                 }
885         }
886         
887         /* Note
888          *   memmove( start, eind, strlen(eind)+1 );
889          * is the same as
890          *   strcpy( start, eind ); 
891          * except strcpy should not be used because there is overlap,
892           * so use memmove's slightly more obscure syntax - Campbell
893          */
894         
895 #ifdef WIN32
896         if(dir[0]=='.') {       /* happens for example in FILE_MAIN */
897            get_default_root(dir);
898            return;
899         }       
900
901         while ( (start = strstr(dir, "\\..\\")) ) {
902                 eind = start + strlen("\\..\\") - 1;
903                 a = start-dir-1;
904                 while (a>0) {
905                         if (dir[a] == '\\') break;
906                         a--;
907                 }
908                 if (a<0) {
909                         break;
910                 } else {
911                         memmove( dir+a, eind, strlen(eind)+1 );
912                 }
913         }
914
915         while ( (start = strstr(dir,"\\.\\")) ){
916                 eind = start + strlen("\\.\\") - 1;
917                 memmove( start, eind, strlen(eind)+1 );
918         }
919
920         while ( (start = strstr(dir,"\\\\" )) ){
921                 eind = start + strlen("\\\\") - 1;
922                 memmove( start, eind, strlen(eind)+1 );
923         }
924
925         if((a = strlen(dir))){                          /* remove the '\\' at the end */
926                 while(a>0 && dir[a-1] == '\\'){
927                         a--;
928                         dir[a] = 0;
929                 }
930         }
931 #else
932         if(dir[0]=='.') {       /* happens, for example in FILE_MAIN */
933            dir[0]= '/';
934            dir[1]= 0;
935            return;
936         }       
937
938         while ( (start = strstr(dir, "/../")) ) {
939                 eind = start + strlen("/../") - 1;
940                 a = start-dir-1;
941                 while (a>0) {
942                         if (dir[a] == '/') break;
943                         a--;
944                 }
945                 if (a<0) {
946                         break;
947                 } else {
948                         memmove( dir+a, eind, strlen(eind)+1 );
949                 }
950         }
951
952         while ( (start = strstr(dir,"/./")) ){
953                 eind = start + strlen("/./") - 1;
954                 memmove( start, eind, strlen(eind)+1 );
955         }
956
957         while ( (start = strstr(dir,"//" )) ){
958                 eind = start + strlen("//") - 1;
959                 memmove( start, eind, strlen(eind)+1 );
960         }
961
962         if( (a = strlen(dir)) ){                                /* remove all '/' at the end */
963                 while(dir[a-1] == '/'){
964                         a--;
965                         dir[a] = 0;
966                         if (a<=0) break;
967                 }
968         }
969 #endif
970 }
971
972
973 void BLI_makestringcode(const char *relfile, char *file)
974 {
975         char * p;
976         char * q;
977         char * lslash;
978         char temp[FILE_MAXDIR+FILE_MAXFILE];
979         char res[FILE_MAXDIR+FILE_MAXFILE];
980         
981         /* if file is already relative, bail out */
982         if(file[0]=='/' && file[1]=='/') return;
983         
984         /* also bail out if relative path is not set */
985         if (relfile[0] == 0) return;
986
987 #ifdef WIN32 
988         if (strlen(relfile) > 2 && relfile[1] != ':') {
989                 char* ptemp;
990                 /* fix missing volume name in relative base,
991                    can happen with old .Blog files */
992                 get_default_root(temp);
993                 ptemp = &temp[2];
994                 if (relfile[0] != '\\' && relfile[0] != '/') {
995                         ptemp++;
996                 }
997                 BLI_strncpy(ptemp, relfile, FILE_MAXDIR + FILE_MAXFILE-3);
998         } else {
999                 BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE);
1000         }
1001
1002         if (strlen(file) > 2) {
1003                 if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] )
1004                         return;
1005         }
1006 #else
1007         BLI_strncpy(temp, relfile, FILE_MAX);
1008 #endif
1009
1010         BLI_char_switch(temp, '\\', '/');
1011         BLI_char_switch(file, '\\', '/');
1012         
1013         /* remove /./ which confuse the following slash counting... */
1014         BLI_cleanup_file(NULL, file);
1015         BLI_cleanup_file(NULL, temp);
1016         
1017         /* the last slash in the file indicates where the path part ends */
1018         lslash = BLI_last_slash(temp);
1019
1020         if (lslash) 
1021         {       
1022                 /* find the prefix of the filename that is equal for both filenames.
1023                    This is replaced by the two slashes at the beginning */
1024                 p = temp;
1025                 q = file;
1026                 while (*p == *q) {
1027                         ++p; ++q;
1028                 }
1029                 /* we might have passed the slash when the beginning of a dir matches 
1030                    so we rewind. Only check on the actual filename
1031                 */
1032                 if (*q != '/') {
1033                         while ( (q >= file) && (*q != '/') ) { --q; --p; }
1034                 } 
1035                 else if (*p != '/') {
1036                         while ( (p >= temp) && (*p != '/') ) { --p; --q; }
1037                 }
1038                 
1039                 strcpy(res,     "//");
1040
1041                 /* p now points to the slash that is at the beginning of the part
1042                    where the path is different from the relative path. 
1043                    We count the number of directories we need to go up in the
1044                    hierarchy to arrive at the common 'prefix' of the path
1045                 */                      
1046                 while (p && p < lslash) {
1047                         if (*p == '/') 
1048                                 strcat(res,     "../");
1049                         ++p;
1050                 }
1051
1052                 strcat(res, q+1); /* don't copy the slash at the beginning */
1053                 
1054 #ifdef  WIN32
1055                 BLI_char_switch(res+2, '/', '\\');
1056 #endif
1057                 strcpy(file, res);
1058         }
1059 }
1060
1061
1062 int BLI_convertstringframe(char *path, int frame)
1063 {
1064         int ch_sta, ch_end, i;
1065         /* Insert current frame: file### -> file001 */
1066         ch_sta = ch_end = 0;
1067         for (i = 0; path[i] != '\0'; i++) {
1068                 if (path[i] == '\\' || path[i] == '/') {
1069                         ch_end = 0; /* this is a directory name, dont use any hashes we found */
1070                 } else if (path[i] == '#') {
1071                         ch_sta = i;
1072                         ch_end = ch_sta+1;
1073                         while (path[ch_end] == '#') {
1074                                 ch_end++;
1075                         }
1076                         i = ch_end-1; /* keep searching */
1077                         
1078                         /* dont break, there may be a slash after this that invalidates the previous #'s */
1079                 }
1080         }
1081         if (ch_end) { /* warning, ch_end is the last # +1 */
1082                 /* Add the frame number? */
1083                 short numlen, hashlen;
1084                 char tmp[FILE_MAX];
1085                 
1086                 char format[16]; /* 6 is realistically the maxframe (300000), so 8 should be enough, but 16 to be safe. */
1087                 if (((ch_end-1)-ch_sta) >= 16) {
1088                         ch_end = ch_sta+15; /* disallow values longer then 'format' can hold */
1089                 }
1090                 
1091                 strcpy(tmp, path);
1092                 
1093                 numlen = 1 + (int)log10((double)frame); /* this is the number of chars in the number */
1094                 hashlen = ch_end - ch_sta;
1095                 
1096                 sprintf(format, "%d", frame);
1097                 
1098                 if (numlen==hashlen) { /* simple case */
1099                         memcpy(tmp+ch_sta, format, numlen);
1100                 } else if (numlen < hashlen) {
1101                         memcpy(tmp+ch_sta + (hashlen-numlen), format, numlen); /*dont copy the string terminator */
1102                         memset(tmp+ch_sta, '0', hashlen-numlen);
1103                 } else {
1104                         /* number is longer then number of #'s */
1105                         if (tmp[ch_end] == '\0') { /* hashes are last, no need to move any string*/
1106                                 /* bad juju - not testing string length here :/ */
1107                                 memcpy(tmp+ch_sta, format, numlen+1); /* add 1 to get the string terminator \0 */
1108                         } else {
1109                                 /* we need to move the end characters, reuse i */
1110                                 int j;
1111                                 
1112                                 i = strlen(tmp); /* +1 to copy the string terminator */
1113                                 j = i + (numlen-hashlen); /* from/to */
1114                                 
1115                                 while (i >= ch_end) {
1116                                         tmp[j] = tmp[i]; 
1117                                         i--;
1118                                         j--;
1119                                 }
1120                                 memcpy(tmp + ch_sta, format, numlen);
1121                         }
1122                 }       
1123                 strcpy(path, tmp);
1124                 return 1;
1125         }
1126         return 0;
1127 }
1128
1129
1130 int BLI_convertstringcode(char *path, const char *basepath)
1131 {
1132         int wasrelative;
1133         char tmp[FILE_MAX];
1134         char base[FILE_MAX];
1135         char vol[3] = {'\0', '\0', '\0'};
1136
1137         BLI_strncpy(vol, path, 3);
1138         wasrelative= (vol[0]=='/' && vol[1]=='/');
1139         
1140 #ifdef WIN32
1141         /* we are checking here if we have an absolute path that is not in the current
1142            blend file as a lib main - we are basically checking for the case that a 
1143            UNIX root '/' is passed.
1144         */
1145         if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
1146                 char *p = path;
1147                 get_default_root(tmp);
1148                 // get rid of the slashes at the beginning of the path
1149                 while (*p == '\\' || *p == '/') {
1150                         p++;
1151                 }
1152                 strcat(tmp, p);
1153         }
1154         else {
1155                 BLI_strncpy(tmp, path, FILE_MAX);
1156         }
1157 #else
1158         BLI_strncpy(tmp, path, FILE_MAX);
1159 #endif
1160
1161         BLI_strncpy(base, basepath, FILE_MAX);
1162         
1163         BLI_cleanup_file(NULL, base);
1164         
1165         /* push slashes into unix mode - strings entering this part are
1166            potentially messed up: having both back- and forward slashes.
1167            Here we push into one conform direction, and at the end we
1168            push them into the system specific dir. This ensures uniformity
1169            of paths and solving some problems (and prevent potential future
1170            ones) -jesterKing. */
1171         BLI_char_switch(tmp, '\\', '/');
1172         BLI_char_switch(base, '\\', '/');       
1173
1174         /* Paths starting with // will get the blend file as their base,
1175          * this isnt standard in any os but is uesed in blender all over the place */
1176         if (wasrelative) {
1177                 char *lslash= BLI_last_slash(base);
1178                 if (lslash) {
1179                         int baselen= (int) (lslash-base) + 1;
1180                         /* use path for for temp storage here, we copy back over it right away */
1181                         BLI_strncpy(path, tmp+2, FILE_MAX);
1182                         
1183                         memcpy(tmp, base, baselen);
1184                         strcpy(tmp+baselen, path);
1185                         strcpy(path, tmp);
1186                 } else {
1187                         strcpy(path, tmp+2);
1188                 }
1189         } else {
1190                 strcpy(path, tmp);
1191         }
1192         
1193         if (path[0]!='\0') {
1194                 if ( path[strlen(path)-1]=='/') {
1195                         BLI_cleanup_dir(NULL, path);
1196                 } else {
1197                         BLI_cleanup_file(NULL, path);
1198                 }
1199         }
1200         
1201 #ifdef WIN32
1202         /* skip first two chars, which in case of
1203            absolute path will be drive:/blabla and
1204            in case of relpath //blabla/. So relpath
1205            // will be retained, rest will be nice and
1206            shiny win32 backward slashes :) -jesterKing
1207         */
1208         BLI_char_switch(path+2, '/', '\\');
1209 #endif
1210         
1211         return wasrelative;
1212 }
1213
1214 /* copy di to fi, filename only */
1215 void BLI_splitdirstring(char *di, char *fi)
1216 {
1217         char *lslash= BLI_last_slash(di);
1218
1219         if (lslash) {
1220                 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
1221                 *(lslash+1)=0;
1222         } else {
1223                 BLI_strncpy(fi, di, FILE_MAXFILE);
1224                 di[0]= 0;
1225         }
1226 }
1227
1228 char *BLI_gethome(void) {
1229         #ifdef __BeOS
1230                 return "/boot/home/";           /* BeOS 4.5: doubleclick at icon doesnt give home env */
1231
1232         #elif !defined(WIN32)
1233                 return getenv("HOME");
1234
1235         #else /* Windows */
1236                 char * ret;
1237                 static char dir[512];
1238                 static char appdatapath[MAXPATHLEN];
1239                 HRESULT hResult;
1240
1241                 /* Check for %HOME% env var */
1242
1243                 ret = getenv("HOME");
1244                 if(ret) {
1245                         sprintf(dir, "%s\\.blender", ret);
1246                         if (BLI_exists(dir)) return dir;
1247                 }
1248
1249                 /* else, check install dir (path containing blender.exe) */
1250
1251                 BLI_getInstallationDir(dir);
1252
1253                 if (BLI_exists(dir))
1254                 {
1255                         strcat(dir,"\\.blender");
1256                         if (BLI_exists(dir)) return(dir);
1257                 }
1258
1259                                 
1260                 /* add user profile support for WIN 2K / NT */
1261                 hResult = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdatapath);
1262                 
1263                 if (hResult == S_OK)
1264                 {
1265                         if (BLI_exists(appdatapath)) { /* from fop, also below... */
1266                                 sprintf(dir, "%s\\Blender Foundation\\Blender", appdatapath);
1267                                 BLI_recurdir_fileops(dir);
1268                                 if (BLI_exists(dir)) {
1269                                         strcat(dir,"\\.blender");
1270                                         if(BLI_exists(dir)) return(dir);
1271                                 }
1272                         }
1273                         hResult = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdatapath);
1274                         if (hResult == S_OK)
1275                         {
1276                                 if (BLI_exists(appdatapath)) 
1277                                 { /* from fop, also below... */
1278                                         sprintf(dir, "%s\\Blender Foundation\\Blender", appdatapath);
1279                                         BLI_recurdir_fileops(dir);
1280                                         if (BLI_exists(dir)) {
1281                                                 strcat(dir,"\\.blender");
1282                                                 if(BLI_exists(dir)) return(dir);
1283                                         }
1284                                 }
1285                         }
1286                 }
1287 #if 0
1288                 ret = getenv("USERPROFILE");
1289                 if (ret) {
1290                         if (BLI_exists(ret)) { /* from fop, also below...  */
1291                                 sprintf(dir, "%s\\Application Data\\Blender Foundation\\Blender", ret);
1292                                 BLI_recurdir_fileops(dir);
1293                                 if (BLI_exists(dir)) {
1294                                         strcat(dir,"\\.blender");
1295                                         if(BLI_exists(dir)) return(dir);
1296                                 }
1297                         }
1298                 }
1299 #endif
1300
1301                 /* 
1302                    Saving in the Windows dir is less than desirable. 
1303                    Use as a last resort ONLY! (aphex)
1304                 */
1305                 
1306                 ret = getenv("WINDOWS");                
1307                 if (ret) {
1308                         if(BLI_exists(ret)) return ret;
1309                 }
1310
1311                 ret = getenv("WINDIR"); 
1312                 if (ret) {
1313                         if(BLI_exists(ret)) return ret;
1314                 }
1315                 
1316                 return "C:\\Temp";      /* sheesh! bad, bad, bad! (aphex) */
1317         #endif
1318 }
1319
1320 void BLI_clean(char *path)
1321 {
1322         if(path==0) return;
1323 #ifdef WIN32
1324         if(path && strlen(path)>2) {
1325                 BLI_char_switch(path+2, '/', '\\');
1326         }
1327 #else
1328         BLI_char_switch(path, '\\', '/');
1329 #endif
1330 }
1331
1332 void BLI_char_switch(char *string, char from, char to) 
1333 {
1334         if(string==0) return;
1335         while (*string != 0) {
1336                 if (*string == from) *string = to;
1337                 string++;
1338         }
1339 }
1340
1341 void BLI_make_exist(char *dir) {
1342         int a;
1343
1344         #ifdef WIN32
1345                 BLI_char_switch(dir, '/', '\\');
1346         #else
1347                 BLI_char_switch(dir, '\\', '/');
1348         #endif  
1349         
1350         a = strlen(dir);
1351         
1352 #ifdef WIN32    
1353         while(BLI_exists(dir) == 0){
1354                 a --;
1355                 while(dir[a] != '\\'){
1356                         a--;
1357                         if (a <= 0) break;
1358                 }
1359                 if (a >= 0) dir[a+1] = 0;
1360                 else {
1361                         /* defaulting to drive (usually 'C:') of Windows installation */
1362                         get_default_root(dir);
1363                         break;
1364                 }
1365         }
1366 #else
1367         while(BLI_exist(dir) == 0){
1368                 a --;
1369                 while(dir[a] != '/'){
1370                         a--;
1371                         if (a <= 0) break;
1372                 }
1373                 if (a >= 0) dir[a+1] = 0;
1374                 else {
1375                         strcpy(dir,"/");
1376                         break;
1377                 }
1378         }
1379 #endif
1380 }
1381
1382 void BLI_make_existing_file(char *name)
1383 {
1384         char di[FILE_MAXDIR], fi[FILE_MAXFILE];
1385         
1386         strcpy(di, name);
1387         BLI_splitdirstring(di, fi);
1388         
1389         /* test exist */
1390         if (BLI_exists(di) == 0) {
1391                 BLI_recurdir_fileops(di);
1392         }
1393 }
1394
1395
1396 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
1397 {
1398         int sl;
1399
1400         if (!string || !dir || !file) return; /* We don't want any NULLs */
1401         
1402         string[0]= 0; /* ton */
1403
1404         /* we first push all slashes into unix mode, just to make sure we don't get
1405            any mess with slashes later on. -jesterKing */
1406         /* constant strings can be passed for those parameters - don't change them - elubie */
1407         /*
1408         BLI_char_switch(relabase, '\\', '/');
1409         BLI_char_switch(dir, '\\', '/');
1410         BLI_char_switch(file, '\\', '/');
1411         */
1412
1413         /* Resolve relative references */       
1414         if (relabase && dir[0] == '/' && dir[1] == '/') {
1415                 char *lslash;
1416                 
1417                 /* Get the file name, chop everything past the last slash (ie. the filename) */
1418                 strcpy(string, relabase);
1419                 
1420                 lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\');
1421                 
1422                 if(lslash) *(lslash+1)= 0;
1423
1424                 dir+=2; /* Skip over the relative reference */
1425         }
1426 #ifdef WIN32
1427         else {
1428                 if (strlen(dir) >= 2 && dir[1] == ':' ) {
1429                         BLI_strncpy(string, dir, 3);
1430                         dir += 2;
1431                 }
1432                 else { /* no drive specified */
1433                         /* first option: get the drive from the relabase if it has one */
1434                         if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1435                                 BLI_strncpy(string, relabase, 3);       
1436                                 string[2] = '\\';
1437                                 string[3] = '\0';
1438                         }
1439                         else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1440                                 get_default_root(string);
1441                         }
1442                         
1443                         /* ignore leading slashes */
1444                         while (*dir == '/' || *dir == '\\') dir++;
1445                 }
1446         }
1447 #endif
1448
1449         strcat(string, dir);
1450
1451         /* Make sure string ends in one (and only one) slash */ 
1452         /* first trim all slashes from the end of the string */
1453         sl = strlen(string);
1454         while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1455                 string[sl-1] = '\0';
1456                 sl--;
1457         }
1458         /* since we've now removed all slashes, put back one slash at the end. */
1459         strcat(string, "/");
1460         
1461         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1462                 file++;
1463                 
1464         strcat (string, file);
1465         
1466         /* Push all slashes to the system preferred direction */
1467         BLI_clean(string);
1468 }
1469
1470 int BLI_testextensie(const char *str, const char *ext)
1471 {
1472         short a, b;
1473         int retval;
1474
1475         a= strlen(str);
1476         b= strlen(ext);
1477
1478         if(a==0 || b==0 || b>=a) {
1479                 retval = 0;
1480         } else if (BLI_strcasecmp(ext, str + a - b)) {
1481                 retval = 0;     
1482         } else {
1483                 retval = 1;
1484         }
1485
1486         return (retval);
1487 }
1488
1489 /*
1490  * This is a simple version of BLI_split_dirfile that has the following advantages...
1491  * 
1492  * Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1493  * - wont change 'string'
1494  * - wont create any directories
1495  * - dosnt use CWD, or deal with relative paths.
1496  * - Only fill's in *dir and *file when they are non NULL
1497  * */
1498 void BLI_split_dirfile_basic(const char *string, char *dir, char *file)
1499 {
1500         int lslash=0, i = 0;
1501         for (i=0; string[i]!='\0'; i++) {
1502                 if (string[i]=='\\' || string[i]=='/')
1503                         lslash = i+1;
1504         }
1505         if (dir) {
1506                 if (lslash) {
1507                         BLI_strncpy( dir, string, lslash+1); /* +1 to include the slash and the last char */
1508                 } else {
1509                         dir[0] = '\0';
1510                 }
1511         }
1512         
1513         if (file) {
1514                 strcpy( file, string+lslash);
1515         }
1516 }
1517
1518
1519 /* Warning,
1520  * - May modify 'string' variable
1521  * - May create the directory if it dosnt exist
1522  * if this is not needed use BLI_split_dirfile_basic(...)
1523  */
1524 void BLI_split_dirfile(char *string, char *dir, char *file)
1525 {
1526         int a;
1527 #ifdef WIN32
1528         int sl;
1529         short is_relative = 0;
1530         char path[FILE_MAX];
1531 #endif
1532
1533         dir[0]= 0;
1534         file[0]= 0;
1535
1536 #ifdef WIN32
1537         BLI_strncpy(path, string, FILE_MAX);
1538         BLI_char_switch(path, '/', '\\'); /* make sure we have a valid path format */
1539         sl = strlen(path);
1540         if (sl) {
1541                 int len;
1542                 if (path[0] == '/' || path[0] == '\\') { 
1543                         BLI_strncpy(dir, path, FILE_MAXDIR);
1544                         if (sl > 1 && path[0] == '\\' && path[1] == '\\') is_relative = 1;
1545                 } else if (sl > 2 && path[1] == ':' && path[2] == '\\') {
1546                         BLI_strncpy(dir, path, FILE_MAXDIR);
1547                 } else {
1548                         BLI_getwdN(dir);
1549                         strcat(dir,"\\");
1550                         strcat(dir,path);
1551                         BLI_strncpy(path,dir,FILE_MAXDIR+FILE_MAXFILE);
1552                 }
1553                 
1554                 // BLI_exist doesn't recognize a slashed dirname as a dir
1555                 //  check if a trailing slash exists, and remove it. Do not do this
1556                 //  when we are already at root. -jesterKing
1557                 a = strlen(dir);
1558                 if(a>=4 && dir[a-1]=='\\') dir[a-1] = 0;
1559
1560                 if (is_relative) {
1561                         printf("WARNING: BLI_split_dirfile needs absolute dir\n");
1562                 }
1563                 else {
1564                         BLI_make_exist(dir);
1565                 }
1566
1567                 if (S_ISDIR(BLI_exist(dir))) {
1568
1569                         /* copy from end of string into file, to ensure filename itself isn't truncated 
1570                         if string is too long. (aphex) */
1571
1572                         len = FILE_MAXFILE - strlen(path);
1573
1574                         if (len < 0)
1575                                 BLI_strncpy(file,path + abs(len),FILE_MAXFILE);
1576                         else
1577                                 BLI_strncpy(file,path,FILE_MAXFILE);
1578                     
1579                         if (strrchr(path,'\\')) {
1580                                 BLI_strncpy(file,strrchr(path,'\\')+1,FILE_MAXFILE);
1581                         }
1582                         
1583                         if ( (a = strlen(dir)) ) {
1584                                 if (dir[a-1] != '\\') strcat(dir,"\\");
1585                         }
1586                 }
1587                 else {
1588                         a = strlen(dir) - 1;
1589                         while(a>0 && dir[a] != '\\') a--;
1590                         dir[a + 1] = 0;
1591                         BLI_strncpy(file, path + strlen(dir),FILE_MAXFILE);
1592                 }
1593
1594         }
1595         else {
1596                 /* defaulting to first valid drive hoping it's not empty CD and DVD drives */
1597                 get_default_root(dir);
1598                 file[0]=0;
1599         }
1600 #else
1601         if (strlen(string)) {
1602                 if (string[0] == '/') { 
1603                         strcpy(dir, string);
1604                 } else if (string[1] == ':' && string[2] == '\\') {
1605                         string+=2;
1606                         strcpy(dir, string);
1607                 } else {
1608                         BLI_getwdN(dir);
1609                         strcat(dir,"/");
1610                         strcat(dir,string);
1611                         strcpy((char *)string,dir);
1612                 }
1613
1614                 BLI_make_exist(dir);
1615                         
1616                 if (S_ISDIR(BLI_exist(dir))) {
1617                         strcpy(file,string + strlen(dir));
1618
1619                         if (strrchr(file,'/')) strcpy(file,strrchr(file,'/')+1);
1620                 
1621                         if ( (a = strlen(dir)) ) {
1622                                 if (dir[a-1] != '/') strcat(dir,"/");
1623                         }
1624                 }
1625                 else {
1626                         a = strlen(dir) - 1;
1627                         while(dir[a] != '/') a--;
1628                         dir[a + 1] = 0;
1629                         strcpy(file, string + strlen(dir));
1630                 }
1631         }
1632         else {
1633                 BLI_getwdN(dir);
1634                 strcat(dir, "/");
1635                 file[0] = 0;
1636         }
1637 #endif
1638 }
1639
1640 /* simple appending of filename to dir, does not check for valid path! */
1641 void BLI_join_dirfile(char *string, const char *dir, const char *file)
1642 {
1643         int sl_dir = strlen(dir);
1644         BLI_strncpy(string, dir, FILE_MAX);
1645         if (sl_dir > FILE_MAX-1) sl_dir = FILE_MAX-1;
1646         
1647         /* only add seperator if needed */
1648 #ifdef WIN32
1649         if (string[sl_dir-1] != '\\') {
1650                 string[sl_dir] = '\\';
1651                 sl_dir++;
1652         }
1653 #else
1654         if (string[sl_dir-1] != '/') {
1655                 string[sl_dir] = '/';
1656                 sl_dir++;
1657         }
1658 #endif
1659         
1660         if (sl_dir <FILE_MAX) {
1661                 BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
1662         }
1663 }
1664
1665 static int add_win32_extension(char *name)
1666 {
1667         int retval = 0;
1668         int type;
1669
1670         type = BLI_exist(name);
1671         if ((type == 0) || S_ISDIR(type)) {
1672 #ifdef _WIN32
1673                 char filename[FILE_MAXDIR+FILE_MAXFILE];
1674                 char ext[FILE_MAXDIR+FILE_MAXFILE];
1675                 char *extensions = getenv("PATHEXT");
1676                 if (extensions) {
1677                         char *temp;
1678                         do {
1679                                 strcpy(filename, name);
1680                                 temp = strstr(extensions, ";");
1681                                 if (temp) {
1682                                         strncpy(ext, extensions, temp - extensions);
1683                                         ext[temp - extensions] = 0;
1684                                         extensions = temp + 1;
1685                                         strcat(filename, ext);
1686                                 } else {
1687                                         strcat(filename, extensions);
1688                                 }
1689
1690                                 type = BLI_exist(filename);
1691                                 if (type && (! S_ISDIR(type))) {
1692                                         retval = 1;
1693                                         strcpy(name, filename);
1694                                         break;
1695                                 }
1696                         } while (temp);
1697                 }
1698 #endif
1699         } else {
1700                 retval = 1;
1701         }
1702
1703         return (retval);
1704 }
1705
1706 void BLI_where_am_i(char *fullname, const char *name)
1707 {
1708         char filename[FILE_MAXDIR+FILE_MAXFILE];
1709         char *path = NULL, *temp;
1710         int len;
1711 #ifdef _WIN32
1712         char *seperator = ";";
1713         char *slash = "\\";
1714 #else
1715         char *seperator = ":";
1716         char *slash = "/";
1717 #endif
1718
1719         
1720 #ifdef __linux__
1721         /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */
1722         path = br_find_exe( NULL );
1723         if (path) {
1724                 strcpy(fullname, path);
1725                 free(path);
1726                 return;
1727         }
1728 #endif
1729         
1730         /* unix and non linux */
1731         if (name && fullname && strlen(name)) {
1732                 strcpy(fullname, name);
1733                 if (name[0] == '.') {
1734                         // relative path, prepend cwd
1735                         BLI_getwdN(fullname);
1736                         len = strlen(fullname);
1737                         if (len && fullname[len -1] != slash[0]) {
1738                                 strcat(fullname, slash);
1739                         }
1740                         strcat(fullname, name);
1741                         add_win32_extension(fullname);
1742                 } else if (BLI_last_slash(name)) {
1743                         // full path
1744                         strcpy(fullname, name);
1745                         add_win32_extension(fullname);
1746                 } else {
1747                         // search for binary in $PATH
1748                         path = getenv("PATH");
1749                         if (path) {
1750                                 do {
1751                                         temp = strstr(path, seperator);
1752                                         if (temp) {
1753                                                 strncpy(filename, path, temp - path);
1754                                                 filename[temp - path] = 0;
1755                                                 path = temp + 1;
1756                                         } else {
1757                                                 strncpy(filename, path, sizeof(filename));
1758                                         }
1759                                         len = strlen(filename);
1760                                         if (len && filename[len - 1] != slash[0]) {
1761                                                 strcat(filename, slash);
1762                                         }
1763                                         strcat(filename, name);
1764                                         if (add_win32_extension(filename)) {
1765                                                 strcpy(fullname, filename);
1766                                                 break;
1767                                         }
1768                                 } while (temp);
1769                         }
1770                 }
1771 #ifndef NDEBUG
1772                 if (strcmp(name, fullname)) {
1773                         printf("guessing '%s' == '%s'\n", name, fullname);
1774                 }
1775 #endif
1776
1777 #ifdef _WIN32
1778                 // in windows change long filename to short filename because
1779                 // win2k doesn't know how to parse a commandline with lots of
1780                 // spaces and double-quotes. There's another solution to this
1781                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
1782                 // that's even uglier
1783                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
1784 #ifndef NDEBUG
1785                 printf("Shortname = '%s'\n", fullname);
1786 #endif
1787 #endif
1788         }
1789 }
1790
1791 void BLI_where_is_temp(char *fullname, int usertemp)
1792 {
1793         fullname[0] = '\0';
1794         
1795         if (usertemp && BLI_exists(U.tempdir)) {
1796                 strcpy(fullname, U.tempdir);
1797         }
1798         
1799         
1800 #ifdef WIN32
1801         if (fullname[0] == '\0') {
1802                 char *tmp = getenv("TEMP"); /* Windows */
1803                 if (tmp && BLI_exists(tmp)) {
1804                         strcpy(fullname, tmp);
1805                 }
1806         }
1807 #else
1808         /* Other OS's - Try TMP and TMPDIR */
1809         if (fullname[0] == '\0') {
1810                 char *tmp = getenv("TMP");
1811                 if (tmp && BLI_exists(tmp)) {
1812                         strcpy(fullname, tmp);
1813                 }
1814         }
1815         
1816         if (fullname[0] == '\0') {
1817                 char *tmp = getenv("TMPDIR");
1818                 if (tmp && BLI_exists(tmp)) {
1819                         strcpy(fullname, tmp);
1820                 }
1821         }
1822 #endif  
1823         
1824         if (fullname[0] == '\0') {
1825                 strcpy(fullname, "/tmp/");
1826         } else {
1827                 /* add a trailing slash if needed */
1828                 BLI_add_slash(fullname);
1829         }
1830 }
1831
1832 /* 
1833  * returns absolute path to the app bundle
1834  * only useful on OS X 
1835  */
1836 #ifdef __APPLE__
1837 char* BLI_getbundle(void) {
1838         CFURLRef bundleURL;
1839         CFStringRef pathStr;
1840         static char path[MAXPATHLEN];
1841         CFBundleRef mainBundle = CFBundleGetMainBundle();
1842
1843         bundleURL = CFBundleCopyBundleURL(mainBundle);
1844         pathStr = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
1845         CFStringGetCString(pathStr, path, MAXPATHLEN, kCFStringEncodingASCII);
1846         return path;
1847 }
1848 #endif
1849
1850 /* strcasestr not available in MSVC */
1851 char *BLI_strcasestr(const char *s, const char *find)
1852 {
1853     register char c, sc;
1854     register size_t len;
1855         
1856     if ((c = *find++) != 0) {
1857                 c= tolower(c);
1858                 len = strlen(find);
1859                 do {
1860                         do {
1861                                 if ((sc = *s++) == 0)
1862                                         return (NULL);
1863                                 sc= tolower(sc);
1864                         } while (sc != c);
1865                 } while (BLI_strncasecmp(s, find, len) != 0);
1866                 s--;
1867     }
1868     return ((char *) s);
1869 }
1870
1871
1872 int BLI_strcasecmp(const char *s1, const char *s2) {
1873         int i;
1874
1875         for (i=0; ; i++) {
1876                 char c1 = tolower(s1[i]);
1877                 char c2 = tolower(s2[i]);
1878
1879                 if (c1<c2) {
1880                         return -1;
1881                 } else if (c1>c2) {
1882                         return 1;
1883                 } else if (c1==0) {
1884                         break;
1885                 }
1886         }
1887
1888         return 0;
1889 }
1890
1891 int BLI_strncasecmp(const char *s1, const char *s2, int n) {
1892         int i;
1893
1894         for (i=0; i<n; i++) {
1895                 char c1 = tolower(s1[i]);
1896                 char c2 = tolower(s2[i]);
1897
1898                 if (c1<c2) {
1899                         return -1;
1900                 } else if (c1>c2) {
1901                         return 1;
1902                 } else if (c1==0) {
1903                         break;
1904                 }
1905         }
1906
1907         return 0;
1908 }
1909
1910
1911 #ifdef WITH_ICONV
1912 #include "iconv.h"
1913 #include "localcharset.h"
1914
1915 void BLI_string_to_utf8(char *original, char *utf_8, char *code)
1916 {
1917         size_t inbytesleft=strlen(original);
1918         size_t outbytesleft=512;
1919         size_t rv=0;
1920         iconv_t cd;
1921         
1922         if (NULL == code) {
1923                 code = locale_charset();
1924         }
1925         cd=iconv_open("UTF-8", code);
1926
1927         if (cd == (iconv_t)(-1)) {
1928                 printf("iconv_open Error");
1929                 *utf_8='\0';
1930                 return ;
1931         }
1932         rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1933         if (rv == (size_t) -1) {
1934                 printf("iconv Error\n");
1935                 return ;
1936         }
1937         *utf_8 = '\0';
1938         iconv_close(cd);
1939 }
1940 #endif // WITH_ICONV
1941
1942 void BLI_timestr(double _time, char *str)
1943 {
1944         /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */
1945         int  hr= ( (int)  _time) / (60*60);
1946         int min= (((int)  _time) / 60 ) % 60;
1947         int sec= ( (int) (_time)) % 60;
1948         int hun= ( (int) (_time   * 100.0)) % 100;
1949         
1950         if (hr) {
1951                 sprintf(str, "%.2d:%.2d:%.2d.%.2d",hr,min,sec,hun);
1952         } else {
1953                 sprintf(str, "%.2d:%.2d.%.2d",min,sec,hun);
1954         }
1955         
1956         str[11]=0;
1957 }
1958
1959 /* ************** 64 bits magic, trick to support up to 32 gig of address space *************** */
1960 /*                only works for malloced pointers (8 aligned)                   */
1961
1962 #ifdef __LP64__ 
1963
1964 #if defined(WIN32) && !defined(FREE_WINDOWS)
1965 #define PMASK           0x07FFFFFFFFi64
1966 #else
1967 #define PMASK           0x07FFFFFFFFll
1968 #endif
1969
1970
1971 int BLI_int_from_pointer(void *poin)
1972 {
1973         long lval= (long)poin;
1974         
1975         return (int)(lval>>3);
1976 }
1977
1978 void *BLI_pointer_from_int(int val)
1979 {
1980         static int firsttime= 1;
1981         static long basevalue= 0;
1982         
1983         if(firsttime) {
1984                 void *poin= malloc(10000);
1985                 basevalue= (long)poin;
1986                 basevalue &= ~PMASK;
1987                 printf("base: %d pointer %p\n", basevalue, poin); /* debug */
1988                 firsttime= 0;
1989                 free(poin);
1990         }
1991         return (void *)(basevalue | (((long)val)<<3));
1992 }
1993
1994 #else
1995
1996 int BLI_int_from_pointer(void *poin)
1997 {
1998         return (int)poin;
1999 }
2000 void *BLI_pointer_from_int(int val)
2001 {
2002         return (void *)val;
2003 }
2004
2005 #endif
2006