void BLT_lang_set(const char *str) { #ifdef WITH_INTERNATIONAL int ulang = ULANGUAGE; const char *short_locale = str ? str : LOCALE(ulang); const char *short_locale_utf8 = NULL; if ((U.transopts & USER_DOTRANSLATE) == 0) return; /* We want to avoid locales like '.UTF-8'! */ if (short_locale[0]) { /* Hurrey! encoding needs to be placed *before* variant! */ char *variant = strchr(short_locale, '@'); if (variant) { char *locale = BLI_strdupn(short_locale, variant - short_locale); short_locale_utf8 = BLI_sprintfN("%s.UTF-8%s", locale, variant); MEM_freeN(locale); } else { short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale); } bl_locale_set(short_locale_utf8); MEM_freeN((void *)short_locale_utf8); } else { bl_locale_set(short_locale); } #else (void)str; #endif blt_lang_check_ime_supported(); }
/* Get locale's elements (if relevant pointer is not NULL and element actually exists, e.g. if there is no variant, * *variant and *language_variant will always be NULL). * Non-null elements are always MEM_mallocN'ed, it's the caller's responsibility to free them. * NOTE: Keep that one always available, you never know, may become useful even in no-WITH_INTERNATIONAL context... */ void BLT_lang_locale_explode( const char *locale, char **language, char **country, char **variant, char **language_country, char **language_variant) { char *m1, *m2, *_t = NULL; m1 = strchr(locale, '_'); m2 = strchr(locale, '@'); if (language || language_variant) { if (m1 || m2) { _t = m1 ? BLI_strdupn(locale, m1 - locale) : BLI_strdupn(locale, m2 - locale); if (language) *language = _t; } else if (language) { *language = BLI_strdup(locale); } } if (country) { if (m1) *country = m2 ? BLI_strdupn(m1 + 1, m2 - (m1 + 1)) : BLI_strdup(m1 + 1); else *country = NULL; } if (variant) { if (m2) *variant = BLI_strdup(m2 + 1); else *variant = NULL; } if (language_country) { if (m1) *language_country = m2 ? BLI_strdupn(locale, m2 - locale) : BLI_strdup(locale); else *language_country = NULL; } if (language_variant) { if (m2) *language_variant = m1 ? BLI_strdupcat(_t, m2) : BLI_strdup(locale); else *language_variant = NULL; } if (_t && !language) { MEM_freeN(_t); } }
/* Makes a copy of the text within the "" that appear after some text 'blahblah' * i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples" * * - str: is the entire string to chop * - prefix: is the part of the string to leave out * * Assume that the strings returned must be freed afterwards, and that the inputs will contain * data we want... */ char *BLI_getQuotedStr (const char *str, const char *prefix) { int prefixLen = strlen(prefix); char *startMatch, *endMatch; /* get the starting point (i.e. where prefix starts, and add prefixLen+1 to it to get be after the first " */ startMatch= strstr(str, prefix) + prefixLen + 1; /* get the end point (i.e. where the next occurance of " is after the starting point) */ endMatch= strchr(startMatch, '"'); // " NOTE: this comment here is just so that my text editor still shows the functions ok... /* return the slice indicated */ return BLI_strdupn(startMatch, (int)(endMatch-startMatch)); }
/* Get (or add relevant data to be able to do so) F-Curve from the driver stack, * for the given Animation Data block. This assumes that all the destinations are valid. * * - add: 0 - don't add anything if not found, * 1 - add new Driver FCurve, * -1 - add new Driver FCurve without driver stuff (for pasting) */ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add) { AnimData *adt; FCurve *fcu; /* sanity checks */ if ELEM(NULL, id, rna_path) return NULL; /* init animdata if none available yet */ adt= BKE_animdata_from_id(id); if ((adt == NULL) && (add)) adt= BKE_id_add_animdata(id); if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ return NULL; } /* try to find f-curve matching for this setting * - add if not found and allowed to add one * TODO: add auto-grouping support? how this works will need to be resolved */ fcu= list_find_fcurve(&adt->drivers, rna_path, array_index); if ((fcu == NULL) && (add)) { /* use default settings to make a F-Curve */ fcu= MEM_callocN(sizeof(FCurve), "FCurve"); fcu->flag = (FCURVE_VISIBLE|FCURVE_SELECTED); /* store path - make copy, and store that */ fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path)); fcu->array_index= array_index; /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */ if (add > 0) { /* add some new driver data */ fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); /* add simple generator modifier for driver so that there is some visible representation */ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); } /* just add F-Curve to end of driver list */ BLI_addtail(&adt->drivers, fcu); } /* return the F-Curve */ return fcu; }
/** * Reads the contents of a text file and returns the lines in a linked list. */ LinkNode *BLI_file_read_as_lines(const char *name) { FILE *fp = BLI_fopen(name, "r"); LinkNodePair lines = {NULL, NULL}; char *buf; size_t size; if (!fp) return NULL; fseek(fp, 0, SEEK_END); size = (size_t)ftell(fp); fseek(fp, 0, SEEK_SET); if (UNLIKELY(size == (size_t)-1)) { fclose(fp); return NULL; } buf = MEM_mallocN(size, "file_as_lines"); if (buf) { size_t i, last = 0; /* * size = because on win32 reading * all the bytes in the file will return * less bytes because of crnl changes. */ size = fread(buf, 1, size, fp); for (i = 0; i <= size; i++) { if (i == size || buf[i] == '\n') { char *line = BLI_strdupn(&buf[last], i - last); BLI_linklist_append(&lines, line); /* faster to build singly-linked list in reverse order */ /* alternatively, could process buffer in reverse order so * list ends up right way round to start with */ last = i + 1; } } MEM_freeN(buf); } fclose(fp); return lines.list; }
/** * Reads the contents of a text file and returns the lines in a linked list. */ LinkNode *BLI_file_read_as_lines(const char *name) { FILE *fp = BLI_fopen(name, "r"); LinkNodePair lines = {NULL, NULL}; char *buf; size_t size; if (!fp) return NULL; fseek(fp, 0, SEEK_END); size = (size_t)ftell(fp); fseek(fp, 0, SEEK_SET); if (UNLIKELY(size == (size_t)-1)) { fclose(fp); return NULL; } buf = MEM_mallocN(size, "file_as_lines"); if (buf) { size_t i, last = 0; /* * size = because on win32 reading * all the bytes in the file will return * less bytes because of `CRNL` changes. */ size = fread(buf, 1, size, fp); for (i = 0; i <= size; i++) { if (i == size || buf[i] == '\n') { char *line = BLI_strdupn(&buf[last], i - last); BLI_linklist_append(&lines, line); last = i + 1; } } MEM_freeN(buf); } fclose(fp); return lines.list; }
static ConsoleLine *console_lb_add__internal(ListBase *lb, ConsoleLine *from) { ConsoleLine *ci = MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add"); if (from) { BLI_assert(strlen(from->line) == from->len); ci->line = BLI_strdupn(from->line, from->len); ci->len = ci->len_alloc = from->len; ci->cursor = from->cursor; ci->type = from->type; } else { ci->line = MEM_callocN(64, "console-in-line"); ci->len_alloc = 64; ci->len = 0; } BLI_addtail(lb, ci); return ci; }
LinkNode *BLI_read_file_as_lines(const char *name) { FILE *fp= fopen(name, "r"); LinkNode *lines= NULL; char *buf; int size; if (!fp) return NULL; fseek(fp, 0, SEEK_END); size= ftell(fp); fseek(fp, 0, SEEK_SET); buf= MEM_mallocN(size, "file_as_lines"); if (buf) { int i, last= 0; /* * size = because on win32 reading * all the bytes in the file will return * less bytes because of crnl changes. */ size= fread(buf, 1, size, fp); for (i=0; i<=size; i++) { if (i==size || buf[i]=='\n') { char *line= BLI_strdupn(&buf[last], i-last); BLI_linklist_prepend(&lines, line); last= i+1; } } MEM_freeN(buf); } fclose(fp); BLI_linklist_reverse(&lines); return lines; }
/** * Duplicates the cstring \a str into a newly mallocN'd * string and returns it. * * \param str The string to be duplicated * \retval Returns the duplicated string */ char *BLI_strdup(const char *str) { return BLI_strdupn(str, strlen(str)); }
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); }
/* Get (or add relevant data to be able to do so) F-Curve from the driver stack, * for the given Animation Data block. This assumes that all the destinations are valid. * * - add: 0 - don't add anything if not found, * 1 - add new Driver FCurve (with keyframes for visual tweaking), * 2 - add new Driver FCurve (with generator, for script backwards compatibility) * -1 - add new Driver FCurve without driver stuff (for pasting) */ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, short add) { AnimData *adt; FCurve *fcu; /* sanity checks */ if (ELEM(NULL, id, rna_path)) return NULL; /* init animdata if none available yet */ adt = BKE_animdata_from_id(id); if ((adt == NULL) && (add)) adt = BKE_id_add_animdata(id); if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ return NULL; } /* try to find f-curve matching for this setting * - add if not found and allowed to add one * TODO: add auto-grouping support? how this works will need to be resolved */ fcu = list_find_fcurve(&adt->drivers, rna_path, array_index); if ((fcu == NULL) && (add)) { /* use default settings to make a F-Curve */ fcu = MEM_callocN(sizeof(FCurve), "FCurve"); fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED); /* store path - make copy, and store that */ fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); fcu->array_index = array_index; /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */ if (add > 0) { BezTriple *bezt; size_t i; /* add some new driver data */ fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); fcu->driver->flag |= DRIVER_FLAG_SHOWDEBUG; /* F-Modifier or Keyframes? */ // FIXME: replace these magic numbers with defines if (add == 2) { /* Python API Backwards compatibility hack: * Create FModifier so that old scripts won't break * for now before 2.7 series -- (September 4, 2013) */ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); } else { /* add 2 keyframes so that user has something to work with * - These are configured to 0,0 and 1,1 to give a 1-1 mapping * which can be easily tweaked from there. */ insert_vert_fcurve(fcu, 0.0f, 0.0f, INSERTKEY_FAST); insert_vert_fcurve(fcu, 1.0f, 1.0f, INSERTKEY_FAST); /* configure this curve to extrapolate */ for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) { bezt->h1 = bezt->h2 = HD_VECT; } fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; calchandles_fcurve(fcu); } } /* just add F-Curve to end of driver list */ BLI_addtail(&adt->drivers, fcu); } /* return the F-Curve */ return fcu; }
static GHash *text_autocomplete_build(Text *text) { GHash *gh; int seek_len = 0; const char *seek; texttool_text_clear(); texttool_text_set_active(text); /* first get the word we're at */ { const int i = text_find_identifier_start(text->curl->line, text->curc); seek_len = text->curc - i; seek = text->curl->line + i; // BLI_strncpy(seek, seek_ptr, seek_len); } /* now walk over entire doc and suggest words */ { TextLine *linep; gh = BLI_ghash_str_new(__func__); for (linep = text->lines.first; linep; linep = linep->next) { size_t i_start = 0; size_t i_end = 0; size_t i_pos = 0; while (i_start < linep->len) { /* seek identifier beginning */ i_pos = i_start; while ((i_start < linep->len) && (!text_check_identifier_nodigit_unicode(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_start], &i_pos)))) { i_start = i_pos; } i_pos = i_end = i_start; while ((i_end < linep->len) && (text_check_identifier_unicode(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_end], &i_pos)))) { i_end = i_pos; } if ((i_start != i_end) && /* check we're at the beginning of a line or that the previous char is not an identifier * this prevents digits from being added */ ((i_start < 1) || !text_check_identifier_unicode(BLI_str_utf8_as_unicode(&linep->line[i_start - 1])))) { char *str_sub = &linep->line[i_start]; const int choice_len = i_end - i_start; if ((choice_len > seek_len) && (seek_len == 0 || STREQLEN(seek, str_sub, seek_len)) && (seek != str_sub)) { // printf("Adding: %s\n", s); char str_sub_last = str_sub[choice_len]; str_sub[choice_len] = '\0'; if (!BLI_ghash_lookup(gh, str_sub)) { char *str_dup = BLI_strdupn(str_sub, choice_len); BLI_ghash_insert(gh, str_dup, str_dup); /* A 'set' would make more sense here */ } str_sub[choice_len] = str_sub_last; } } if (i_end != i_start) { i_start = i_end; } else { /* highly unlikely, but prevent eternal loop */ i_start++; } } } { GHashIterator gh_iter; /* get the formatter for highlighting */ TextFormatType *tft; tft = ED_text_format_get(text); GHASH_ITER (gh_iter, gh) { const char *s = BLI_ghashIterator_getValue(&gh_iter); texttool_suggest_add(s, tft->format_identifier(s)); } } } texttool_suggest_prefix(seek, seek_len); return gh; }
static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int flags) { JSAMPARRAY row_pointer; JSAMPLE *buffer = NULL; int row_stride; int x, y, depth, r, g, b, k; struct ImBuf *ibuf = NULL; uchar *rect; jpeg_saved_marker_ptr marker; char *str, *key, *value; /* install own app1 handler */ ibuf_quality = jpeg_default_quality; jpeg_set_marker_processor(cinfo, 0xe1, handle_app1); cinfo->dct_method = JDCT_FLOAT; jpeg_save_markers(cinfo, JPEG_COM, 0xffff); if (jpeg_read_header(cinfo, false) == JPEG_HEADER_OK) { x = cinfo->image_width; y = cinfo->image_height; depth = cinfo->num_components; if (cinfo->jpeg_color_space == JCS_YCCK) cinfo->out_color_space = JCS_CMYK; jpeg_start_decompress(cinfo); if (flags & IB_test) { jpeg_abort_decompress(cinfo); ibuf = IMB_allocImBuf(x, y, 8 * depth, 0); } else if ((ibuf = IMB_allocImBuf(x, y, 8 * depth, IB_rect)) == NULL) { jpeg_abort_decompress(cinfo); } else { row_stride = cinfo->output_width * depth; row_pointer = (*cinfo->mem->alloc_sarray)((j_common_ptr) cinfo, JPOOL_IMAGE, row_stride, 1); for (y = ibuf->y - 1; y >= 0; y--) { jpeg_read_scanlines(cinfo, row_pointer, 1); rect = (uchar *) (ibuf->rect + y * ibuf->x); buffer = row_pointer[0]; switch (depth) { case 1: for (x = ibuf->x; x > 0; x--) { rect[3] = 255; rect[0] = rect[1] = rect[2] = *buffer++; rect += 4; } break; case 3: for (x = ibuf->x; x > 0; x--) { rect[3] = 255; rect[0] = *buffer++; rect[1] = *buffer++; rect[2] = *buffer++; rect += 4; } break; case 4: for (x = ibuf->x; x > 0; x--) { r = *buffer++; g = *buffer++; b = *buffer++; k = *buffer++; r = (r * k) / 255; g = (g * k) / 255; b = (b * k) / 255; rect[3] = 255; rect[2] = b; rect[1] = g; rect[0] = r; rect += 4; } break; } } marker = cinfo->marker_list; while (marker) { if (marker->marker != JPEG_COM) goto next_stamp_marker; /* * JPEG marker strings are not null-terminated, * create a null-terminated copy before going further */ str = BLI_strdupn((char *)marker->data, marker->data_length); /* * Because JPEG format don't support the * pair "key/value" like PNG, we store the * stampinfo in a single "encode" string: * "Blender:key:value" * * That is why we need split it to the * common key/value here. */ if (!STREQLEN(str, "Blender", 7)) { /* * Maybe the file have text that * we don't know "what it's", in that * case we keep the text (with a * key "None"). * This is only for don't "lose" * the information when we write * it back to disk. */ IMB_metadata_ensure(&ibuf->metadata); IMB_metadata_set_field(ibuf->metadata, "None", str); ibuf->flags |= IB_metadata; MEM_freeN(str); goto next_stamp_marker; } key = strchr(str, ':'); /* * A little paranoid, but the file maybe * is broken... and a "extra" check is better * then segfault ;) */ if (!key) { MEM_freeN(str); goto next_stamp_marker; } key++; value = strchr(key, ':'); if (!value) { MEM_freeN(str); goto next_stamp_marker; } *value = '\0'; /* need finish the key string */ value++; IMB_metadata_ensure(&ibuf->metadata); IMB_metadata_set_field(ibuf->metadata, key, value); ibuf->flags |= IB_metadata; MEM_freeN(str); next_stamp_marker: marker = marker->next; } jpeg_finish_decompress(cinfo); } jpeg_destroy((j_common_ptr) cinfo); if (ibuf) { ibuf->ftype = IMB_FTYPE_JPG; ibuf->foptions.quality = MIN2(ibuf_quality, 100); } } return(ibuf); }