This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenlib/intern/util.c

833 lines
17 KiB
C
Raw Normal View History

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 *****
* Diverse string, file, list operations.
*/
#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"
#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
/* 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) {
if (strncasecmp(string + len - 6, ".blend", 6) == 0) len -= 6;
else if (strncasecmp(string + len - 6, ".trace", 6) == 0) len -= 6;
}
if (len == len2) {
if (len > 4) {
/* .jf0 en .jf1 voor jstreams afvangen */
if (strncasecmp(string + len - 4, ".jf", 3) == 0) len -= 4;
else if (strncasecmp(string + len - 4, ".tga", 4) == 0) len -= 4;
else if (strncasecmp(string + len - 4, ".jpg", 4) == 0) len -= 4;
else if (strncasecmp(string + len - 4, ".png", 4) == 0) len -= 4;
else if (strncasecmp(string + len - 4, ".txt", 4) == 0) len -= 4;
else if (strncasecmp(string + len - 4, ".cyc", 4) == 0) len -= 4;
else if (strncasecmp(string + len - 4, ".enh", 4) == 0) len -= 4;
else if (strncasecmp(string + len - 4, ".rgb", 4) == 0) len -= 4;
else if (strncasecmp(string + len - 4, ".psx", 4) == 0) len -= 4;
else if (strncasecmp(string + len - 4, ".ble", 4) == 0) len -= 4;
}
}
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);
/* gaan we van 100 -> 99 of van 10 naar 9 */
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;
/* newlink komt na prevlink */
if (newlink == 0) return;
if (listbase == 0) return;
if(listbase->first==0) { /* lege lijst */
listbase->first= newlink;
listbase->last= newlink;
return;
}
if (prevlink== 0) { /* inserten voor eerste element */
newlink->next= listbase->first;
newlink->prev= 0;
newlink->next->prev= newlink;
listbase->first= newlink;
return;
}
if (listbase->last== prevlink) /* aan einde lijst */
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;
/* newlink komt voor nextlink */
if (newlink == 0) return;
if (listbase == 0) return;
if(listbase->first==0) { /* lege lijst */
listbase->first= newlink;
listbase->last= newlink;
return;
}
if (nextlink== 0) { /* inserten aan einde lijst */
newlink->prev= listbase->last;
newlink->next= 0;
((struct Link *)listbase->last)->next= newlink;
listbase->last= newlink;
return;
}
if (listbase->first== nextlink) /* aan begin lijst */
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) {
return (strcasecmp(a, b)==0);
}
void BLI_makestringcode(char *fromfile, char *str)
{
char *slash, len, temp[512];
strcpy(temp, fromfile);
/* Find the last slash */
slash = (strrchr(temp, '/')>strrchr(temp, '\\'))
? strrchr(temp, '/') : strrchr(temp, '\\');
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);
strcpy(str, temp);
}
}
}
}
int BLI_convertstringcode(char *path, char *basepath, int framenum)
{
int len, wasrelative= (strncmp(path, "//", 2)==0);
if (path[0] == '/' && path[1] == '/') {
char *filepart= BLI_strdup(path+2); /* skip code */
char *lslash= BLI_last_slash(basepath);
if (lslash) {
int baselen= (int) (lslash-basepath) + 1;
memcpy(path, basepath, baselen);
strcpy(path+baselen, filepart);
} else {
strcpy(path, filepart);
}
MEM_freeN(filepart);
}
len= strlen(path);
if(len && path[len-1]=='#') {
sprintf(path+len-1, "%04d", framenum);
}
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];
ret = getenv("HOME");
if(ret) {
if (BLI_exists(ret)) return ret;
}
// add user profile support for WIN 2K / NT
ret = getenv("USERPROFILE");
if (ret) {
if (BLI_exists(ret)) { /* from fop, also below... */
sprintf(dir, "%s/Application Data/Not a Number/Blender", ret);
BLI_recurdir_fileops(dir);
if (BLI_exists(dir)) {
return(dir);
} else {
return(ret);
}
}
}
ret = getenv("WINDOWS");
if (ret) {
if(BLI_exists(ret)) return ret;
}
ret = getenv("WINDIR");
if (ret) {
if(BLI_exists(ret)) return ret;
}
return "C:\\Temp";
#endif
}
static void char_switch(char *string, char from, char to)
{
while (*string != 0) {
if (*string == from) *string = to;
string++;
}
}
void BLI_make_exist(char *dir)
{
int a;
#ifdef WIN32
char_switch(dir, '/', '\\');
#else
char_switch(dir, '\\', '/');
#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 */
/* 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 */
#ifdef WIN32
char_switch(string, '/', '\\');
#else
char_switch(string, '\\', '/');
#endif
}
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;
} else if (strcasecmp(ext, str + a - b)) {
retval = 0;
} else {
retval = 1;
}
return (retval);
}
void BLI_split_dirfile(char *string, char *dir, char *file)
{
int a;
dir[0]= 0;
file[0]= 0;
#ifdef WIN32
if (strlen(string)) {
if (string[0] == '/' || string[0] == '\\') {
strcpy(dir, string);
} else if (string[1] == ':' && 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(a>0 && dir[a] != '\\') a--;
dir[a + 1] = 0;
strcpy(file, string + strlen(dir));
}
}
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
}
// copies from BKE_utildefines
#ifndef FILE_MAXDIR
#define FILE_MAXDIR 160
#endif
#ifndef FILE_MAXFILE
#define FILE_MAXFILE 80
#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
}
}