2003-04-26 16:02:26 +00:00
|
|
|
/* util.c
|
|
|
|
*
|
|
|
|
* various string, file, list operations.
|
|
|
|
*
|
|
|
|
*
|
2002-10-12 11:37:38 +00:00
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version. The Blender
|
|
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
|
|
* about this.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
*
|
|
|
|
* Contributor(s): none yet.
|
|
|
|
*
|
|
|
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
2003-04-26 16:02:26 +00:00
|
|
|
*
|
2002-10-12 11:37:38 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "DNA_listBase.h"
|
|
|
|
#include "BLI_storage.h"
|
|
|
|
#include "BLI_storage_types.h"
|
|
|
|
|
|
|
|
#include "BLI_util.h"
|
|
|
|
|
2002-11-25 12:02:15 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#ifndef WIN32
|
|
|
|
#include <unistd.h>
|
|
|
|
#else
|
|
|
|
#include <io.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
#include "BLI_winstuff.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
|
|
|
|
2003-05-12 14:59:08 +00:00
|
|
|
#ifdef __APPLE__
|
2003-05-12 17:13:12 +00:00
|
|
|
#include <sys/param.h>
|
2003-05-12 14:59:08 +00:00
|
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
|
|
#endif
|
|
|
|
|
2005-05-20 12:18:11 +00:00
|
|
|
|
|
|
|
// copies from BKE_utildefines
|
|
|
|
#ifndef FILE_MAXDIR
|
|
|
|
#define FILE_MAXDIR 160
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef FILE_MAXFILE
|
|
|
|
#define FILE_MAXFILE 80
|
|
|
|
#endif
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
/* local */
|
|
|
|
|
|
|
|
static int add_win32_extension(char *name);
|
|
|
|
|
|
|
|
/* implementation */
|
|
|
|
|
|
|
|
/* Ripped this from blender.c
|
|
|
|
*/
|
|
|
|
void addlisttolist(ListBase *list1, ListBase *list2)
|
|
|
|
{
|
|
|
|
|
|
|
|
if(list2->first==0) return;
|
|
|
|
|
|
|
|
if(list1->first==0) {
|
|
|
|
list1->first= list2->first;
|
|
|
|
list1->last= list2->last;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
((struct Link *)list1->last)->next= list2->first;
|
|
|
|
((struct Link *)list2->first)->prev= list1->last;
|
|
|
|
list1->last= list2->last;
|
|
|
|
}
|
|
|
|
list2->first= list2->last= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int BLI_stringdec(char *string, char *kop, char *staart, unsigned short *numlen)
|
|
|
|
{
|
|
|
|
unsigned short len, len2, nums = 0, nume = 0;
|
|
|
|
short i, found = 0;
|
|
|
|
|
|
|
|
len2 = len = strlen( string);
|
|
|
|
|
|
|
|
if (len > 6) {
|
2005-04-02 15:36:57 +00:00
|
|
|
if (BLI_strncasecmp(string + len - 6, ".blend", 6) == 0) len -= 6;
|
|
|
|
else if (BLI_strncasecmp(string + len - 6, ".trace", 6) == 0) len -= 6;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
Patch provided by Shaul Kedem: Compressed files are back!
He even made a nice doc in wiki:
http://wiki.blender.org/bin/view.pl/Blenderdev/Blendgz
Usage: set the option "Compress File" in the main "File" pulldown menu.
This setting is a user-def, meaning it is not changed on reading files.
If you want it default, save it with CTRL+U.
The longest debate went over the file naming convention. Shaul started
with .blend.gz files, which gave issues in Blender because of the code
hanging out everywhere that detects blender files, and that appends the
.blend extension if needed.
Daniel Dunbar proposed to just save it as .blend, and not bother users
with such details. This is indeed the most elegant solution, with as
only drawback that old Blender executables cannot read it.
This drawback isn't very relevant at the moment, since we're heading
towards a release that isn't upward compatible anyway... the recode
going on on Meshes, Modfiers, Armatures, Poses, Actions, NLA already
have upward compatibility issues.
We might check - during the next month(s) - on a builtin system to
warn users in the future when we change things that make a file risky
to read in an older release.
2005-07-27 19:46:06 +00:00
|
|
|
if (len > 9) {
|
|
|
|
if (BLI_strncasecmp(string + len - 9, ".blend.gz", 9) == 0) len -= 9;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (len == len2) {
|
|
|
|
if (len > 4) {
|
2003-04-26 16:02:26 +00:00
|
|
|
/* handle .jf0 en .jf1 for jstreams */
|
2005-04-02 15:36:57 +00:00
|
|
|
if (BLI_strncasecmp(string + len - 4, ".jf", 3) == 0) len -= 4;
|
|
|
|
else if (BLI_strncasecmp(string + len - 4, ".tga", 4) == 0) len -= 4;
|
|
|
|
else if (BLI_strncasecmp(string + len - 4, ".jpg", 4) == 0) len -= 4;
|
|
|
|
else if (BLI_strncasecmp(string + len - 4, ".png", 4) == 0) len -= 4;
|
|
|
|
else if (BLI_strncasecmp(string + len - 4, ".txt", 4) == 0) len -= 4;
|
|
|
|
else if (BLI_strncasecmp(string + len - 4, ".cyc", 4) == 0) len -= 4;
|
|
|
|
else if (BLI_strncasecmp(string + len - 4, ".enh", 4) == 0) len -= 4;
|
|
|
|
else if (BLI_strncasecmp(string + len - 4, ".rgb", 4) == 0) len -= 4;
|
|
|
|
else if (BLI_strncasecmp(string + len - 4, ".psx", 4) == 0) len -= 4;
|
|
|
|
else if (BLI_strncasecmp(string + len - 4, ".ble", 4) == 0) len -= 4;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = len - 1; i >= 0; i--){
|
|
|
|
if (string[i] == '/') break;
|
|
|
|
if (isdigit(string[i])) {
|
|
|
|
if (found){
|
|
|
|
nums = i;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
nume = i;
|
|
|
|
nums = i;
|
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
if (found) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (found){
|
|
|
|
if (staart) strcpy(staart,&string[nume+1]);
|
|
|
|
if (kop) {
|
|
|
|
strcpy(kop,string);
|
|
|
|
kop[nums]=0;
|
|
|
|
}
|
|
|
|
if (numlen) *numlen = nume-nums+1;
|
|
|
|
return ((int)atoi(&(string[nums])));
|
|
|
|
}
|
|
|
|
if (staart) strcpy(staart, string + len);
|
|
|
|
if (kop) {
|
|
|
|
strncpy(kop, string, len);
|
|
|
|
kop[len] = 0;
|
|
|
|
}
|
|
|
|
if (numlen) *numlen=0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_stringenc(char *string, char *kop, char *staart, unsigned short numlen, int pic)
|
|
|
|
{
|
|
|
|
char numstr[10]="";
|
|
|
|
unsigned short len,i;
|
|
|
|
|
|
|
|
strcpy(string,kop);
|
|
|
|
|
|
|
|
if (pic>0 || numlen==4) {
|
|
|
|
len= sprintf(numstr,"%d",pic);
|
|
|
|
|
|
|
|
for(i=len;i<numlen;i++){
|
|
|
|
strcat(string,"0");
|
|
|
|
}
|
|
|
|
strcat(string,numstr);
|
|
|
|
}
|
|
|
|
strcat(string,staart);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_newname(char * name, int add)
|
|
|
|
{
|
|
|
|
char head[128], tail[128];
|
|
|
|
int pic;
|
|
|
|
unsigned short digits;
|
|
|
|
|
|
|
|
pic = BLI_stringdec(name, head, tail, &digits);
|
|
|
|
|
2003-04-26 16:02:26 +00:00
|
|
|
/* are we going from 100 -> 99 or from 10 -> 9 */
|
2002-10-12 11:37:38 +00:00
|
|
|
if (add < 0 && digits < 4 && digits > 0) {
|
|
|
|
int i, exp;
|
|
|
|
exp = 1;
|
|
|
|
for (i = digits; i > 1; i--) exp *= 10;
|
|
|
|
if (pic >= exp && (pic + add) < exp) digits--;
|
|
|
|
}
|
|
|
|
|
|
|
|
pic += add;
|
|
|
|
|
|
|
|
if(digits==4 && pic<0) pic= 0;
|
|
|
|
BLI_stringenc(name, head, tail, digits, pic);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_addhead(ListBase *listbase, void *vlink)
|
|
|
|
{
|
|
|
|
struct Link *link= vlink;
|
|
|
|
|
|
|
|
if (link == 0) return;
|
|
|
|
if (listbase == 0) return;
|
|
|
|
|
|
|
|
link->next = listbase->first;
|
|
|
|
link->prev = 0;
|
|
|
|
|
|
|
|
if (listbase->first) ((struct Link *)listbase->first)->prev = link;
|
|
|
|
if (listbase->last == 0) listbase->last = link;
|
|
|
|
listbase->first = link;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_addtail(ListBase *listbase, void *vlink)
|
|
|
|
{
|
|
|
|
struct Link *link= vlink;
|
|
|
|
|
|
|
|
if (link == 0) return;
|
|
|
|
if (listbase == 0) return;
|
|
|
|
|
|
|
|
link->next = 0;
|
|
|
|
link->prev = listbase->last;
|
|
|
|
|
|
|
|
if (listbase->last) ((struct Link *)listbase->last)->next = link;
|
|
|
|
if (listbase->first == 0) listbase->first = link;
|
|
|
|
listbase->last = link;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_remlink(ListBase *listbase, void *vlink)
|
|
|
|
{
|
|
|
|
struct Link *link= vlink;
|
|
|
|
|
|
|
|
if (link == 0) return;
|
|
|
|
if (listbase == 0) return;
|
|
|
|
|
|
|
|
if (link->next) link->next->prev = link->prev;
|
|
|
|
if (link->prev) link->prev->next = link->next;
|
|
|
|
|
|
|
|
if (listbase->last == link) listbase->last = link->prev;
|
|
|
|
if (listbase->first == link) listbase->first = link->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_freelinkN(ListBase *listbase, void *vlink)
|
|
|
|
{
|
|
|
|
struct Link *link= vlink;
|
|
|
|
|
|
|
|
if (link == 0) return;
|
|
|
|
if (listbase == 0) return;
|
|
|
|
|
|
|
|
BLI_remlink(listbase,link);
|
|
|
|
MEM_freeN(link);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink)
|
|
|
|
{
|
|
|
|
struct Link *prevlink= vprevlink, *newlink= vnewlink;
|
|
|
|
|
2003-04-26 16:02:26 +00:00
|
|
|
/* newlink comes after prevlink */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (newlink == 0) return;
|
|
|
|
if (listbase == 0) return;
|
|
|
|
|
2003-04-26 16:02:26 +00:00
|
|
|
if(listbase->first==0) { /* empty list */
|
2002-10-12 11:37:38 +00:00
|
|
|
listbase->first= newlink;
|
|
|
|
listbase->last= newlink;
|
|
|
|
return;
|
|
|
|
}
|
2003-04-26 16:02:26 +00:00
|
|
|
if (prevlink== 0) { /* insert before first element */
|
2002-10-12 11:37:38 +00:00
|
|
|
newlink->next= listbase->first;
|
|
|
|
newlink->prev= 0;
|
|
|
|
newlink->next->prev= newlink;
|
|
|
|
listbase->first= newlink;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-26 16:02:26 +00:00
|
|
|
if (listbase->last== prevlink) /* at end of list */
|
2002-10-12 11:37:38 +00:00
|
|
|
listbase->last = newlink;
|
|
|
|
|
|
|
|
newlink->next= prevlink->next;
|
|
|
|
prevlink->next= newlink;
|
|
|
|
if(newlink->next) newlink->next->prev= newlink;
|
|
|
|
newlink->prev= prevlink;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
|
|
|
|
{
|
|
|
|
struct Link *nextlink= vnextlink, *newlink= vnewlink;
|
|
|
|
|
2003-04-26 16:02:26 +00:00
|
|
|
/* newlink before nextlink */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (newlink == 0) return;
|
|
|
|
if (listbase == 0) return;
|
|
|
|
|
2003-04-26 16:02:26 +00:00
|
|
|
if(listbase->first==0) { /* empty list */
|
2002-10-12 11:37:38 +00:00
|
|
|
listbase->first= newlink;
|
|
|
|
listbase->last= newlink;
|
|
|
|
return;
|
|
|
|
}
|
2003-04-26 16:02:26 +00:00
|
|
|
if (nextlink== 0) { /* insert at end of list */
|
2002-10-12 11:37:38 +00:00
|
|
|
newlink->prev= listbase->last;
|
|
|
|
newlink->next= 0;
|
|
|
|
((struct Link *)listbase->last)->next= newlink;
|
|
|
|
listbase->last= newlink;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-26 16:02:26 +00:00
|
|
|
if (listbase->first== nextlink) /* at beginning of list */
|
2002-10-12 11:37:38 +00:00
|
|
|
listbase->first = newlink;
|
|
|
|
|
|
|
|
newlink->next= nextlink;
|
|
|
|
newlink->prev= nextlink->prev;
|
|
|
|
nextlink->prev= newlink;
|
|
|
|
if(newlink->prev) newlink->prev->next= newlink;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_freelist(ListBase *listbase)
|
|
|
|
{
|
|
|
|
struct Link *link,*next;
|
|
|
|
|
|
|
|
if (listbase == 0) return;
|
|
|
|
link= listbase->first;
|
|
|
|
while(link) {
|
|
|
|
next= link->next;
|
|
|
|
free(link);
|
|
|
|
link= next;
|
|
|
|
}
|
|
|
|
listbase->first=0;
|
|
|
|
listbase->last=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BLI_freelistN(ListBase *listbase)
|
|
|
|
{
|
|
|
|
struct Link *link,*next;
|
|
|
|
|
|
|
|
if (listbase == 0) return;
|
|
|
|
link= listbase->first;
|
|
|
|
while(link) {
|
|
|
|
next= link->next;
|
|
|
|
MEM_freeN(link);
|
|
|
|
link= next;
|
|
|
|
}
|
|
|
|
listbase->first=0;
|
|
|
|
listbase->last=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int BLI_countlist(ListBase *listbase)
|
|
|
|
{
|
|
|
|
Link * link;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
if (listbase){
|
|
|
|
link = listbase->first;
|
|
|
|
while(link) {
|
|
|
|
count++;
|
|
|
|
link= link->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(count);
|
|
|
|
}
|
|
|
|
|
|
|
|
void * BLI_findlink(ListBase *listbase, int number)
|
|
|
|
{
|
|
|
|
Link * link = NULL;
|
|
|
|
|
|
|
|
if (number >= 0) {
|
|
|
|
link = listbase->first;
|
|
|
|
while (link != NULL && number != 0) {
|
|
|
|
number--;
|
|
|
|
link = link->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (link);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *BLI_strdupn(char *str, int len) {
|
|
|
|
char *n= MEM_mallocN(len+1, "strdup");
|
|
|
|
memcpy(n, str, len);
|
|
|
|
n[len]= '\0';
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
char *BLI_strdup(char *str) {
|
|
|
|
return BLI_strdupn(str, strlen(str));
|
|
|
|
}
|
|
|
|
|
|
|
|
char *BLI_strncpy(char *dst, char *src, int maxncpy) {
|
|
|
|
int srclen= strlen(src);
|
|
|
|
int cpylen= (srclen>(maxncpy-1))?(maxncpy-1):srclen;
|
|
|
|
|
|
|
|
memcpy(dst, src, cpylen);
|
|
|
|
dst[cpylen]= '\0';
|
|
|
|
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
int BLI_streq(char *a, char *b) {
|
|
|
|
return (strcmp(a, b)==0);
|
|
|
|
}
|
|
|
|
int BLI_strcaseeq(char *a, char *b) {
|
2005-04-02 15:36:57 +00:00
|
|
|
return (BLI_strcasecmp(a, b)==0);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BLI_makestringcode(char *fromfile, char *str)
|
|
|
|
{
|
|
|
|
char *slash, len, temp[512];
|
|
|
|
|
|
|
|
strcpy(temp, fromfile);
|
2005-05-20 12:18:11 +00:00
|
|
|
|
|
|
|
BLI_char_switch(temp, '\\', '/');
|
|
|
|
BLI_char_switch(str, '\\', '/');
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* Find the last slash */
|
2005-05-20 12:18:11 +00:00
|
|
|
slash = strrchr(temp, '/');
|
2002-10-12 11:37:38 +00:00
|
|
|
if(slash) {
|
|
|
|
*(slash+1)= 0;
|
|
|
|
len= strlen(temp);
|
|
|
|
if(len) {
|
|
|
|
if(strncmp(str, temp, len)==0) {
|
|
|
|
temp[0]= '/';
|
|
|
|
temp[1]= '/';
|
|
|
|
strcpy(temp+2, str+len);
|
2005-05-20 12:18:11 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
BLI_char_switch(temp+2, '/', '\\');
|
|
|
|
#endif
|
2002-10-12 11:37:38 +00:00
|
|
|
strcpy(str, temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int BLI_convertstringcode(char *path, char *basepath, int framenum)
|
|
|
|
{
|
2005-05-20 12:18:11 +00:00
|
|
|
int len, wasrelative;
|
|
|
|
char tmp[FILE_MAXDIR+FILE_MAXFILE];
|
|
|
|
char base[FILE_MAXDIR];
|
|
|
|
|
|
|
|
strcpy(tmp, path);
|
|
|
|
strcpy(base, basepath);
|
|
|
|
|
|
|
|
/* push slashes into unix mode - strings entering this part are
|
|
|
|
potentially messed up: having both back- and forward slashes.
|
|
|
|
Here we push into one conform direction, and at the end we
|
|
|
|
push them into the system specific dir. This ensures uniformity
|
|
|
|
of paths and solving some problems (and prevent potential future
|
|
|
|
ones) -jesterKing. */
|
|
|
|
BLI_char_switch(tmp, '\\', '/');
|
|
|
|
BLI_char_switch(base, '\\', '/');
|
|
|
|
|
|
|
|
wasrelative= (strncmp(tmp, "//", 2)==0);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2005-05-20 12:18:11 +00:00
|
|
|
if (tmp[0] == '/' && tmp[1] == '/') {
|
|
|
|
char *filepart= BLI_strdup(tmp+2); /* skip code */
|
|
|
|
char *lslash= BLI_last_slash(base);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (lslash) {
|
2005-05-20 12:18:11 +00:00
|
|
|
int baselen= (int) (lslash-base) + 1;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2005-05-20 12:18:11 +00:00
|
|
|
memcpy(tmp, base, baselen);
|
|
|
|
strcpy(tmp+baselen, filepart);
|
2002-10-12 11:37:38 +00:00
|
|
|
} else {
|
2005-05-20 12:18:11 +00:00
|
|
|
strcpy(tmp, filepart);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(filepart);
|
|
|
|
}
|
|
|
|
|
2005-05-20 12:18:11 +00:00
|
|
|
len= strlen(tmp);
|
|
|
|
if(len && tmp[len-1]=='#') {
|
|
|
|
sprintf(tmp+len-1, "%04d", framenum);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2005-05-20 12:18:11 +00:00
|
|
|
|
|
|
|
strcpy(path, tmp);
|
|
|
|
#ifdef WIN32
|
|
|
|
/* skip first two chars, which in case of
|
|
|
|
absolute path will be drive:/blabla and
|
|
|
|
in case of relpath //blabla/. So relpath
|
|
|
|
// will be retained, rest will be nice and
|
|
|
|
shiny win32 backward slashes :) -jesterKing
|
|
|
|
*/
|
|
|
|
BLI_char_switch(path+2, '/', '\\');
|
|
|
|
#endif
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
return wasrelative;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BLI_splitdirstring(char *di,char *fi)
|
|
|
|
{
|
|
|
|
char *lslash= BLI_last_slash(di);
|
|
|
|
|
|
|
|
if (lslash) {
|
|
|
|
strcpy(fi, lslash+1);
|
|
|
|
*(lslash+1)=0;
|
|
|
|
} else {
|
|
|
|
strcpy(fi, di);
|
|
|
|
di[0]= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char *BLI_gethome(void) {
|
|
|
|
#ifdef __BeOS
|
|
|
|
return "/boot/home/"; /* BeOS 4.5: doubleclick at icon doesnt give home env */
|
|
|
|
|
|
|
|
#elif !defined(WIN32)
|
|
|
|
return getenv("HOME");
|
|
|
|
|
|
|
|
#else /* Windows */
|
|
|
|
char * ret;
|
|
|
|
static char dir[512];
|
|
|
|
|
2004-07-11 21:54:18 +00:00
|
|
|
/* Check for %HOME% env var */
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
ret = getenv("HOME");
|
|
|
|
if(ret) {
|
2005-03-03 20:40:48 +00:00
|
|
|
sprintf(dir, "%s\\.blender", ret);
|
2004-05-10 20:35:46 +00:00
|
|
|
if (BLI_exists(dir)) return dir;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2004-07-11 21:54:18 +00:00
|
|
|
|
|
|
|
/* else, check install dir (path containing blender.exe) */
|
|
|
|
|
|
|
|
BLI_getInstallationDir(dir);
|
|
|
|
|
|
|
|
if (BLI_exists(dir))
|
|
|
|
{
|
2005-03-03 20:40:48 +00:00
|
|
|
strcat(dir,"\\.blender");
|
2004-07-11 21:54:18 +00:00
|
|
|
if (BLI_exists(dir)) return(dir);
|
|
|
|
}
|
|
|
|
|
2003-08-11 18:53:23 +00:00
|
|
|
|
|
|
|
/* add user profile support for WIN 2K / NT */
|
2002-10-12 11:37:38 +00:00
|
|
|
ret = getenv("USERPROFILE");
|
|
|
|
if (ret) {
|
|
|
|
if (BLI_exists(ret)) { /* from fop, also below... */
|
2005-03-03 20:40:48 +00:00
|
|
|
sprintf(dir, "%s\\Application Data\\Blender Foundation\\Blender", ret);
|
2002-10-12 11:37:38 +00:00
|
|
|
BLI_recurdir_fileops(dir);
|
|
|
|
if (BLI_exists(dir)) {
|
2005-03-03 20:40:48 +00:00
|
|
|
strcat(dir,"\\.blender");
|
2004-04-20 19:12:48 +00:00
|
|
|
if(BLI_exists(dir)) return(dir);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-08-11 18:53:23 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
Saving in the Windows dir is less than desirable.
|
|
|
|
Use as a last resort ONLY! (aphex)
|
|
|
|
*/
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
ret = getenv("WINDOWS");
|
|
|
|
if (ret) {
|
|
|
|
if(BLI_exists(ret)) return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = getenv("WINDIR");
|
|
|
|
if (ret) {
|
|
|
|
if(BLI_exists(ret)) return ret;
|
|
|
|
}
|
|
|
|
|
2003-08-11 18:53:23 +00:00
|
|
|
return "C:\\Temp"; /* sheesh! bad, bad, bad! (aphex) */
|
2002-10-12 11:37:38 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-05-20 12:18:11 +00:00
|
|
|
void BLI_clean(char *path)
|
|
|
|
{
|
2005-05-20 12:37:48 +00:00
|
|
|
if(path==0) return;
|
2005-05-20 12:18:11 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
if(path && strlen(path)>2) {
|
|
|
|
BLI_char_switch(path+2, '/', '\\');
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
BLI_char_switch(path, '\\', '/');
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void BLI_char_switch(char *string, char from, char to)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2005-05-20 12:37:48 +00:00
|
|
|
if(string==0) return;
|
2002-10-12 11:37:38 +00:00
|
|
|
while (*string != 0) {
|
|
|
|
if (*string == from) *string = to;
|
|
|
|
string++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-05-20 12:18:11 +00:00
|
|
|
void BLI_make_exist(char *dir) {
|
2002-10-12 11:37:38 +00:00
|
|
|
int a;
|
|
|
|
|
|
|
|
#ifdef WIN32
|
2005-05-20 12:18:11 +00:00
|
|
|
BLI_char_switch(dir, '/', '\\');
|
2002-10-12 11:37:38 +00:00
|
|
|
#else
|
2005-05-20 12:18:11 +00:00
|
|
|
BLI_char_switch(dir, '\\', '/');
|
2002-10-12 11:37:38 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
a = strlen(dir);
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
while(BLI_exists(dir) == 0){
|
|
|
|
a --;
|
|
|
|
while(dir[a] != '\\'){
|
|
|
|
a--;
|
|
|
|
if (a <= 0) break;
|
|
|
|
}
|
|
|
|
if (a >= 0) dir[a+1] = 0;
|
|
|
|
else {
|
|
|
|
strcpy(dir,"\\");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
while(BLI_exist(dir) == 0){
|
|
|
|
a --;
|
|
|
|
while(dir[a] != '/'){
|
|
|
|
a--;
|
|
|
|
if (a <= 0) break;
|
|
|
|
}
|
|
|
|
if (a >= 0) dir[a+1] = 0;
|
|
|
|
else {
|
|
|
|
strcpy(dir,"/");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void BLI_make_file_string(char *relabase, char *string, char *dir, char *file)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!string || !dir || !file) return; /* We don't want any NULLs */
|
|
|
|
|
|
|
|
string[0]= 0; /* ton */
|
2005-06-10 13:12:59 +00:00
|
|
|
|
2005-05-20 12:18:11 +00:00
|
|
|
/* we first push all slashes into unix mode, just to make sure we don't get
|
|
|
|
any mess with slashes later on. -jesterKing */
|
|
|
|
BLI_char_switch(relabase, '\\', '/');
|
|
|
|
BLI_char_switch(dir, '\\', '/');
|
|
|
|
BLI_char_switch(file, '\\', '/');
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* Resolve relative references */
|
|
|
|
if (relabase && dir[0] == '/' && dir[1] == '/') {
|
|
|
|
char *lslash;
|
|
|
|
|
|
|
|
/* Get the file name, chop everything past the last slash (ie. the filename) */
|
|
|
|
strcpy(string, relabase);
|
|
|
|
|
|
|
|
lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\');
|
|
|
|
|
|
|
|
if(lslash) *(lslash+1)= 0;
|
|
|
|
|
|
|
|
dir+=2; /* Skip over the relative reference */
|
|
|
|
}
|
|
|
|
|
|
|
|
strcat(string, dir);
|
|
|
|
|
|
|
|
/* Make sure string ends in one (and only one) slash */
|
|
|
|
if (string[strlen(string)-1] != '/' && string[strlen(string)-1] != '\\')
|
|
|
|
strcat(string, "/");
|
|
|
|
|
|
|
|
while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
|
|
|
|
file++;
|
|
|
|
|
|
|
|
strcat (string, file);
|
|
|
|
|
|
|
|
/* Push all slashes to the system preferred direction */
|
2005-06-10 13:12:59 +00:00
|
|
|
BLI_clean(string);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int BLI_testextensie(char *str, char *ext)
|
|
|
|
{
|
|
|
|
short a, b;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
a= strlen(str);
|
|
|
|
b= strlen(ext);
|
|
|
|
|
|
|
|
if(a==0 || b==0 || b>=a) {
|
|
|
|
retval = 0;
|
2005-04-02 15:36:57 +00:00
|
|
|
} else if (BLI_strcasecmp(ext, str + a - b)) {
|
2002-10-12 11:37:38 +00:00
|
|
|
retval = 0;
|
|
|
|
} else {
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (retval);
|
|
|
|
}
|
|
|
|
|
2005-03-28 15:29:59 +00:00
|
|
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
void BLI_split_dirfile(char *string, char *dir, char *file)
|
|
|
|
{
|
|
|
|
int a;
|
|
|
|
|
|
|
|
dir[0]= 0;
|
|
|
|
file[0]= 0;
|
|
|
|
|
|
|
|
#ifdef WIN32
|
2005-05-20 12:18:11 +00:00
|
|
|
BLI_char_switch(string, '/', '\\'); /* make sure we have a valid path format */
|
2005-03-28 15:29:59 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (strlen(string)) {
|
2005-04-02 18:20:03 +00:00
|
|
|
int len;
|
2002-10-12 11:37:38 +00:00
|
|
|
if (string[0] == '/' || string[0] == '\\') {
|
2005-03-28 18:37:19 +00:00
|
|
|
BLI_strncpy(dir, string, FILE_MAXDIR);
|
2002-10-12 11:37:38 +00:00
|
|
|
} else if (string[1] == ':' && string[2] == '\\') {
|
2005-03-28 18:37:19 +00:00
|
|
|
BLI_strncpy(dir, string, FILE_MAXDIR);
|
2003-12-01 14:27:06 +00:00
|
|
|
} else {
|
|
|
|
BLI_getwdN(dir);
|
|
|
|
strcat(dir,"/");
|
|
|
|
strcat(dir,string);
|
2005-03-28 18:37:19 +00:00
|
|
|
BLI_strncpy(string,dir,FILE_MAXDIR+FILE_MAXFILE);
|
2003-12-01 14:27:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BLI_make_exist(dir);
|
|
|
|
|
|
|
|
// BLI_exist doesn't recognize a slashed dirname as a dir
|
|
|
|
// check if a trailing slash exists, and remove it. Do not do this
|
|
|
|
// when we are already at root. -jesterKing
|
|
|
|
a = strlen(dir);
|
|
|
|
if(a>=4 && dir[a-1]=='\\') dir[a-1] = 0;
|
|
|
|
|
|
|
|
if (S_ISDIR(BLI_exist(dir))) {
|
|
|
|
|
2005-03-28 15:29:59 +00:00
|
|
|
/* copy from end of string into file, to ensure filename itself isn't truncated
|
|
|
|
if string is too long. (aphex) */
|
|
|
|
|
|
|
|
len = FILE_MAXFILE - strlen(string);
|
|
|
|
|
|
|
|
if (len < 0)
|
2005-03-28 18:37:19 +00:00
|
|
|
BLI_strncpy(file,string + abs(len),FILE_MAXFILE);
|
2005-03-28 15:29:59 +00:00
|
|
|
else
|
2005-03-28 18:37:19 +00:00
|
|
|
BLI_strncpy(file,string,FILE_MAXFILE);
|
2005-03-28 15:29:59 +00:00
|
|
|
|
|
|
|
if (strrchr(string,'\\')){
|
2005-03-28 18:37:19 +00:00
|
|
|
BLI_strncpy(file,strrchr(string,'\\')+1,FILE_MAXFILE);
|
2005-03-28 15:29:59 +00:00
|
|
|
}
|
2003-12-01 14:27:06 +00:00
|
|
|
|
|
|
|
if (a = strlen(dir)) {
|
|
|
|
if (dir[a-1] != '\\') strcat(dir,"\\");
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
a = strlen(dir) - 1;
|
|
|
|
while(a>0 && dir[a] != '\\') a--;
|
|
|
|
dir[a + 1] = 0;
|
2005-03-28 18:37:19 +00:00
|
|
|
BLI_strncpy(file, string + strlen(dir),FILE_MAXFILE);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
strcpy(dir, "\\");
|
|
|
|
file[0]=0;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (strlen(string)) {
|
|
|
|
if (string[0] == '/') {
|
|
|
|
strcpy(dir, string);
|
|
|
|
} else if (string[1] == ':' && string[2] == '\\') {
|
|
|
|
string+=2;
|
|
|
|
strcpy(dir, string);
|
|
|
|
} else {
|
|
|
|
BLI_getwdN(dir);
|
|
|
|
strcat(dir,"/");
|
|
|
|
strcat(dir,string);
|
|
|
|
strcpy(string,dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_make_exist(dir);
|
|
|
|
|
|
|
|
if (S_ISDIR(BLI_exist(dir))) {
|
|
|
|
strcpy(file,string + strlen(dir));
|
|
|
|
|
|
|
|
if (strrchr(file,'/')) strcpy(file,strrchr(file,'/')+1);
|
|
|
|
|
|
|
|
if ( (a = strlen(dir)) ) {
|
|
|
|
if (dir[a-1] != '/') strcat(dir,"/");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
a = strlen(dir) - 1;
|
|
|
|
while(dir[a] != '/') a--;
|
|
|
|
dir[a + 1] = 0;
|
|
|
|
strcpy(file, string + strlen(dir));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BLI_getwdN(dir);
|
|
|
|
strcat(dir, "/");
|
|
|
|
file[0] = 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static int add_win32_extension(char *name)
|
|
|
|
{
|
|
|
|
int retval = 0;
|
|
|
|
int type;
|
|
|
|
|
|
|
|
type = BLI_exist(name);
|
|
|
|
if ((type == 0) || S_ISDIR(type)) {
|
|
|
|
#ifdef _WIN32
|
|
|
|
char filename[FILE_MAXDIR+FILE_MAXFILE];
|
|
|
|
char ext[FILE_MAXDIR+FILE_MAXFILE];
|
|
|
|
char *extensions = getenv("PATHEXT");
|
|
|
|
if (extensions) {
|
|
|
|
char *temp;
|
|
|
|
do {
|
|
|
|
strcpy(filename, name);
|
|
|
|
temp = strstr(extensions, ";");
|
|
|
|
if (temp) {
|
|
|
|
strncpy(ext, extensions, temp - extensions);
|
|
|
|
ext[temp - extensions] = 0;
|
|
|
|
extensions = temp + 1;
|
|
|
|
strcat(filename, ext);
|
|
|
|
} else {
|
|
|
|
strcat(filename, extensions);
|
|
|
|
}
|
|
|
|
|
|
|
|
type = BLI_exist(filename);
|
|
|
|
if (type && (! S_ISDIR(type))) {
|
|
|
|
retval = 1;
|
|
|
|
strcpy(name, filename);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (temp);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BLI_where_am_i(char *fullname, char *name)
|
|
|
|
{
|
|
|
|
char filename[FILE_MAXDIR+FILE_MAXFILE];
|
|
|
|
char *path, *temp;
|
|
|
|
int len;
|
|
|
|
#ifdef _WIN32
|
|
|
|
char *seperator = ";";
|
|
|
|
char *slash = "\\";
|
|
|
|
#else
|
|
|
|
char *seperator = ":";
|
|
|
|
char *slash = "/";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (name && fullname && strlen(name)) {
|
|
|
|
strcpy(fullname, name);
|
|
|
|
if (name[0] == '.') {
|
|
|
|
// relative path, prepend cwd
|
|
|
|
BLI_getwdN(fullname);
|
|
|
|
len = strlen(fullname);
|
|
|
|
if (len && fullname[len -1] != slash[0]) {
|
|
|
|
strcat(fullname, slash);
|
|
|
|
}
|
|
|
|
strcat(fullname, name);
|
|
|
|
add_win32_extension(fullname);
|
|
|
|
} else if (BLI_last_slash(name)) {
|
|
|
|
// full path
|
|
|
|
strcpy(fullname, name);
|
|
|
|
add_win32_extension(fullname);
|
|
|
|
} else {
|
|
|
|
// search for binary in $PATH
|
|
|
|
path = getenv("PATH");
|
|
|
|
if (path) {
|
|
|
|
do {
|
|
|
|
temp = strstr(path, seperator);
|
|
|
|
if (temp) {
|
|
|
|
strncpy(filename, path, temp - path);
|
|
|
|
filename[temp - path] = 0;
|
|
|
|
path = temp + 1;
|
|
|
|
} else {
|
|
|
|
strncpy(filename, path, sizeof(filename));
|
|
|
|
}
|
|
|
|
len = strlen(filename);
|
|
|
|
if (len && filename[len - 1] != slash[0]) {
|
|
|
|
strcat(filename, slash);
|
|
|
|
}
|
|
|
|
strcat(filename, name);
|
|
|
|
if (add_win32_extension(filename)) {
|
|
|
|
strcpy(fullname, filename);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
|
|
if (strcmp(name, fullname)) {
|
|
|
|
printf("guessing '%s' == '%s'\n", name, fullname);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
// in windows change long filename to short filename because
|
|
|
|
// win2k doesn't know how to parse a commandline with lots of
|
|
|
|
// spaces and double-quotes. There's another solution to this
|
|
|
|
// with spawnv(P_WAIT, bprogname, argv) instead of system() but
|
|
|
|
// that's even uglier
|
|
|
|
GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
|
|
|
|
#ifndef NDEBUG
|
|
|
|
printf("Shortname = '%s'\n", fullname);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-05-12 14:59:08 +00:00
|
|
|
/*
|
|
|
|
* returns absolute path to the app bundle
|
|
|
|
* only useful on OS X
|
|
|
|
*/
|
|
|
|
#ifdef __APPLE__
|
|
|
|
char* BLI_getbundle(void) {
|
|
|
|
CFURLRef bundleURL;
|
|
|
|
CFStringRef pathStr;
|
2004-12-12 13:29:54 +00:00
|
|
|
static char path[MAXPATHLEN];
|
2003-05-12 14:59:08 +00:00
|
|
|
CFBundleRef mainBundle = CFBundleGetMainBundle();
|
|
|
|
|
|
|
|
bundleURL = CFBundleCopyBundleURL(mainBundle);
|
|
|
|
pathStr = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
|
|
|
|
CFStringGetCString(pathStr, path, MAXPATHLEN, kCFStringEncodingASCII);
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-04-02 15:36:57 +00:00
|
|
|
int BLI_strcasecmp(const char *s1, const char *s2) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; ; i++) {
|
|
|
|
char c1 = tolower(s1[i]);
|
|
|
|
char c2 = tolower(s2[i]);
|
|
|
|
|
|
|
|
if (c1<c2) {
|
|
|
|
return -1;
|
|
|
|
} else if (c1>c2) {
|
|
|
|
return 1;
|
|
|
|
} else if (c1==0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int BLI_strncasecmp(const char *s1, const char *s2, int n) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; i<n; i++) {
|
|
|
|
char c1 = tolower(s1[i]);
|
|
|
|
char c2 = tolower(s2[i]);
|
|
|
|
|
|
|
|
if (c1<c2) {
|
|
|
|
return -1;
|
|
|
|
} else if (c1>c2) {
|
|
|
|
return 1;
|
|
|
|
} else if (c1==0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|