/* 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; }
/* 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); }
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 */ }
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 }
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); }
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; }
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; }
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); }
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; }
/* "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); }
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; }
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); }
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); } }
/* 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); }
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); }
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; }
/* 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); }