- replaced G.{edve,eded,edvl} with G.editMesh, atm just a structure to
[blender.git] / source / blender / blenlib / intern / util.c
1 /* util.c
2  *
3  * various string, file, list operations.
4  *
5  *
6  * $Id$
7  *
8  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version. The Blender
14  * Foundation also sells licenses for use in proprietary software under
15  * the Blender License.  See http://www.blender.org/BL/ for information
16  * about this.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  *
27  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
28  * All rights reserved.
29  *
30  * The Original Code is: all of this file.
31  *
32  * Contributor(s): none yet.
33  *
34  * ***** END GPL/BL DUAL LICENSE BLOCK *****
35  * 
36  */
37
38 #include <stdio.h>
39 #include <fcntl.h>
40 #include <ctype.h>
41 #include <string.h>
42 #include <stdlib.h>
43
44 #include "MEM_guardedalloc.h"
45
46 #include "BLI_blenlib.h"
47 #include "DNA_listBase.h"
48 #include "BLI_storage.h"
49 #include "BLI_storage_types.h"
50
51 #include "BLI_util.h"
52
53 #ifdef HAVE_CONFIG_H
54 #include <config.h>
55 #endif
56
57 #ifndef WIN32 
58 #include <unistd.h>
59 #else
60 #include <io.h>
61 #endif
62
63 #ifdef WIN32
64 #include "BLI_winstuff.h"
65 #endif
66
67
68 #ifndef WIN32
69 #include <sys/time.h>
70 #endif
71
72 #ifdef __APPLE__
73 #include <sys/param.h>
74 #include <CoreFoundation/CoreFoundation.h>
75 #endif
76
77 /* local */
78
79 static int add_win32_extension(char *name);
80
81 /* implementation */
82
83 /* Ripped this from blender.c
84  */
85 void addlisttolist(ListBase *list1, ListBase *list2)
86 {
87
88         if(list2->first==0) return;
89
90         if(list1->first==0) {
91                 list1->first= list2->first;
92                 list1->last= list2->last;
93         }
94         else {
95                 ((struct Link *)list1->last)->next= list2->first;
96                 ((struct Link *)list2->first)->prev= list1->last;
97                 list1->last= list2->last;
98         }
99         list2->first= list2->last= 0;
100 }
101
102 int BLI_stringdec(char *string, char *kop, char *staart, unsigned short *numlen)
103 {
104         unsigned short len, len2, nums = 0, nume = 0;
105         short i, found = 0;
106
107         len2 = len =  strlen( string);
108         
109         if (len > 6) {
110                 if (strncasecmp(string + len - 6, ".blend", 6) == 0) len -= 6;
111                 else if (strncasecmp(string + len - 6, ".trace", 6) == 0) len -= 6;
112         }
113         
114         if (len == len2) {
115                 if (len > 4) {
116                         /* handle .jf0 en .jf1 for jstreams */
117                         if (strncasecmp(string + len - 4, ".jf", 3) == 0) len -= 4;
118                         else if (strncasecmp(string + len - 4, ".tga", 4) == 0) len -= 4;
119                         else if (strncasecmp(string + len - 4, ".jpg", 4) == 0) len -= 4;
120                         else if (strncasecmp(string + len - 4, ".png", 4) == 0) len -= 4;
121                         else if (strncasecmp(string + len - 4, ".txt", 4) == 0) len -= 4;
122                         else if (strncasecmp(string + len - 4, ".cyc", 4) == 0) len -= 4;
123                         else if (strncasecmp(string + len - 4, ".enh", 4) == 0) len -= 4;
124                         else if (strncasecmp(string + len - 4, ".rgb", 4) == 0) len -= 4;
125                         else if (strncasecmp(string + len - 4, ".psx", 4) == 0) len -= 4;
126                         else if (strncasecmp(string + len - 4, ".ble", 4) == 0) len -= 4;
127                 }
128         }
129         
130         for (i = len - 1; i >= 0; i--){
131                 if (string[i] == '/') break;
132                 if (isdigit(string[i])) {
133                         if (found){
134                                 nums = i;
135                         }
136                         else{
137                                 nume = i;
138                                 nums = i;
139                                 found = 1;
140                         }
141                 }
142                 else{
143                         if (found) break;
144                 }
145         }
146         if (found){
147                 if (staart) strcpy(staart,&string[nume+1]);
148                 if (kop) {
149                         strcpy(kop,string);
150                         kop[nums]=0;
151                 }
152                 if (numlen) *numlen = nume-nums+1;
153                 return ((int)atoi(&(string[nums])));
154         }
155         if (staart) strcpy(staart, string + len);
156         if (kop) {
157                 strncpy(kop, string, len);
158                 kop[len] = 0;
159         }
160         if (numlen) *numlen=0;
161         return 0;
162 }
163
164
165 void BLI_stringenc(char *string, char *kop, char *staart, unsigned short numlen, int pic)
166 {
167         char numstr[10]="";
168         unsigned short len,i;
169
170         strcpy(string,kop);
171         
172         if (pic>0 || numlen==4) {
173                 len= sprintf(numstr,"%d",pic);
174
175                 for(i=len;i<numlen;i++){
176                         strcat(string,"0");
177                 }
178                 strcat(string,numstr);
179         }
180         strcat(string,staart);
181 }
182
183
184 void BLI_newname(char * name, int add)
185 {
186         char head[128], tail[128];
187         int pic;
188         unsigned short digits;
189         
190         pic = BLI_stringdec(name, head, tail, &digits);
191         
192         /* are we going from 100 -> 99 or from 10 -> 9 */
193         if (add < 0 && digits < 4 && digits > 0) {
194                 int i, exp;
195                 exp = 1;
196                 for (i = digits; i > 1; i--) exp *= 10;
197                 if (pic >= exp && (pic + add) < exp) digits--;
198         }
199         
200         pic += add;
201         
202         if(digits==4 && pic<0) pic= 0;
203         BLI_stringenc(name, head, tail, digits, pic);
204 }
205
206
207 void BLI_addhead(ListBase *listbase, void *vlink)
208 {
209         struct Link *link= vlink;
210
211         if (link == 0) return;
212         if (listbase == 0) return;
213
214         link->next = listbase->first;
215         link->prev = 0;
216
217         if (listbase->first) ((struct Link *)listbase->first)->prev = link;
218         if (listbase->last == 0) listbase->last = link;
219         listbase->first = link;
220 }
221
222
223 void BLI_addtail(ListBase *listbase, void *vlink)
224 {
225         struct Link *link= vlink;
226
227         if (link == 0) return;
228         if (listbase == 0) return;
229
230         link->next = 0;
231         link->prev = listbase->last;
232
233         if (listbase->last) ((struct Link *)listbase->last)->next = link;
234         if (listbase->first == 0) listbase->first = link;
235         listbase->last = link;
236 }
237
238
239 void BLI_remlink(ListBase *listbase, void *vlink)
240 {
241         struct Link *link= vlink;
242
243         if (link == 0) return;
244         if (listbase == 0) return;
245
246         if (link->next) link->next->prev = link->prev;
247         if (link->prev) link->prev->next = link->next;
248
249         if (listbase->last == link) listbase->last = link->prev;
250         if (listbase->first == link) listbase->first = link->next;
251 }
252
253
254 void BLI_freelinkN(ListBase *listbase, void *vlink)
255 {
256         struct Link *link= vlink;
257
258         if (link == 0) return;
259         if (listbase == 0) return;
260
261         BLI_remlink(listbase,link);
262         MEM_freeN(link);
263 }
264
265
266 void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink)
267 {
268         struct Link *prevlink= vprevlink, *newlink= vnewlink;
269
270         /* newlink comes after prevlink */
271
272         if (newlink == 0) return;
273         if (listbase == 0) return;
274
275         if(listbase->first==0) { /* empty list */
276                 listbase->first= newlink;
277                 listbase->last= newlink;
278                 return;
279         }
280         if (prevlink== 0) {     /* insert before first element */
281                 newlink->next= listbase->first;
282                 newlink->prev= 0;
283                 newlink->next->prev= newlink;
284                 listbase->first= newlink;
285                 return;
286         }
287
288         if (listbase->last== prevlink) /* at end of list */
289                 listbase->last = newlink;
290
291         newlink->next= prevlink->next;
292         prevlink->next= newlink;
293         if(newlink->next) newlink->next->prev= newlink;
294         newlink->prev= prevlink;
295 }
296
297 void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
298 {
299         struct Link *nextlink= vnextlink, *newlink= vnewlink;
300
301         /* newlink before nextlink */
302
303         if (newlink == 0) return;
304         if (listbase == 0) return;
305
306         if(listbase->first==0) { /* empty list */
307                 listbase->first= newlink;
308                 listbase->last= newlink;
309                 return;
310         }
311         if (nextlink== 0) {     /* insert at end of list */
312                 newlink->prev= listbase->last;
313                 newlink->next= 0;
314                 ((struct Link *)listbase->last)->next= newlink;
315                 listbase->last= newlink;
316                 return;
317         }
318
319         if (listbase->first== nextlink) /* at beginning of list */
320                 listbase->first = newlink;
321
322         newlink->next= nextlink;
323         newlink->prev= nextlink->prev;
324         nextlink->prev= newlink;
325         if(newlink->prev) newlink->prev->next= newlink;
326 }
327
328
329 void BLI_freelist(ListBase *listbase)
330 {
331         struct Link *link,*next;
332
333         if (listbase == 0) return;
334         link= listbase->first;
335         while(link) {
336                 next= link->next;
337                 free(link);
338                 link= next;
339         }
340         listbase->first=0;
341         listbase->last=0;
342 }
343
344 void BLI_freelistN(ListBase *listbase)
345 {
346         struct Link *link,*next;
347
348         if (listbase == 0) return;
349         link= listbase->first;
350         while(link) {
351                 next= link->next;
352                 MEM_freeN(link);
353                 link= next;
354         }
355         listbase->first=0;
356         listbase->last=0;
357 }
358
359
360 int BLI_countlist(ListBase *listbase)
361 {
362         Link * link;
363         int count = 0;
364         
365         if (listbase){
366                 link = listbase->first;
367                 while(link) {
368                         count++;
369                         link= link->next;
370                 }
371         }
372         return(count);
373 }
374
375 void * BLI_findlink(ListBase *listbase, int number)
376 {
377         Link * link = NULL;
378
379         if (number >= 0) {
380                 link = listbase->first;
381                 while (link != NULL && number != 0) {
382                         number--;
383                         link = link->next;
384                 }
385         }
386
387         return (link);
388 }
389
390
391 char *BLI_strdupn(char *str, int len) {
392         char *n= MEM_mallocN(len+1, "strdup");
393         memcpy(n, str, len);
394         n[len]= '\0';
395         
396         return n;
397 }
398 char *BLI_strdup(char *str) {
399         return BLI_strdupn(str, strlen(str));
400 }
401
402 char *BLI_strncpy(char *dst, char *src, int maxncpy) {
403         int srclen= strlen(src);
404         int cpylen= (srclen>(maxncpy-1))?(maxncpy-1):srclen;
405         
406         memcpy(dst, src, cpylen);
407         dst[cpylen]= '\0';
408         
409         return dst;
410 }
411
412 int BLI_streq(char *a, char *b) {
413         return (strcmp(a, b)==0);
414 }
415 int BLI_strcaseeq(char *a, char *b) {
416         return (strcasecmp(a, b)==0);
417 }
418
419 void BLI_makestringcode(char *fromfile, char *str)
420 {
421         char *slash, len, temp[512];
422
423         strcpy(temp, fromfile);
424
425         /* Find the last slash */
426         slash = (strrchr(temp, '/')>strrchr(temp, '\\'))
427             ? strrchr(temp, '/') : strrchr(temp, '\\');
428         if(slash) {
429                 *(slash+1)= 0;
430                 len= strlen(temp);
431                 if(len) {
432                         if(strncmp(str, temp, len)==0) {
433                                 temp[0]= '/';
434                                 temp[1]= '/';
435                                 strcpy(temp+2, str+len);
436                                 strcpy(str, temp);
437                         }
438                 }
439         }
440 }
441
442 int BLI_convertstringcode(char *path, char *basepath, int framenum)
443 {
444         int len, wasrelative= (strncmp(path, "//", 2)==0);
445
446         if (path[0] == '/' && path[1] == '/') {
447                 char *filepart= BLI_strdup(path+2); /* skip code */
448                 char *lslash= BLI_last_slash(basepath);
449
450                 if (lslash) {
451                         int baselen= (int) (lslash-basepath) + 1;
452
453                         memcpy(path, basepath, baselen);
454                         strcpy(path+baselen, filepart);
455                 } else {
456                         strcpy(path, filepart);
457                 }
458                 
459                 MEM_freeN(filepart);
460         }
461
462         len= strlen(path);
463         if(len && path[len-1]=='#') {
464                 sprintf(path+len-1, "%04d", framenum);
465         }
466
467         return wasrelative;
468 }
469
470 void BLI_splitdirstring(char *di,char *fi)
471 {
472         char *lslash= BLI_last_slash(di);
473
474         if (lslash) {
475                 strcpy(fi, lslash+1);
476                 *(lslash+1)=0;
477         } else {
478                 strcpy(fi, di);
479                 di[0]= 0;
480         }
481 }
482
483 char *BLI_gethome(void) {
484         
485         #ifdef __BeOS
486                 return "/boot/home/";           /* BeOS 4.5: doubleclick at icon doesnt give home env */
487
488         #elif !defined(WIN32)
489                 return getenv("HOME");
490
491         #else /* Windows */
492                 char * ret;
493                 static char dir[512];
494                 char tmpdir[512];
495
496                 ret = getenv("HOME");
497                 if(ret) {
498                         if (BLI_exists(ret)) return ret;
499                 }
500
501                 /* 
502                    "change-over" period - blender still checks in
503                    old locations, but Ctrl+U now saves in ~/.blender
504                 */
505
506                 BLI_getInstallationDir(dir);
507
508                 if (BLI_exists(dir))
509                 {
510                         strcat(dir,"/.blender");
511                         if (BLI_exists(dir)) return(dir);
512                 }
513
514                 /* 
515                    everything below this point to be removed -
516                    blender should use the same %HOME% across
517                    all versions of Windows... (aphex)
518                 */
519                                 
520                 /* add user profile support for WIN 2K / NT */
521                 ret = getenv("USERPROFILE");
522                 if (ret) {
523                         if (BLI_exists(ret)) { /* from fop, also below... */
524                                 sprintf(dir, "%s/Application Data/Not a Number/Blender", ret);
525                                 BLI_recurdir_fileops(dir);
526                                 if (BLI_exists(dir)) {
527                                         return(dir);
528                                 } else {
529                                         return(ret);
530                                 }
531                         }
532                 }
533
534                 /* 
535                    Saving in the Windows dir is less than desirable. 
536                    Use as a last resort ONLY! (aphex)
537                 */
538                 
539                 ret = getenv("WINDOWS");                
540                 if (ret) {
541                         if(BLI_exists(ret)) return ret;
542                 }
543
544                 ret = getenv("WINDIR"); 
545                 if (ret) {
546                         if(BLI_exists(ret)) return ret;
547                 }
548                 
549                 return "C:\\Temp";      /* sheesh! bad, bad, bad! (aphex) */
550         #endif
551 }
552
553 static void char_switch(char *string, char from, char to) 
554 {
555         while (*string != 0) {
556                 if (*string == from) *string = to;
557                 string++;
558         }
559 }
560
561 void BLI_make_exist(char *dir)
562 {
563         int a;
564
565         #ifdef WIN32
566                 char_switch(dir, '/', '\\');
567         #else
568                 char_switch(dir, '\\', '/');
569         #endif  
570         
571         a = strlen(dir);
572         
573 #ifdef WIN32    
574         while(BLI_exists(dir) == 0){
575                 a --;
576                 while(dir[a] != '\\'){
577                         a--;
578                         if (a <= 0) break;
579                 }
580                 if (a >= 0) dir[a+1] = 0;
581                 else {
582                         strcpy(dir,"\\");
583                         break;
584                 }
585         }
586 #else
587         while(BLI_exist(dir) == 0){
588                 a --;
589                 while(dir[a] != '/'){
590                         a--;
591                         if (a <= 0) break;
592                 }
593                 if (a >= 0) dir[a+1] = 0;
594                 else {
595                         strcpy(dir,"/");
596                         break;
597                 }
598         }
599 #endif
600 }
601
602 void BLI_make_file_string(char *relabase, char *string,  char *dir,  char *file)
603 {
604
605         if (!string || !dir || !file) return; /* We don't want any NULLs */
606         
607         string[0]= 0; /* ton */
608
609         /* Resolve relative references */       
610         if (relabase && dir[0] == '/' && dir[1] == '/') {
611                 char *lslash;
612                 
613                 /* Get the file name, chop everything past the last slash (ie. the filename) */
614                 strcpy(string, relabase);
615                 
616                 lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\');
617                 
618                 if(lslash) *(lslash+1)= 0;
619
620                 dir+=2; /* Skip over the relative reference */
621         }
622         
623         strcat(string, dir);
624
625         /* Make sure string ends in one (and only one) slash */
626         if (string[strlen(string)-1] != '/' && string[strlen(string)-1] != '\\')
627                 strcat(string, "/");
628         
629         while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
630                 file++;
631                 
632         strcat (string, file);
633         
634         /* Push all slashes to the system preferred direction */
635         #ifdef WIN32
636                 char_switch(string, '/', '\\');
637         #else
638                 char_switch(string, '\\', '/');
639         #endif  
640 }
641
642 int BLI_testextensie(char *str, char *ext)
643 {
644         short a, b;
645         int retval;
646
647         a= strlen(str);
648         b= strlen(ext);
649
650         if(a==0 || b==0 || b>=a) {
651                 retval = 0;
652         } else if (strcasecmp(ext, str + a - b)) {
653                 retval = 0;     
654         } else {
655                 retval = 1;
656         }
657
658         return (retval);
659 }
660
661 void BLI_split_dirfile(char *string, char *dir, char *file)
662 {
663         int a;
664         
665         dir[0]= 0;
666         file[0]= 0;
667
668 #ifdef WIN32
669         if (strlen(string)) {
670                 if (string[0] == '/' || string[0] == '\\') { 
671                         strcpy(dir, string);
672                 } else if (string[1] == ':' && string[2] == '\\') {
673             strcpy(dir, string);
674         } else {
675             BLI_getwdN(dir);
676             strcat(dir,"/");
677             strcat(dir,string);
678             strcpy(string,dir);
679         }
680
681         BLI_make_exist(dir);
682
683         // BLI_exist doesn't recognize a slashed dirname as a dir
684         //  check if a trailing slash exists, and remove it. Do not do this
685         //  when we are already at root. -jesterKing
686         a = strlen(dir);
687         if(a>=4 && dir[a-1]=='\\') dir[a-1] = 0;
688
689         if (S_ISDIR(BLI_exist(dir))) {
690             strcpy(file,string + strlen(dir));
691
692             if (strrchr(file,'\\')) strcpy(file,strrchr(file,'\\')+1);
693
694             if (a = strlen(dir)) {
695                 if (dir[a-1] != '\\') strcat(dir,"\\");
696             }
697                 }
698                 else {
699                         a = strlen(dir) - 1;
700                         while(a>0 && dir[a] != '\\') a--;
701                         dir[a + 1] = 0;
702                         strcpy(file, string + strlen(dir));
703                 }
704                 
705         }
706         else {
707                 strcpy(dir, "\\");
708                 file[0]=0;
709         }
710 #else
711         if (strlen(string)) {
712                 if (string[0] == '/') { 
713                         strcpy(dir, string);
714                 } else if (string[1] == ':' && string[2] == '\\') {
715                         string+=2;
716                         strcpy(dir, string);
717                 } else {
718                         BLI_getwdN(dir);
719                         strcat(dir,"/");
720                         strcat(dir,string);
721                         strcpy(string,dir);
722                 }
723
724                 BLI_make_exist(dir);
725                         
726                 if (S_ISDIR(BLI_exist(dir))) {
727                         strcpy(file,string + strlen(dir));
728
729                         if (strrchr(file,'/')) strcpy(file,strrchr(file,'/')+1);
730                 
731                         if ( (a = strlen(dir)) ) {
732                                 if (dir[a-1] != '/') strcat(dir,"/");
733                         }
734                 }
735                 else {
736                         a = strlen(dir) - 1;
737                         while(dir[a] != '/') a--;
738                         dir[a + 1] = 0;
739                         strcpy(file, string + strlen(dir));
740                 }
741         }
742         else {
743                 BLI_getwdN(dir);
744                 strcat(dir, "/");
745                 file[0] = 0;
746         }
747 #endif
748 }
749
750 // copies from BKE_utildefines
751 #ifndef FILE_MAXDIR
752 #define FILE_MAXDIR  160
753 #endif
754
755 #ifndef FILE_MAXFILE
756 #define FILE_MAXFILE 80
757 #endif
758  
759 static int add_win32_extension(char *name)
760 {
761         int retval = 0;
762         int type;
763
764         type = BLI_exist(name);
765         if ((type == 0) || S_ISDIR(type)) {
766 #ifdef _WIN32
767                 char filename[FILE_MAXDIR+FILE_MAXFILE];
768                 char ext[FILE_MAXDIR+FILE_MAXFILE];
769                 char *extensions = getenv("PATHEXT");
770                 if (extensions) {
771                         char *temp;
772                         do {
773                                 strcpy(filename, name);
774                                 temp = strstr(extensions, ";");
775                                 if (temp) {
776                                         strncpy(ext, extensions, temp - extensions);
777                                         ext[temp - extensions] = 0;
778                                         extensions = temp + 1;
779                                         strcat(filename, ext);
780                                 } else {
781                                         strcat(filename, extensions);
782                                 }
783
784                                 type = BLI_exist(filename);
785                                 if (type && (! S_ISDIR(type))) {
786                                         retval = 1;
787                                         strcpy(name, filename);
788                                         break;
789                                 }
790                         } while (temp);
791                 }
792 #endif
793         } else {
794                 retval = 1;
795         }
796
797         return (retval);
798 }
799
800 void BLI_where_am_i(char *fullname, char *name)
801 {
802         char filename[FILE_MAXDIR+FILE_MAXFILE];
803         char *path, *temp;
804         int len;
805 #ifdef _WIN32
806         char *seperator = ";";
807         char *slash = "\\";
808 #else
809         char *seperator = ":";
810         char *slash = "/";
811 #endif
812
813         if (name && fullname && strlen(name)) {
814                 strcpy(fullname, name);
815                 if (name[0] == '.') {
816                         // relative path, prepend cwd
817                         BLI_getwdN(fullname);
818                         len = strlen(fullname);
819                         if (len && fullname[len -1] != slash[0]) {
820                                 strcat(fullname, slash);
821                         }
822                         strcat(fullname, name);
823                         add_win32_extension(fullname);
824                 } else if (BLI_last_slash(name)) {
825                         // full path
826                         strcpy(fullname, name);
827                         add_win32_extension(fullname);
828                 } else {
829                         // search for binary in $PATH
830                         path = getenv("PATH");
831                         if (path) {
832                                 do {
833                                         temp = strstr(path, seperator);
834                                         if (temp) {
835                                                 strncpy(filename, path, temp - path);
836                                                 filename[temp - path] = 0;
837                                                 path = temp + 1;
838                                         } else {
839                                                 strncpy(filename, path, sizeof(filename));
840                                         }
841                                         len = strlen(filename);
842                                         if (len && filename[len - 1] != slash[0]) {
843                                                 strcat(filename, slash);
844                                         }
845                                         strcat(filename, name);
846                                         if (add_win32_extension(filename)) {
847                                                 strcpy(fullname, filename);
848                                                 break;
849                                         }
850                                 } while (temp);
851                         }
852                 }
853 #ifndef NDEBUG
854                 if (strcmp(name, fullname)) {
855                         printf("guessing '%s' == '%s'\n", name, fullname);
856                 }
857 #endif
858
859 #ifdef _WIN32
860                 // in windows change long filename to short filename because
861                 // win2k doesn't know how to parse a commandline with lots of
862                 // spaces and double-quotes. There's another solution to this
863                 // with spawnv(P_WAIT, bprogname, argv) instead of system() but
864                 // that's even uglier
865                 GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
866 #ifndef NDEBUG
867                 printf("Shortname = '%s'\n", fullname);
868 #endif
869 #endif
870         }
871 }
872
873 /* 
874  * returns absolute path to the app bundle
875  * only useful on OS X 
876  */
877 #ifdef __APPLE__
878 char* BLI_getbundle(void) {
879         CFURLRef bundleURL;
880         CFStringRef pathStr;
881         char path[MAXPATHLEN];
882         CFBundleRef mainBundle = CFBundleGetMainBundle();
883
884         bundleURL = CFBundleCopyBundleURL(mainBundle);
885         pathStr = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
886         CFStringGetCString(pathStr, path, MAXPATHLEN, kCFStringEncodingASCII);
887         return path;
888 }
889 #endif
890