/* Some font have additional file with metrics information,
 * in general, the extension of the file is: .afm or .pfm
 */
char *blf_dir_metrics_search(const char *filename)
{
	char *mfile;
	char *s;

	mfile = BLI_strdup(filename);
	s = strrchr(mfile, '.');
	if (s) {
		if (BLI_strnlen(s, 4) < 4) {
			MEM_freeN(mfile);
			return NULL;
		}
		s++;
		s[0] = 'a';
		s[1] = 'f';
		s[2] = 'm';

		/* first check .afm */
		if (BLI_exists(mfile))
			return mfile;

		/* and now check .pfm */
		s[0] = 'p';

		if (BLI_exists(mfile))
			return mfile;
	}
	MEM_freeN(mfile);
	return NULL;
}
Exemple #2
0
/* simple appending of filename to dir, does not check for valid path! */
void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const char *file)
{
	size_t dirlen = BLI_strnlen(dir, maxlen);

	if (dst != dir) {
		if (dirlen == maxlen) {
			memcpy(dst, dir, dirlen);
			dst[dirlen - 1] = '\0';
			return; /* dir fills the path */
		}
		else {
			memcpy(dst, dir, dirlen + 1);
		}
	}

	if (dirlen + 1 >= maxlen) {
		return; /* fills the path */
	}

	/* inline BLI_add_slash */
	if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) {
		dst[dirlen++] = SEP;
		dst[dirlen] = '\0';
	}

	if (dirlen >= maxlen) {
		return; /* fills the path */
	}

	if (file == NULL) {
		return;
	}

	BLI_strncpy(dst + dirlen, file, maxlen - dirlen);
}
Exemple #3
0
StructRNA *rna_PropertyGroup_register(Main *UNUSED(bmain), ReportList *reports, void *data, const char *identifier,
                                      StructValidateFunc validate, StructCallbackFunc UNUSED(call),
                                      StructFreeFunc UNUSED(free))
{
	PointerRNA dummyptr;

	/* create dummy pointer */
	RNA_pointer_create(NULL, &RNA_PropertyGroup, NULL, &dummyptr);

	/* validate the python class */
	if (validate(&dummyptr, data, NULL) != 0)
		return NULL;

	/* note: it looks like there is no length limit on the srna id since its
	 * just a char pointer, but take care here, also be careful that python
	 * owns the string pointer which it could potentially free while blender
	 * is running. */
	if (BLI_strnlen(identifier, MAX_IDPROP_NAME) == MAX_IDPROP_NAME) {
		BKE_reportf(reports, RPT_ERROR, "Registering id property class: '%s' is too long, maximum length is %d",
		            identifier, MAX_IDPROP_NAME);
		return NULL;
	}

	return RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_PropertyGroup);  /* XXX */
}
Exemple #4
0
void BLI_clean(char *path)
{
#ifdef WIN32
	if (path && BLI_strnlen(path, 3) > 2) {
		BLI_char_switch(path + 2, '/', '\\');
	}
#else
	BLI_char_switch(path, '\\', '/');
#endif
}
Exemple #5
0
static int controller_add_exec(bContext *C, wmOperator *op)
{
	Object *ob;
	bController *cont;
	PointerRNA cont_ptr;
	PropertyRNA *prop;
	const char *cont_name;
	int bit;
	char name[32];
	int type= RNA_enum_get(op->ptr, "type");

	ob= edit_object_property_get(C, op);
	if(!ob)
		return OPERATOR_CANCELLED;
	
	cont= new_controller(type);
	BLI_addtail(&(ob->controllers), cont);
	
	/* set the controller name based on rna type enum */
	RNA_pointer_create((ID *)ob, &RNA_Controller, cont, &cont_ptr);
	prop = RNA_struct_find_property(&cont_ptr, "type");

	RNA_string_get(op->ptr, "name", name);
	if(BLI_strnlen(name, 32) < 1){
		RNA_property_enum_name(C, &cont_ptr, prop, RNA_property_enum_get(&cont_ptr, prop), &cont_name);
		BLI_strncpy(cont->name, cont_name, sizeof(cont->name));
	}
	else
		BLI_strncpy(cont->name, name, sizeof(cont->name));

	make_unique_prop_names(C, cont->name);
	/* set the controller state mask from the current object state.
	 A controller is always in a single state, so select the lowest bit set
	 from the object state */
	for (bit=0; bit<OB_MAX_STATES; bit++) {
		if (ob->state & (1<<bit))
			break;
	}
	cont->state_mask = (1<<bit);
	if (cont->state_mask == 0) {
		/* shouldn't happen, object state is never 0 */
		cont->state_mask = 1;
	}
	
	ob->scaflag |= OB_SHOWCONT;
	
	WM_event_add_notifier(C, NC_LOGIC, NULL);
	
	return OPERATOR_FINISHED;
}
/**
 * Copies the current working directory into *dir (max size maxncpy), and
 * returns a pointer to same.
 *
 * \note can return NULL when the size is not big enough
 */
char *BLI_current_working_dir(char *dir, const size_t maxncpy)
{
	const char *pwd = getenv("PWD");
	if (pwd) {
		size_t srclen = BLI_strnlen(pwd, maxncpy);
		if (srclen != maxncpy) {
			memcpy(dir, pwd, srclen + 1);
			return dir;
		}
		else {
			return NULL;
		}
	}

	return getcwd(dir, maxncpy);
}
Exemple #7
0
void BLI_dynstr_nappend(DynStr *ds, const char *cstr, int len) {
	DynStrElem *dse= malloc(sizeof(*dse));
	int cstrlen= BLI_strnlen(cstr, len);

	dse->str= malloc(cstrlen+1);
	memcpy(dse->str, cstr, cstrlen);
	dse->str[cstrlen] = '\0';
	dse->next= NULL;

	if (!ds->last)
		ds->last= ds->elems= dse;
	else
		ds->last= ds->last->next= dse;

	ds->curlen+= cstrlen;
}
Exemple #8
0
static Object *edit_object_property_get(bContext *C, wmOperator *op)
{
	char ob_name[32];
	Object *ob;

	RNA_string_get(op->ptr, "object", ob_name);

	/* if ob_name is valid try to find the object with this name
	otherwise gets the active object */
	if (BLI_strnlen(ob_name, 32) > 0)
		ob = BLI_findstring(&(CTX_data_main(C)->object), ob_name, offsetof(ID, name) + 2);
	else
		ob= ED_object_active_context(C);

	return ob;
}
Exemple #9
0
void BKE_deform_split_suffix(const char string[MAX_VGROUP_NAME], char body[MAX_VGROUP_NAME], char suf[MAX_VGROUP_NAME])
{
	size_t len = BLI_strnlen(string, MAX_VGROUP_NAME);
	size_t i;

	body[0] = suf[0] = '\0';

	for (i = len; i > 0; i--) {
		if (is_char_sep(string[i])) {
			BLI_strncpy(body, string, i + 1);
			BLI_strncpy(suf, string + i,  (len + 1) - i);
			return;
		}
	}

	memcpy(body, string, len + 1);
}
Exemple #10
0
static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *UNUSED(closure))
{
    char *st;
    if (!PyUnicode_Check(value)) {
        PyErr_SetString(PyExc_TypeError, "expected a string!");
        return -1;
    }

    st = _PyUnicode_AsString(value);
    if (BLI_strnlen(st, MAX_IDPROP_NAME) == MAX_IDPROP_NAME) {
        PyErr_SetString(PyExc_TypeError, "string length cannot exceed 31 characters!");
        return -1;
    }

    BLI_strncpy(self->prop->name, st, sizeof(self->prop->name));
    return 0;
}
Exemple #11
0
/* "a.b.c" -> ("a.", "b.c") */
void BKE_deform_split_prefix(const char string[MAX_VGROUP_NAME], char pre[MAX_VGROUP_NAME], char body[MAX_VGROUP_NAME])
{
	size_t len = BLI_strnlen(string, MAX_VGROUP_NAME);
	size_t i;

	body[0] = pre[0] = '\0';

	for (i = 1; i < len; i++) {
		if (is_char_sep(string[i])) {
			i++;
			BLI_strncpy(pre, string, i + 1);
			BLI_strncpy(body, string + i, (len + 1) - i);
			return;
		}
	}

	BLI_strncpy(body, string, len);
}
Exemple #12
0
static int actuator_add_exec(bContext *C, wmOperator *op)
{
	Object *ob;
	bActuator *act;
	PointerRNA act_ptr;
	PropertyRNA *prop;
	const char *act_name;
	char  name[32];
	int type= RNA_enum_get(op->ptr, "type");
		
	ob= edit_object_property_get(C, op);
	if(!ob)
		return OPERATOR_CANCELLED;

	act= new_actuator(type);
	BLI_addtail(&(ob->actuators), act);
	
	/* set the actuator name based on rna type enum */
	RNA_pointer_create((ID *)ob, &RNA_Actuator, act, &act_ptr);
	prop = RNA_struct_find_property(&act_ptr, "type");

	RNA_string_get(op->ptr, "name", name);
	if (BLI_strnlen(name, 32) < 1){
		RNA_property_enum_name(C, &act_ptr, prop, RNA_property_enum_get(&act_ptr, prop), &act_name);
		BLI_strncpy(act->name, act_name, sizeof(act->name));
	}
	else
		BLI_strncpy(act->name, name, sizeof(act->name));

	make_unique_prop_names(C, act->name);
	ob->scaflag |= OB_SHOWACT;
	
	WM_event_add_notifier(C, NC_LOGIC, NULL);
	
	return OPERATOR_FINISHED;
}
Exemple #13
0
static void fill_locales(void)
{
	const char * const languages_path = BKE_appdir_folder_id(BLENDER_DATAFILES, "locale");
	char languages[FILE_MAX];
	LinkNode *lines = NULL, *line;
	char *str;
	int idx = 0;

	free_locales();

	BLI_join_dirfile(languages, FILE_MAX, languages_path, "languages");
	line = lines = BLI_file_read_as_lines(languages);

	/* This whole "parsing" code is a bit weak, in that it expects strictly formatted input file...
	 * Should not be a problem, though, as this file is script-generated! */

	/* First loop to find highest locale ID */
	while (line) {
		int t;
		str = (char *)line->link;
		if (str[0] == '#' || str[0] == '\0') {
			line = line->next;
			continue; /* Comment or void... */
		}
		t = atoi(str);
		if (t >= num_locales)
			num_locales = t + 1;
		num_locales_menu++;
		line = line->next;
	}
	num_locales_menu++; /* The "closing" void item... */

	/* And now, build locales and locale_menu! */
	locales_menu = MEM_callocN(num_locales_menu * sizeof(EnumPropertyItem), __func__);
	line = lines;
	/* Do not allocate locales with zero-sized mem, as LOCALE macro uses NULL locales as invalid marker! */
	if (num_locales > 0) {
		locales = MEM_callocN(num_locales * sizeof(char *), __func__);
		while (line) {
			int id;
			char *loc, *sep1, *sep2, *sep3;

			str = (char *)line->link;
			if (str[0] == '#' || str[0] == '\0') {
				line = line->next;
				continue;
			}

			id = atoi(str);
			sep1 = strchr(str, ':');
			if (sep1) {
				sep1++;
				sep2 = strchr(sep1, ':');
				if (sep2) {
					locales_menu[idx].value = id;
					locales_menu[idx].icon = 0;
					locales_menu[idx].name = BLI_strdupn(sep1, sep2 - sep1);

					sep2++;
					sep3 = strchr(sep2, ':');

					if (sep3) {
						locales_menu[idx].identifier = loc = BLI_strdupn(sep2, sep3 - sep2);
					}
					else {
						locales_menu[idx].identifier = loc = BLI_strdup(sep2);
					}

					if (id == 0) {
						/* The DEFAULT item... */
						if (BLI_strnlen(loc, 2)) {
							locales[id] = locales_menu[idx].description = BLI_strdup("");
						}
						/* Menu "label", not to be stored in locales! */
						else {
							locales_menu[idx].description = BLI_strdup("");
						}
					}
					else {
						locales[id] = locales_menu[idx].description = BLI_strdup(loc);
					}
					idx++;
				}
			}

			line = line->next;
		}
	}

	/* Add closing item to menu! */
	locales_menu[idx].identifier = NULL;
	locales_menu[idx].value = locales_menu[idx].icon = 0;
	locales_menu[idx].name = locales_menu[idx].description = "";

	BLI_file_free_lines(lines);
}
Exemple #14
0
void BLI_path_rel(char *file, const char *relfile)
{
	char *lslash;
	char temp[FILE_MAX];
	char res[FILE_MAX];
	
	/* if file is already relative, bail out */
	if (BLI_path_is_rel(file)) {
		return;
	}
	
	/* also bail out if relative path is not set */
	if (relfile[0] == '\0') {
		return;
	}

#ifdef WIN32
	if (BLI_strnlen(relfile, 3) > 2 && relfile[1] != ':') {
		char *ptemp;
		/* fix missing volume name in relative base,
		 * can happen with old recent-files.txt files */
		get_default_root(temp);
		ptemp = &temp[2];
		if (relfile[0] != '\\' && relfile[0] != '/') {
			ptemp++;
		}
		BLI_strncpy(ptemp, relfile, FILE_MAX - 3);
	}
	else {
		BLI_strncpy(temp, relfile, FILE_MAX);
	}

	if (BLI_strnlen(file, 3) > 2) {
		if (temp[1] == ':' && file[1] == ':' && temp[0] != file[0])
			return;
	}
#else
	BLI_strncpy(temp, relfile, FILE_MAX);
#endif

	BLI_char_switch(temp, '\\', '/');
	BLI_char_switch(file, '\\', '/');
	
	/* remove /./ which confuse the following slash counting... */
	BLI_cleanup_path(NULL, file);
	BLI_cleanup_path(NULL, temp);
	
	/* the last slash in the file indicates where the path part ends */
	lslash = BLI_last_slash(temp);

	if (lslash) {
		/* find the prefix of the filename that is equal for both filenames.
		 * This is replaced by the two slashes at the beginning */
		char *p = temp;
		char *q = file;

#ifdef WIN32
		while (tolower(*p) == tolower(*q))
#else
		while (*p == *q)
#endif
		{
			p++;
			q++;

			/* don't search beyond the end of the string
			 * in the rare case they match */
			if ((*p == '\0') || (*q == '\0')) {
				break;
			}
		}

		/* we might have passed the slash when the beginning of a dir matches 
		 * so we rewind. Only check on the actual filename
		 */
		if (*q != '/') {
			while ( (q >= file) && (*q != '/') ) { --q; --p; }
		}
		else if (*p != '/') {
			while ( (p >= temp) && (*p != '/') ) { --p; --q; }
		}
		
		strcpy(res, "//");

		/* p now points to the slash that is at the beginning of the part
		 * where the path is different from the relative path. 
		 * We count the number of directories we need to go up in the
		 * hierarchy to arrive at the common 'prefix' of the path
		 */
		while (p && p < lslash) {
			if (*p == '/') 
				strcat(res, "../");
			p++;
		}

		strcat(res, q + 1); /* don't copy the slash at the beginning */
		
#ifdef  WIN32
		BLI_char_switch(res + 2, '/', '\\');
#endif
		strcpy(file, res);
	}
}
Exemple #15
0
/* if strip_number: removes number extensions
 * note: don't use sizeof() for 'name' or 'from_name' */
void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME],
                               const bool strip_number)
{
	int     len;
	char    prefix[MAX_VGROUP_NAME]  = "";   /* The part before the facing */
	char    suffix[MAX_VGROUP_NAME]  = "";   /* The part after the facing */
	char    replace[MAX_VGROUP_NAME] = "";   /* The replacement string */
	char    number[MAX_VGROUP_NAME]  = "";   /* The number extension string */
	char    *index = NULL;
	bool is_set = false;

	/* always copy the name, since this can be called with an uninitialized string */
	BLI_strncpy(name, from_name, MAX_VGROUP_NAME);

	len = BLI_strnlen(from_name, MAX_VGROUP_NAME);
	if (len < 3) {
		/* we don't do names like .R or .L */
		return;
	}

	/* We first check the case with a .### extension, let's find the last period */
	if (isdigit(name[len - 1])) {
		index = strrchr(name, '.'); // last occurrence
		if (index && isdigit(index[1])) { // doesnt handle case bone.1abc2 correct..., whatever!
			if (strip_number == false) {
				BLI_strncpy(number, index, sizeof(number));
			}
			*index = 0;
			len = BLI_strnlen(name, MAX_VGROUP_NAME);
		}
	}

	BLI_strncpy(prefix, name, sizeof(prefix));

	/* first case; separator . - _ with extensions r R l L  */
	if ((len > 1) && is_char_sep(name[len - 2])) {
		is_set = true;
		switch (name[len - 1]) {
			case 'l':
				prefix[len - 1] = 0;
				strcpy(replace, "r");
				break;
			case 'r':
				prefix[len - 1] = 0;
				strcpy(replace, "l");
				break;
			case 'L':
				prefix[len - 1] = 0;
				strcpy(replace, "R");
				break;
			case 'R':
				prefix[len - 1] = 0;
				strcpy(replace, "L");
				break;
			default:
				is_set = false;
		}
	}

	/* case; beginning with r R l L, with separator after it */
	if (!is_set && is_char_sep(name[1])) {
		is_set = true;
		switch (name[0]) {
			case 'l':
				strcpy(replace, "r");
				BLI_strncpy(suffix, name + 1, sizeof(suffix));
				prefix[0] = 0;
				break;
			case 'r':
				strcpy(replace, "l");
				BLI_strncpy(suffix, name + 1, sizeof(suffix));
				prefix[0] = 0;
				break;
			case 'L':
				strcpy(replace, "R");
				BLI_strncpy(suffix, name + 1, sizeof(suffix));
				prefix[0] = 0;
				break;
			case 'R':
				strcpy(replace, "L");
				BLI_strncpy(suffix, name + 1, sizeof(suffix));
				prefix[0] = 0;
				break;
			default:
				is_set = false;
		}
	}

	if (!is_set && len > 5) {
		/* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
		if (((index = BLI_strcasestr(prefix, "right")) == prefix) ||
		    (index == prefix + len - 5))
		{
			is_set = true;
			if (index[0] == 'r') {
				strcpy(replace, "left");
			}
			else {
				strcpy(replace, (index[1] == 'I') ? "LEFT" : "Left");
			}
			*index = 0;
			BLI_strncpy(suffix, index + 5, sizeof(suffix));
		}
		else if (((index = BLI_strcasestr(prefix, "left")) == prefix) ||
		         (index == prefix + len - 4))
		{
			is_set = true;
			if (index[0] == 'l') {
				strcpy(replace, "right");
			}
			else {
				strcpy(replace, (index[1] == 'E') ? "RIGHT" : "Right");
			}
			*index = 0;
			BLI_strncpy(suffix, index + 4, sizeof(suffix));
		}
	}

	(void)is_set;  /* quiet warning */

	BLI_snprintf(name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
}
Exemple #16
0
void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file)
{
	int sl;

	if (string) {
		/* ensure this is always set even if dir/file are NULL */
		string[0] = '\0';

		if (ELEM(NULL, dir, file)) {
			return; /* We don't want any NULLs */
		}
	}
	else {
		return; /* string is NULL, probably shouldnt happen but return anyway */
	}


	/* we first push all slashes into unix mode, just to make sure we don't get
	 * any mess with slashes later on. -jesterKing */
	/* constant strings can be passed for those parameters - don't change them - elubie */
#if 0
	BLI_char_switch(relabase, '\\', '/');
	BLI_char_switch(dir, '\\', '/');
	BLI_char_switch(file, '\\', '/');
#endif

	/* 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 = BLI_last_slash(string);
		if (lslash) *(lslash + 1) = 0;

		dir += 2; /* Skip over the relative reference */
	}
#ifdef WIN32
	else {
		if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':') {
			BLI_strncpy(string, dir, 3);
			dir += 2;
		}
		else { /* no drive specified */
			   /* first option: get the drive from the relabase if it has one */
			if (relabase && strlen(relabase) >= 2 && relabase[1] == ':') {
				BLI_strncpy(string, relabase, 3);
				string[2] = '\\';
				string[3] = '\0';
			}
			else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
				get_default_root(string);
			}
			
			/* ignore leading slashes */
			while (*dir == '/' || *dir == '\\') dir++;
		}
	}
#endif

	strcat(string, dir);

	/* Make sure string ends in one (and only one) slash */
	/* first trim all slashes from the end of the string */
	sl = strlen(string);
	while (sl > 0 && (string[sl - 1] == '/' || string[sl - 1] == '\\') ) {
		string[sl - 1] = '\0';
		sl--;
	}
	/* since we've now removed all slashes, put back one slash at the end. */
	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 */
	BLI_clean(string);
}
Exemple #17
0
size_t blf_font_width_to_rstrlen(FontBLF *font, const char *str, size_t len, float width, float *r_width)
{
	unsigned int c;
	GlyphBLF *g, *g_prev = NULL;
	FT_Vector delta;
	int pen_x = 0;
	size_t i = 0, i_prev;
	GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
	const int width_i = (int)width + 1;
	int width_new;

	bool is_malloc;
	int (*width_accum)[2];
	int width_accum_ofs = 0;

	BLF_KERNING_VARS(font, has_kerning, kern_mode);

	/* skip allocs in simple cases */
	len = BLI_strnlen(str, len);
	if (width_i <= 1 || len == 0) {
		if (r_width) {
			*r_width = 0.0f;
		}
		return len;
	}

	if (len < 2048) {
		width_accum = BLI_array_alloca(width_accum, len);
		is_malloc = false;
	}
	else {
		width_accum = MEM_mallocN(sizeof(*width_accum) * len, __func__);
		is_malloc = true;
	}

	blf_font_ensure_ascii_table(font);

	while ((i < len) && str[i]) {
		BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);

		if (UNLIKELY(c == BLI_UTF8_ERR))
			break;
		if (UNLIKELY(g == NULL))
			continue;
		if (has_kerning)
			BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);

		pen_x += g->advance_i;

		width_accum[width_accum_ofs][0] = (int)i;
		width_accum[width_accum_ofs][1] = pen_x;
		width_accum_ofs++;

		g_prev = g;
	}

	if (pen_x > width_i && width_accum_ofs != 0) {
		const int min_x = pen_x - width_i;

		/* search backwards */
		width_new = pen_x;
		while (width_accum_ofs-- > 0) {
			if (min_x > width_accum[width_accum_ofs][1]) {
				break;
			}
		}
		width_accum_ofs++;
		width_new = pen_x - width_accum[width_accum_ofs][1];
		i_prev = (size_t)width_accum[width_accum_ofs][0];
	}
	else {
		width_new = pen_x;
		i_prev = 0;
	}

	if (is_malloc) {
		MEM_freeN(width_accum);
	}

	if (r_width) {
		*r_width = (float)width_new;
	}

	return i_prev;
}
Exemple #18
0
/* if strip_number: removes number extensions
 * note: dont use sizeof() for 'name' or 'from_name' */
void flip_side_name (char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME], int strip_number)
{
	int     len;
	char    prefix[MAX_VGROUP_NAME]=  "";   /* The part before the facing */
	char    suffix[MAX_VGROUP_NAME]=  "";   /* The part after the facing */
	char    replace[MAX_VGROUP_NAME]= "";   /* The replacement string */
	char    number[MAX_VGROUP_NAME]=  "";   /* The number extension string */
	char    *index=NULL;

	len= BLI_strnlen(from_name, MAX_VGROUP_NAME);
	if(len<3) return; // we don't do names like .R or .L

	BLI_strncpy(name, from_name, MAX_VGROUP_NAME);

	/* We first check the case with a .### extension, let's find the last period */
	if(isdigit(name[len-1])) {
		index= strrchr(name, '.'); // last occurrence
		if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
			if(strip_number==0)
				BLI_strncpy(number, index, sizeof(number));
			*index= 0;
			len= BLI_strnlen(name, MAX_VGROUP_NAME);
		}
	}

	BLI_strncpy(prefix, name, sizeof(prefix));

#define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')

	/* first case; separator . - _ with extensions r R l L  */
	if( IS_SEPARATOR(name[len-2]) ) {
		switch(name[len-1]) {
			case 'l':
				prefix[len-1]= 0;
				strcpy(replace, "r");
				break;
			case 'r':
				prefix[len-1]= 0;
				strcpy(replace, "l");
				break;
			case 'L':
				prefix[len-1]= 0;
				strcpy(replace, "R");
				break;
			case 'R':
				prefix[len-1]= 0;
				strcpy(replace, "L");
				break;
		}
	}
	/* case; beginning with r R l L , with separator after it */
	else if( IS_SEPARATOR(name[1]) ) {
		switch(name[0]) {
			case 'l':
				strcpy(replace, "r");
				strcpy(suffix, name+1);
				prefix[0]= 0;
				break;
			case 'r':
				strcpy(replace, "l");
				strcpy(suffix, name+1);
				prefix[0]= 0;
				break;
			case 'L':
				strcpy(replace, "R");
				strcpy(suffix, name+1);
				prefix[0]= 0;
				break;
			case 'R':
				strcpy(replace, "L");
				strcpy(suffix, name+1);
				prefix[0]= 0;
				break;
		}
	}
	else if(len > 5) {
		/* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
		index = BLI_strcasestr(prefix, "right");
		if (index==prefix || index==prefix+len-5) {
			if(index[0]=='r')
				strcpy (replace, "left");
			else {
				if(index[1]=='I')
					strcpy (replace, "LEFT");
				else
					strcpy (replace, "Left");
			}
			*index= 0;
			strcpy (suffix, index+5);
		}
		else {
			index = BLI_strcasestr(prefix, "left");
			if (index==prefix || index==prefix+len-4) {
				if(index[0]=='l')
					strcpy (replace, "right");
				else {
					if(index[1]=='E')
						strcpy (replace, "RIGHT");
					else
						strcpy (replace, "Right");
				}
				*index= 0;
				strcpy (suffix, index+4);
			}
		}
	}

#undef IS_SEPARATOR

	BLI_snprintf (name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
}