Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/intern/util.c')
-rw-r--r--source/blender/blenlib/intern/util.c828
1 files changed, 828 insertions, 0 deletions
diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c
new file mode 100644
index 00000000000..f3a2d4f3970
--- /dev/null
+++ b/source/blender/blenlib/intern/util.c
@@ -0,0 +1,828 @@
+/**
+ * $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"
+
+#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
+ }
+}
+