Blame src/common.c

Ivan Mahonin 8535a3
Ivan Mahonin 28a314
#include <dirent.h>
Ivan Mahonin 28a314
#include <sys/stat.h>
Ivan Mahonin 28a314
Ivan Mahonin 8535a3
#include "private.h"
Ivan Mahonin ca6bde
#include "drawing.h"
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
Ivan Mahonin 8eb855
int heliInitialized;
Ivan Mahonin 8eb855
HeliArray heliObjectsSet;
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
Ivan Mahonin 1015c5
struct _Directory {
Ivan Mahonin dac862
	size_t pathLen;
Ivan Mahonin 1015c5
	HeliArray files;
Ivan Mahonin 1015c5
};
Ivan Mahonin 1015c5
Ivan Mahonin 1015c5
Ivan Mahonin 1d641c
static const float yuvToRgb[3][3] = {
Ivan Mahonin 1d641c
	{ 1.0,  0.0     ,  1.402    },
Ivan Mahonin 1d641c
	{ 1.0, -0.344136, -0.714136 },
Ivan Mahonin 1d641c
	{ 1.0,  1.772   ,  0.0      } };
Ivan Mahonin 1d641c
Ivan Mahonin 1d641c
static const float rgbToYuv[3][3] = {
Ivan Mahonin 1d641c
	{  0.299   ,  0.587   ,  0.114    },
Ivan Mahonin 1d641c
	{ -0.168736, -0.331264,  0.5      },
Ivan Mahonin 1d641c
	{  0.5     , -0.418688, -0.081312 } };
Ivan Mahonin 1d641c
Ivan Mahonin c7535b
#include "colors.inc.h"
Ivan Mahonin 09c823
Ivan Mahonin 09c823
Ivan Mahonin 8535a3
int randomNumber(int min, int max)
Ivan Mahonin 8535a3
	{ return max <= min ? min : rand()%(max - min + 1) + min; }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
double randomFloat()
Ivan Mahonin 8535a3
	{ return (double)rand()/(double)RAND_MAX; }
Ivan Mahonin 8535a3
Ivan Mahonin 909bc2
void rotateVector(double *x, double *y, double angle) {
Ivan Mahonin 909bc2
	double a = angle*PI/180.0;
Ivan Mahonin 909bc2
	double xx = x ? *x : 0.0;
Ivan Mahonin 909bc2
	double yy = y ? *y : 0.0;
Ivan Mahonin 909bc2
	double c = cos(a);
Ivan Mahonin 909bc2
	double s = sin(a);
Ivan Mahonin 909bc2
	if (x) *x = xx*c - yy*s;
Ivan Mahonin 909bc2
	if (y) *y = xx*s + yy*c;
Ivan Mahonin 909bc2
}
Ivan Mahonin 8535a3
Ivan Mahonin dac862
Directory openDirectoryEx(
Ivan Mahonin dac862
	const char *path,
Ivan Mahonin dac862
	const char *prefix,
Ivan Mahonin dac862
	const char *suffix,
Ivan Mahonin dac862
	int caseSensitive,
Ivan Mahonin dac862
	int showFiles,
Ivan Mahonin dac862
	int showDirectories )
Ivan Mahonin dac862
{
Ivan Mahonin 8eb855
	if (!heliInitialized) return NULL;
Ivan Mahonin dac862
	if (!path) return NULL;
Ivan Mahonin 28a314
	
Ivan Mahonin 28a314
	DIR *dir = opendir(path);
Ivan Mahonin 1015c5
	if (!dir) return NULL;
Ivan Mahonin 1015c5
	
Ivan Mahonin 87fe10
	Directory d = calloc(1, sizeof(*d));
Ivan Mahonin 28a314
	
Ivan Mahonin dac862
	d->pathLen = strlen(path);
Ivan Mahonin dac862
	size_t prefixLen = prefix ? strlen(prefix) : 0u;
Ivan Mahonin dac862
	size_t suffixLen = suffix ? strlen(suffix) : 0u;
Ivan Mahonin dac862
	
Ivan Mahonin dac862
	size_t bufLen = d->pathLen + 1024;
Ivan Mahonin dac862
	char *buf = calloc(1, bufLen);
Ivan Mahonin dac862
	strcpy(buf, path);
Ivan Mahonin dac862
	if (d->pathLen > 0 && buf[d->pathLen - 1] != '\\' && buf[d->pathLen - 1] != '/') {
Ivan Mahonin dac862
		char lastSlash = '/';
Ivan Mahonin dac862
		for(const char *c = buf; *c; ++c)
Ivan Mahonin dac862
			if (*c == '\\' || *c == '/') lastSlash = *c;
Ivan Mahonin dac862
		buf[d->pathLen++] = lastSlash;
Ivan Mahonin dac862
	}
Ivan Mahonin dac862
	
Ivan Mahonin 28a314
	struct dirent *ent;
Ivan Mahonin 28a314
	while((ent = readdir(dir)) != NULL) {
Ivan Mahonin 87fe10
		if ( !ent->d_name[0]
Ivan Mahonin 87fe10
		  || strcmp(ent->d_name, ".") == 0
Ivan Mahonin 87fe10
		  || strcmp(ent->d_name, "..") == 0 ) continue;
Ivan Mahonin dac862
		
Ivan Mahonin dac862
		if (prefixLen) {
Ivan Mahonin dac862
			if ( caseSensitive ? strncmp(prefix, ent->d_name, prefixLen)
Ivan Mahonin dac862
				               : heliStringCompareNCi(prefix, ent->d_name, prefixLen) )
Ivan Mahonin dac862
				continue;
Ivan Mahonin dac862
		}
Ivan Mahonin dac862
		
Ivan Mahonin dac862
		size_t nameLen = strlen(ent->d_name);
Ivan Mahonin dac862
		
Ivan Mahonin dac862
		if (suffixLen) {
Ivan Mahonin dac862
			if (nameLen < suffixLen) continue;
Ivan Mahonin dac862
			const char *sub = ent->d_name + nameLen - suffixLen;
Ivan Mahonin dac862
			if ( caseSensitive ? strcmp(suffix, sub)
Ivan Mahonin dac862
				               : heliStringCompareCi(suffix, sub) )
Ivan Mahonin dac862
				continue;
Ivan Mahonin dac862
		}
Ivan Mahonin dac862
		
Ivan Mahonin dac862
		if (bufLen <= d->pathLen + nameLen) {
Ivan Mahonin dac862
			bufLen = d->pathLen + nameLen + 1024;
Ivan Mahonin dac862
			buf = realloc(buf, bufLen);
Ivan Mahonin dac862
		}
Ivan Mahonin dac862
		
Ivan Mahonin dac862
		strcpy(buf + d->pathLen, ent->d_name);
Ivan Mahonin dac862
		
Ivan Mahonin dac862
		if ( (showFiles && fileExists(buf))
Ivan Mahonin dac862
		  || (showDirectories && directoryExists(buf)) )
Ivan Mahonin dac862
			heliStringmapAdd(&d->files, buf, NULL, NULL);
Ivan Mahonin 1015c5
	}
Ivan Mahonin 28a314
	closedir(dir);
Ivan Mahonin 1015c5
	
Ivan Mahonin 8eb855
	heliObjectRegister(d, (HeliFreeCallback)&closeDirectory);
Ivan Mahonin 1015c5
	return d;
Ivan Mahonin 1015c5
}
Ivan Mahonin 1015c5
Ivan Mahonin dac862
Directory openDirectory(const char *path)
Ivan Mahonin dac862
	{ return openDirectoryEx(path, NULL, NULL, TRUE, TRUE, TRUE); }
Ivan Mahonin dac862
Ivan Mahonin 1015c5
void closeDirectory(Directory directory) {
Ivan Mahonin 1015c5
	if (!directory) return;
Ivan Mahonin 8eb855
	heliObjectUnregister(directory);
Ivan Mahonin 1015c5
	heliArrayDestroy(&directory->files);
Ivan Mahonin 1015c5
	free(directory);
Ivan Mahonin 1015c5
}
Ivan Mahonin 1015c5
Ivan Mahonin 1015c5
int directoryGetCount(Directory directory)
Ivan Mahonin 1015c5
	{ return directory->files.count; }
Ivan Mahonin 1015c5
Ivan Mahonin dac862
const char* directoryGetFull(Directory directory, int i)
Ivan Mahonin 1015c5
	{ return (const char*)heliArrayGetKey(&directory->files, i); }
Ivan Mahonin 1015c5
Ivan Mahonin dac862
const char* directoryGet(Directory directory, int i) {
Ivan Mahonin dac862
	const char *path = directoryGetFull(directory, i);
Ivan Mahonin dac862
	return path ? path + directory->pathLen : NULL;
Ivan Mahonin dac862
}
Ivan Mahonin 1015c5
Ivan Mahonin 28a314
int fileExists(const char *path) {
Ivan Mahonin 28a314
	struct stat s = {};
Ivan Mahonin 28a314
	return stat(path, &s) == 0 && !(s.st_mode & S_IFDIR);
Ivan Mahonin 28a314
}
Ivan Mahonin 28a314
Ivan Mahonin 28a314
int directoryExists(const char *path) {
Ivan Mahonin 28a314
	struct stat s = {};
Ivan Mahonin 28a314
	return stat(path, &s) == 0 && (s.st_mode & S_IFDIR);
Ivan Mahonin 28a314
}
Ivan Mahonin 1015c5
Ivan Mahonin 0b1da0
int makeDirectory(const char *path)
Ivan Mahonin f13730
#ifdef WIN32
Ivan Mahonin f13730
	{ return directoryExists(path) || !mkdir(path); }
Ivan Mahonin f13730
#else
Ivan Mahonin 0b1da0
	{ return directoryExists(path) || !mkdir(path, 0777); }
Ivan Mahonin f13730
#endif
Ivan Mahonin 4690d8
Ivan Mahonin 1015c5
Ivan Mahonin 8535a3
char* heliStringCopy(const char *x) {
Ivan Mahonin 8535a3
	int len = strlen(x) + 1;
Ivan Mahonin f63775
	char *cp = malloc(len);
Ivan Mahonin 8535a3
	memcpy(cp, x, len);
Ivan Mahonin 8535a3
	return cp;
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin bcaca0
char* heliStringCopyLower(const char *x) {
Ivan Mahonin bcaca0
	char *xx = heliStringCopy(x);
Ivan Mahonin bcaca0
	heliStringLower(xx);
Ivan Mahonin bcaca0
	return xx;
Ivan Mahonin bcaca0
}
Ivan Mahonin bcaca0
Ivan Mahonin dba3fc
char* heliStringConcat(const char *a, const char *b) {
Ivan Mahonin dba3fc
	int la = strlen(a);
Ivan Mahonin dba3fc
	int lb = strlen(b);
Ivan Mahonin dba3fc
	char *s = malloc(la + lb + 1);
Ivan Mahonin dba3fc
	memcpy(s, a, la);
Ivan Mahonin dba3fc
	memcpy(s + la, b, lb);
Ivan Mahonin dba3fc
	s[la + lb] = 0;
Ivan Mahonin dba3fc
	return s;
Ivan Mahonin dba3fc
}
Ivan Mahonin dba3fc
Ivan Mahonin 8535a3
char* heliStringConcat3(const char *a, const char *b, const char *c) {
Ivan Mahonin 8535a3
	int la = strlen(a);
Ivan Mahonin 8535a3
	int lb = strlen(b);
Ivan Mahonin 8535a3
	int lc = strlen(c);
Ivan Mahonin 8535a3
	char *s = malloc(la + lb + lc + 1);
Ivan Mahonin 8535a3
	memcpy(s, a, la);
Ivan Mahonin 8535a3
	memcpy(s + la, b, lb);
Ivan Mahonin 8535a3
	memcpy(s + la + lb, c, lc);
Ivan Mahonin 8535a3
	s[la + lb + lc] = 0;
Ivan Mahonin 8535a3
	return s;
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin dac862
int heliStringCompareNCi(const char *a, const char *b, size_t n) {
Ivan Mahonin bcaca0
	if (!a && !b) return 0;
Ivan Mahonin bcaca0
	if (!a) return -1;
Ivan Mahonin bcaca0
	if (!b) return 1;
Ivan Mahonin dac862
	while((*a || *b) && n) {
Ivan Mahonin bcaca0
		if (!a) return -1;
Ivan Mahonin bcaca0
		if (!b) return 1;
Ivan Mahonin bcaca0
		char aa = tolower(*a);
Ivan Mahonin bcaca0
		char bb = tolower(*b);
Ivan Mahonin bcaca0
		if (aa < bb) return -1;
Ivan Mahonin bcaca0
		if (bb < aa) return 1;
Ivan Mahonin dac862
		++a, ++b, --n;
Ivan Mahonin bcaca0
	}
Ivan Mahonin bcaca0
	return 0;
Ivan Mahonin bcaca0
}
Ivan Mahonin bcaca0
Ivan Mahonin dac862
int heliStringCompareCi(const char *a, const char *b)
Ivan Mahonin dac862
	{ return heliStringCompareNCi(a, b, SIZE_MAX); }
Ivan Mahonin dac862
Ivan Mahonin 8535a3
int heliStringEndsWithLowcase(const char *s, const char *tail) {
Ivan Mahonin 8535a3
	int ls = strlen(s);
Ivan Mahonin 8535a3
	int lt = strlen(tail);
Ivan Mahonin 8535a3
	if (lt > ls) return FALSE;
Ivan Mahonin 8535a3
	for(int i = 0; i < lt; ++i)
Ivan Mahonin 8535a3
		if (tolower(s[ls - i]) != tolower(tail[lt - i]))
Ivan Mahonin 8535a3
			return FALSE;
Ivan Mahonin 8535a3
	return TRUE;
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin bcaca0
void heliStringLower(char *x)
Ivan Mahonin 981405
	{ while(*x) { *x = tolower(*x); ++x; } }
Ivan Mahonin 8535a3
Ivan Mahonin 09c823
Ivan Mahonin 1d641c
static double colorClamp(double c)
Ivan Mahonin 1d641c
	{ return c > 0 ? (c < 1 ? c : 1) : 0; }
Ivan Mahonin 1d641c
static unsigned int colorToInt(double c)
Ivan Mahonin 1d641c
	{ return (unsigned int)floor(colorClamp(c)*255.99); }
Ivan Mahonin d4e89f
Ivan Mahonin 7ac038
unsigned int colorWithAlpha(unsigned int colorCode, double a)
Ivan Mahonin 7ac038
	{ return (0xffffff00 & colorCode) | colorToInt(colorGetAlpha(colorCode)*a); }
Ivan Mahonin d4e89f
unsigned int colorByRGBA(double r, double g, double b, double a) {
Ivan Mahonin d4e89f
	return (colorToInt(r) << 24)
Ivan Mahonin d4e89f
	     | (colorToInt(g) << 16)
Ivan Mahonin d4e89f
	     | (colorToInt(b) <<  8)
Ivan Mahonin d4e89f
	     |  colorToInt(a);
Ivan Mahonin d4e89f
}
Ivan Mahonin 7ac038
Ivan Mahonin 1d641c
unsigned int colorByYUVA(double y, double u, double v, double a) {
Ivan Mahonin 1d641c
	return colorByRGBA(
Ivan Mahonin 1d641c
		yuvToRgb[0][0]*y + yuvToRgb[0][1]*u + yuvToRgb[0][2]*v,
Ivan Mahonin 1d641c
		yuvToRgb[1][0]*y + yuvToRgb[1][1]*u + yuvToRgb[1][2]*v,
Ivan Mahonin 1d641c
		yuvToRgb[2][0]*y + yuvToRgb[2][1]*u + yuvToRgb[2][2]*v,
Ivan Mahonin 1d641c
		a );
Ivan Mahonin 1d641c
}
Ivan Mahonin 1d641c
unsigned int colorByHSVA(double h, double s, double v, double a) {
Ivan Mahonin 1d641c
	h -= floor(h/360)*360;
Ivan Mahonin 1d641c
	h /= 60.0;
Ivan Mahonin 1d641c
	int i = (int)h;
Ivan Mahonin 1d641c
	double f = h - i;
Ivan Mahonin 1d641c
	double p = v*(1 - s);
Ivan Mahonin 1d641c
	double q = v*(1 - s*f);
Ivan Mahonin 1d641c
	double t = v*(1 - s*(1 - f));
Ivan Mahonin 1d641c
	switch(i) {
Ivan Mahonin 1d641c
	case 0: return colorByRGBA(v, t, p, a);
Ivan Mahonin 1d641c
	case 1: return colorByRGBA(q, v, p, a);
Ivan Mahonin 1d641c
	case 2: return colorByRGBA(p, v, t, a);
Ivan Mahonin 1d641c
	case 3: return colorByRGBA(p, q, v, a);
Ivan Mahonin 1d641c
	case 4: return colorByRGBA(t, p, v, a);
Ivan Mahonin 1d641c
	case 5: return colorByRGBA(v, p, q, a);
Ivan Mahonin 1d641c
	}
Ivan Mahonin 1d641c
	return colorByRGBA(v, t, p, a);
Ivan Mahonin 1d641c
}
Ivan Mahonin d4e89f
Ivan Mahonin d4e89f
unsigned int colorByRGB(double r, double g, double b)
Ivan Mahonin d4e89f
	{ return colorByRGBA(r, g, b, 1); }
Ivan Mahonin 1d641c
unsigned int colorByHSV(double h, double s, double v)
Ivan Mahonin 1d641c
	{ return colorByHSVA(h, s, v, 1); }
Ivan Mahonin 1d641c
unsigned int colorByYUV(double y, double u, double v)
Ivan Mahonin 1d641c
	{ return colorByYUVA(y, u, v, 1); }
Ivan Mahonin 1d641c
Ivan Mahonin d6f40c
double colorGetRed  (unsigned int colorCode) { return ( colorCode >> 24         )/255.0; }
Ivan Mahonin d6f40c
double colorGetGreen(unsigned int colorCode) { return ((colorCode >> 16) & 0xFFu)/255.0; }
Ivan Mahonin d6f40c
double colorGetBlue (unsigned int colorCode) { return ((colorCode >>  8) & 0xFFu)/255.0; }
Ivan Mahonin d6f40c
double colorGetAlpha(unsigned int colorCode) { return ( colorCode        & 0xFFu)/255.0; }
Ivan Mahonin 1d641c
void heliColorToDouble(unsigned int code, double *rgba) {
Ivan Mahonin 1d641c
	rgba[0] = colorGetRed  (code);
Ivan Mahonin 1d641c
	rgba[1] = colorGetGreen(code);
Ivan Mahonin 1d641c
	rgba[2] = colorGetBlue (code);
Ivan Mahonin 1d641c
	rgba[3] = colorGetAlpha(code);
Ivan Mahonin 1d641c
}
Ivan Mahonin 1d641c
Ivan Mahonin d6f40c
double colorGetYLuminance(unsigned int colorCode) {
Ivan Mahonin d6f40c
	return rgbToYuv[0][0]*colorGetRed  (colorCode)
Ivan Mahonin d6f40c
		 + rgbToYuv[0][1]*colorGetGreen(colorCode)
Ivan Mahonin d6f40c
		 + rgbToYuv[0][2]*colorGetBlue (colorCode);
Ivan Mahonin 1d641c
}
Ivan Mahonin d6f40c
double colorGetUChrominance(unsigned int colorCode) {
Ivan Mahonin d6f40c
	return rgbToYuv[1][0]*colorGetRed  (colorCode)
Ivan Mahonin d6f40c
		 + rgbToYuv[1][1]*colorGetGreen(colorCode)
Ivan Mahonin d6f40c
		 + rgbToYuv[1][2]*colorGetBlue (colorCode);
Ivan Mahonin 1d641c
}
Ivan Mahonin d6f40c
double colorGetVChrominance(unsigned int colorCode) {
Ivan Mahonin d6f40c
	return rgbToYuv[1][0]*colorGetRed  (colorCode)
Ivan Mahonin d6f40c
		 + rgbToYuv[1][1]*colorGetGreen(colorCode)
Ivan Mahonin d6f40c
		 + rgbToYuv[1][2]*colorGetBlue (colorCode);
Ivan Mahonin 1d641c
}
Ivan Mahonin 1d641c
Ivan Mahonin 1d641c
Ivan Mahonin 1d641c
static int colorMin(double *c)
Ivan Mahonin 1d641c
	{ return c[0] < c[1] ? (c[0] < c[2] ? 0 : 2) : (c[1] < c[2] ? 1 : 2); }
Ivan Mahonin 1d641c
static int colorMax(double *c)
Ivan Mahonin 1d641c
	{ return c[0] > c[1] ? (c[0] > c[2] ? 0 : 2) : (c[1] > c[2] ? 1 : 2); }
Ivan Mahonin d6f40c
double colorGetHue(unsigned int colorCode) {
Ivan Mahonin d6f40c
	double rgb[] = { colorGetRed  (colorCode),
Ivan Mahonin d6f40c
	                 colorGetGreen(colorCode),
Ivan Mahonin d6f40c
	                 colorGetBlue (colorCode) };
Ivan Mahonin 1d641c
	int cmin = colorMin(rgb);
Ivan Mahonin 1d641c
	int cmax = colorMax(rgb);
Ivan Mahonin 1d641c
	double d = rgb[cmax] - rgb[cmin];
Ivan Mahonin 1d641c
	double h = 0;
Ivan Mahonin 1d641c
	if (d > HELI_PRECISION) {
Ivan Mahonin 1d641c
		d = 1.0/d;
Ivan Mahonin 1d641c
		switch(cmax){
Ivan Mahonin 1d641c
		case 0: h = (rgb[1] - rgb[2])*d + 0; break;
Ivan Mahonin 1d641c
		case 1: h = (rgb[2] - rgb[0])*d + 2; break;
Ivan Mahonin 1d641c
		case 2: h = (rgb[0] - rgb[1])*d + 4; break;
Ivan Mahonin 1d641c
		}
Ivan Mahonin 1d641c
		h /= 6; h -= floor(h); h *= 360;
Ivan Mahonin 1d641c
	}
Ivan Mahonin 1d641c
	return h;
Ivan Mahonin 1d641c
}
Ivan Mahonin d6f40c
double colorGetSaturation(unsigned int colorCode) {
Ivan Mahonin d6f40c
	double rgb[] = { colorGetRed  (colorCode),
Ivan Mahonin d6f40c
	                 colorGetGreen(colorCode),
Ivan Mahonin d6f40c
	                 colorGetBlue (colorCode) };
Ivan Mahonin 1d641c
	int cmin = colorMin(rgb);
Ivan Mahonin 1d641c
	int cmax = colorMax(rgb);
Ivan Mahonin 1d641c
	return rgb[cmax] > HELI_PRECISION ? (rgb[cmax] - rgb[cmin])/rgb[cmax] : 0;
Ivan Mahonin 1d641c
}
Ivan Mahonin d6f40c
double colorGetValue(unsigned int colorCode) {
Ivan Mahonin d6f40c
	double rgb[] = { colorGetRed  (colorCode),
Ivan Mahonin d6f40c
	                 colorGetGreen(colorCode),
Ivan Mahonin d6f40c
	                 colorGetBlue (colorCode) };
Ivan Mahonin 1d641c
	return rgb[colorMax(rgb)];
Ivan Mahonin 1d641c
}
Ivan Mahonin 1d641c
Ivan Mahonin d4e89f
Ivan Mahonin 7ac038
unsigned int colorByNameA(const char *colorName, double a)
Ivan Mahonin 7ac038
	{ return colorWithAlpha(colorByName(colorName), a); }
Ivan Mahonin 7ac038
unsigned int colorByName(const char *colorName) {
Ivan Mahonin d4e89f
	unsigned int code = 0;
Ivan Mahonin 09c823
	
Ivan Mahonin d4e89f
	const char *x = colorName;
Ivan Mahonin 09c823
	if (*x == '#') {
Ivan Mahonin 09c823
		++x;
Ivan Mahonin 09c823
		int hex[8] = { 0, 0, 0, 0, 0, 0, 15, 15 };
Ivan Mahonin 59dae5
		for(int i = 0; *x && i < 8; ++i, ++x) {
Ivan Mahonin 09c823
			char c = tolower(*x);
Ivan Mahonin 09c823
			if (c >= '0' && c <= '9') hex[i] = c - '0';
Ivan Mahonin 09c823
			if (c >= 'a' && c <= 'f') hex[i] = c - 'a' + 10;
Ivan Mahonin 09c823
		}
Ivan Mahonin ca6bde
		for(int i = 0; i < 6; ++i)
Ivan Mahonin d4e89f
			code |= ( hex[i] << ((7-i)*4) );
Ivan Mahonin 7ac038
		code |= colorToInt( (hex[6]*16 + hex[7])/255.0 );
Ivan Mahonin 09c823
	} else
Ivan Mahonin 09c823
	if (isalpha(*x)) {
Ivan Mahonin 59dae5
		int count = (int)(sizeof(colors)/sizeof(*colors));
Ivan Mahonin bcaca0
		for(int i = 0; i < count; ++i)
Ivan Mahonin 7ac038
			if (heliStringCompareCi(x, colors[i].name) == 0)
Ivan Mahonin 7ac038
				return colors[i].code;
Ivan Mahonin 09c823
	} else {
Ivan Mahonin 7ac038
		double r = 0, g = 0, b = 0, a = 1;
Ivan Mahonin 7ac038
		sscanf(x, "%lf %lf %lf %lf", &r, &g, &b, &a);
Ivan Mahonin 7ac038
		code = colorByRGBA(r, g, b, a);
Ivan Mahonin 09c823
	}
Ivan Mahonin d4e89f
	return code;
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin 09c823
Ivan Mahonin 8eb855
static int objectsCompare(const void *a, const void *b)
Ivan Mahonin 8eb855
	{ return a < b ? -1 : b < a ? 1 : 0; }
Ivan Mahonin 8eb855
Ivan Mahonin 8eb855
static void* objectsKeyClone(void *k)
Ivan Mahonin 8eb855
	{ return k; }
Ivan Mahonin 8eb855
Ivan Mahonin 8eb855
void heliObjectRegister(void *o, HeliFreeCallback fo)
Ivan Mahonin 8eb855
	{ heliMapAdd(&heliObjectsSet, o, &objectsCompare, (HeliCloneCallback)objectsKeyClone, fo, NULL, NULL); }
Ivan Mahonin 8eb855
Ivan Mahonin 8eb855
void heliObjectUnregister(void *o) {
Ivan Mahonin 8eb855
	int i;
Ivan Mahonin 8eb855
	HeliPair *item = heliMapFind(&heliObjectsSet, o, &objectsCompare, &i);
Ivan Mahonin 8eb855
	if (item) {
Ivan Mahonin 8eb855
		item->freeKey = NULL;
Ivan Mahonin 8eb855
		heliArrayRemove(&heliObjectsSet, i);
Ivan Mahonin 8eb855
	}
Ivan Mahonin 8eb855
}