Example #1
0
void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...)
{
	DynStr *ds;
	Report *report;
	va_list args;

	if(G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
		va_start(args, format);
		vprintf(format, args);
		va_end(args);
		fprintf(stdout, "\n"); /* otherise each report needs to include a \n */
		fflush(stdout); /* this ensures the message is printed before a crash */
	}

	if(reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) {
		report= MEM_callocN(sizeof(Report), "Report");

		ds= BLI_dynstr_new();
		va_start(args, format);
		BLI_dynstr_vappendf(ds, format, args);
		va_end(args);

		report->message= BLI_dynstr_get_cstring(ds);
		report->len= BLI_dynstr_get_len(ds);
		BLI_dynstr_free(ds);

		report->type= type;
		report->typestr= report_type_str(type);

		BLI_addtail(&reports->list, report);
	}
}
Example #2
0
void BKE_reports_prependf(ReportList *reports, const char *_prepend, ...)
{
	Report *report;
	DynStr *ds;
	va_list args;
	const char *prepend = TIP_(_prepend);

	if (!reports)
		return;

	for (report = reports->list.first; report; report = report->next) {
		ds = BLI_dynstr_new();
		va_start(args, _prepend);
		BLI_dynstr_vappendf(ds, prepend, args);
		va_end(args);

		BLI_dynstr_append(ds, report->message);
		MEM_freeN((void *)report->message);

		report->message = BLI_dynstr_get_cstring(ds);
		report->len = BLI_dynstr_get_len(ds);

		BLI_dynstr_free(ds);
	}
}
Example #3
0
/* Build menu-string of available keying-sets (allocates memory for string)
 * NOTE: mode must not be longer than 64 chars
 */
char *ANIM_build_keyingsets_menu (ListBase *list, short for_edit)
{
	DynStr *pupds= BLI_dynstr_new();
	KeyingSet *ks;
	char buf[64];
	char *str;
	int i;
	
	/* add title first */
	BLI_dynstr_append(pupds, "Keying Sets%t|");
	
	/* add dummy entries for none-active */
	if (for_edit) { 
		BLI_dynstr_append(pupds, "Add New%x-1|");
		BLI_dynstr_append(pupds, " %x0|");
	}
	else
		BLI_dynstr_append(pupds, "No Keying Set%x0|");
	
	/* loop through keyingsets, adding them */
	for (ks=list->first, i=1; ks; ks=ks->next, i++) {
		if (for_edit == 0)
			BLI_dynstr_append(pupds, "KS: ");
		
		BLI_dynstr_append(pupds, ks->name);
		BLI_snprintf( buf, 64, "%%x%d%s", i, ((ks->next)?"|":"") );
		BLI_dynstr_append(pupds, buf);
	}
	
	/* convert to normal MEM_malloc'd string */
	str= BLI_dynstr_get_cstring(pupds);
	BLI_dynstr_free(pupds);
	
	return str;
}
static char *bmp_slots_as_args(const BMOSlotType slot_types[BMO_OP_MAX_SLOTS], const bool is_out)
{
	DynStr *dyn_str = BLI_dynstr_new();
	char *ret;

	int i = 0;

	while (*slot_types[i].name) {
		/* cut off '.out' by using a string size arg */
		const int name_len = is_out ?
		        (strchr(slot_types[i].name, '.') - slot_types[i].name) :
		        sizeof(slot_types[i].name);
		const char *value = "<Unknown>";
		switch (slot_types[i].type) {
			case BMO_OP_SLOT_BOOL:          value = "False"; break;
			case BMO_OP_SLOT_INT:           value = "0"; break;
			case BMO_OP_SLOT_FLT:           value = "0.0"; break;
			case BMO_OP_SLOT_PTR:           value = "None"; break;
			case BMO_OP_SLOT_MAT:           value = "Matrix()"; break;
			case BMO_OP_SLOT_VEC:           value = "Vector()"; break;
			case BMO_OP_SLOT_ELEMENT_BUF:   value =
			     (slot_types[i].subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) ? "None" : "[]"; break;
			case BMO_OP_SLOT_MAPPING:       value = "{}"; break;
		}
		BLI_dynstr_appendf(dyn_str, i ? ", %.*s=%s" : "%.*s=%s", name_len, slot_types[i].name, value);
		i++;
	}

	ret = BLI_dynstr_get_cstring(dyn_str);
	BLI_dynstr_free(dyn_str);
	return ret;
}
Example #5
0
static int report_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
	SpaceInfo *sinfo= CTX_wm_space_info(C);
	ReportList *reports= CTX_wm_reports(C);
	int report_mask= info_report_mask(sinfo);

	Report *report;

	DynStr *buf_dyn= BLI_dynstr_new();
	char *buf_str;

	for(report=reports->list.first; report; report= report->next) {
		if((report->type & report_mask) && (report->flag & SELECT)) {
			BLI_dynstr_append(buf_dyn, report->message);
			BLI_dynstr_append(buf_dyn, "\n");
		}
	}

	buf_str= BLI_dynstr_get_cstring(buf_dyn);
	BLI_dynstr_free(buf_dyn);

	WM_clipboard_text_set(buf_str, 0);

	MEM_freeN(buf_str);
	return OPERATOR_FINISHED;
}
Example #6
0
static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const char *UNUSED(name))
{
	DynStr *ds = BLI_dynstr_new();
	char *code;

	/*BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);*/

	codegen_set_unique_ids(nodes);
	codegen_print_uniforms_functions(ds, nodes);

	//if(G.f & G_DEBUG)
	//	BLI_dynstr_appendf(ds, "/* %s */\n", name);

	BLI_dynstr_append(ds, "void main(void)\n");
	BLI_dynstr_append(ds, "{\n");

	codegen_declare_tmps(ds, nodes);
	codegen_call_functions(ds, nodes, output);

	BLI_dynstr_append(ds, "}\n");

	/* create shader */
	code = BLI_dynstr_get_cstring(ds);
	BLI_dynstr_free(ds);

	//if(G.f & G_DEBUG) printf("%s\n", code);

	return code;
}
Example #7
0
static int console_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
	SpaceConsole *sc = CTX_wm_space_console(C);

	DynStr *buf_dyn;
	char *buf_str;
	
	ConsoleLine *cl;
	int sel[2];
	int offset = 0;

	ConsoleLine cl_dummy = {NULL};

	if (sc->sel_start == sc->sel_end)
		return OPERATOR_CANCELLED;

	console_scrollback_prompt_begin(sc, &cl_dummy);

	for (cl = sc->scrollback.first; cl; cl = cl->next) {
		offset += cl->len + 1;
	}

	if (offset == 0) {
		console_scrollback_prompt_end(sc, &cl_dummy);
		return OPERATOR_CANCELLED;
	}

	buf_dyn = BLI_dynstr_new();
	offset -= 1;
	sel[0] = offset - sc->sel_end;
	sel[1] = offset - sc->sel_start;

	for (cl = sc->scrollback.first; cl; cl = cl->next) {
		if (sel[0] <= cl->len && sel[1] >= 0) {
			int sta = max_ii(sel[0], 0);
			int end = min_ii(sel[1], cl->len);

			if (BLI_dynstr_get_len(buf_dyn))
				BLI_dynstr_append(buf_dyn, "\n");

			BLI_dynstr_nappend(buf_dyn, cl->line + sta, end - sta);
		}

		sel[0] -= cl->len + 1;
		sel[1] -= cl->len + 1;
	}

	buf_str = BLI_dynstr_get_cstring(buf_dyn);

	BLI_dynstr_free(buf_dyn);
	WM_clipboard_text_set(buf_str, 0);

	MEM_freeN(buf_str);

	console_scrollback_prompt_end(sc, &cl_dummy);

	return OPERATOR_FINISHED;
}
Example #8
0
char *BPy_enum_as_string(EnumPropertyItem *item)
{
	DynStr *dynstr = BLI_dynstr_new();
	EnumPropertyItem *e;
	char *cstring;

	for (e = item; item->identifier; item++) {
		if (item->identifier[0])
			BLI_dynstr_appendf(dynstr, (e == item) ? "'%s'" : ", '%s'", item->identifier);
	}

	cstring = BLI_dynstr_get_cstring(dynstr);
	BLI_dynstr_free(dynstr);
	return cstring;
}
Example #9
0
static char *gpu_generate_function_prototyps(GHash *hash)
{
	DynStr *ds = BLI_dynstr_new();
	GHashIterator *ghi;
	GPUFunction *function;
	char *name, *prototypes;
	int a;
	
	/* automatically generate function prototypes to add to the top of the
	 * generated code, to avoid have to add the actual code & recompile all */
	ghi = BLI_ghashIterator_new(hash);

	for (; !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) {
		name = BLI_ghashIterator_getValue(ghi);
		function = BLI_ghashIterator_getValue(ghi);

		BLI_dynstr_appendf(ds, "void %s(", name);
		for (a = 0; a < function->totparam; a++) {
			if (function->paramqual[a] == FUNCTION_QUAL_OUT)
				BLI_dynstr_append(ds, "out ");
			else if (function->paramqual[a] == FUNCTION_QUAL_INOUT)
				BLI_dynstr_append(ds, "inout ");

			if (function->paramtype[a] == GPU_TEX2D)
				BLI_dynstr_append(ds, "sampler2D");
			else if (function->paramtype[a] == GPU_SHADOW2D)
				BLI_dynstr_append(ds, "sampler2DShadow");
			else
				BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
#  if 0
			BLI_dynstr_appendf(ds, " param%d", a);
#  endif

			if (a != function->totparam-1)
				BLI_dynstr_append(ds, ", ");
		}
		BLI_dynstr_append(ds, ");\n");
	}

	BLI_dynstr_append(ds, "\n");

	prototypes = BLI_dynstr_get_cstring(ds);
	BLI_dynstr_free(ds);

	return prototypes;
}
void GPU_code_generate_glsl_lib(void)
{
	DynStr *ds;

	/* only initialize the library once */
	if (glsl_material_library)
		return;

	ds = BLI_dynstr_new();

	BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);


	glsl_material_library = BLI_dynstr_get_cstring(ds);

	BLI_dynstr_free(ds);
}
Example #11
0
char *BLI_sprintfN(const char *format, ...)
{
	DynStr *ds;
	va_list arg;
	char *n;

	va_start(arg, format);

	ds= BLI_dynstr_new();
	BLI_dynstr_vappendf(ds, format, arg);
	n= BLI_dynstr_get_cstring(ds);
	BLI_dynstr_free(ds);

	va_end(arg);

	return n;
}
Example #12
0
char *BKE_undo_menu_string(void)
{
	UndoElem *uel;
	DynStr *ds = BLI_dynstr_new();
	char *menu;

	BLI_dynstr_append(ds, "Global Undo History %t");
	
	for (uel = undobase.first; uel; uel = uel->next) {
		BLI_dynstr_append(ds, "|");
		BLI_dynstr_append(ds, uel->name);
	}

	menu = BLI_dynstr_get_cstring(ds);
	BLI_dynstr_free(ds);

	return menu;
}
Example #13
0
static char *code_generate_vertex(ListBase *nodes)
{
	DynStr *ds = BLI_dynstr_new();
	GPUNode *node;
	GPUInput *input;
	char *code;
	
	for (node=nodes->first; node; node=node->next) {
		for (input=node->inputs.first; input; input=input->next) {
			if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
				BLI_dynstr_appendf(ds, "attribute %s att%d;\n",
					GPU_DATATYPE_STR[input->type], input->attribid);
				BLI_dynstr_appendf(ds, "varying %s var%d;\n",
					GPU_DATATYPE_STR[input->type], input->attribid);
			}
		}
	}

	BLI_dynstr_append(ds, "\n");
	BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl);

	for (node=nodes->first; node; node=node->next)
		for (input=node->inputs.first; input; input=input->next)
			if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
				if(input->attribtype == CD_TANGENT) /* silly exception */
				{
					BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize((gl_ModelViewMatrix * vec4(att%d.xyz, 0)).xyz);\n", input->attribid, input->attribid);
					BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
				}
				else
					BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
			}

	BLI_dynstr_append(ds, "}\n\n");

	code = BLI_dynstr_get_cstring(ds);

	BLI_dynstr_free(ds);

	//if(G.f & G_DEBUG) printf("%s\n", code);

	return code;
}
Example #14
0
/* skips viewer images */
void IMAnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr)
{
	DynStr *pupds= BLI_dynstr_new();
	
	if (title) {
		BLI_dynstr_append(pupds, title);
		BLI_dynstr_append(pupds, "%t|");
	}
	
	if (extraops) {
		BLI_dynstr_append(pupds, extraops);
		if (BLI_dynstr_get_len(pupds))
			BLI_dynstr_append(pupds, "|");
	}
	
	IDnames_to_dyn_pupstring(pupds, lb, link, nr, IDPUP_NO_VIEWER);
	
	*str= BLI_dynstr_get_cstring(pupds);
	BLI_dynstr_free(pupds);
}
Example #15
0
void BKE_reports_prepend(ReportList *reports, const char *prepend)
{
	Report *report;
	DynStr *ds;

	if (!reports)
		return;

	for (report=reports->list.first; report; report=report->next) {
		ds= BLI_dynstr_new();

		BLI_dynstr_append(ds, prepend);
		BLI_dynstr_append(ds, report->message);
		MEM_freeN((void *)report->message);

		report->message= BLI_dynstr_get_cstring(ds);
		report->len= BLI_dynstr_get_len(ds);

		BLI_dynstr_free(ds);
	}
}
Example #16
0
char *BKE_reports_string(ReportList *reports, ReportType level)
{
	Report *report;
	DynStr *ds;
	char *cstring;

	if (!reports || !reports->list.first)
		return NULL;

	ds= BLI_dynstr_new();
	for (report=reports->list.first; report; report=report->next)
		if (report->type >= level)
			BLI_dynstr_appendf(ds, "%s: %s\n", report->typestr, report->message);

	if (BLI_dynstr_get_len(ds))
		cstring= BLI_dynstr_get_cstring(ds);
	else
		cstring= NULL;

	BLI_dynstr_free(ds);
	return cstring;
}
Example #17
0
/* this returns a string for the list of usable pyconstraint script names */
char *buildmenu_pyconstraints (Text *con_text, int *pyconindex)
{
	DynStr *pupds= BLI_dynstr_new();
	Text *text;
	char *str;
	char buf[64];
	int i;
	
	/* add title first */
	sprintf(buf, "Scripts: %%t|[None]%%x0|");
	BLI_dynstr_append(pupds, buf);
	
	/* init active-index first */
	if (con_text == NULL)
		*pyconindex= 0;
	
	/* loop through markers, adding them */
	for (text=G.main->text.first, i=1; text; i++, text=text->id.next) {
		/* this is important to ensure that right script is shown as active */
		if (text == con_text) *pyconindex = i;
		
		/* only include valid pyconstraint scripts */
		if (BPY_is_pyconstraint(text)) {
			BLI_dynstr_append(pupds, text->id.name+2);
			
			sprintf(buf, "%%x%d", i);
			BLI_dynstr_append(pupds, buf);
			
			if (text->id.next)
				BLI_dynstr_append(pupds, "|");
		}
	}
	
	/* convert to normal MEM_malloc'd string */
	str= BLI_dynstr_get_cstring(pupds);
	BLI_dynstr_free(pupds);
	
	return str;
}
Example #18
0
static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
{
  if (e_data.ssr_sh[options] == NULL) {
    char *ssr_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
                                            datatoc_common_uniforms_lib_glsl,
                                            datatoc_bsdf_common_lib_glsl,
                                            datatoc_bsdf_sampling_lib_glsl,
                                            datatoc_ambient_occlusion_lib_glsl,
                                            datatoc_octahedron_lib_glsl,
                                            datatoc_lightprobe_lib_glsl,
                                            datatoc_raytrace_lib_glsl,
                                            datatoc_effect_ssr_frag_glsl);

    DynStr *ds_defines = BLI_dynstr_new();
    BLI_dynstr_append(ds_defines, SHADER_DEFINES);
    if (options & SSR_RESOLVE) {
      BLI_dynstr_append(ds_defines, "#define STEP_RESOLVE\n");
    }
    else {
      BLI_dynstr_append(ds_defines, "#define STEP_RAYTRACE\n");
      BLI_dynstr_append(ds_defines, "#define PLANAR_PROBE_RAYTRACE\n");
    }
    if (options & SSR_FULL_TRACE) {
      BLI_dynstr_append(ds_defines, "#define FULLRES\n");
    }
    if (options & SSR_AO) {
      BLI_dynstr_append(ds_defines, "#define SSR_AO\n");
    }
    char *ssr_define_str = BLI_dynstr_get_cstring(ds_defines);
    BLI_dynstr_free(ds_defines);

    e_data.ssr_sh[options] = DRW_shader_create_fullscreen(ssr_shader_str, ssr_define_str);

    MEM_freeN(ssr_shader_str);
    MEM_freeN(ssr_define_str);
  }

  return e_data.ssr_sh[options];
}
Example #19
0
static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
{
	DynStr *ds = BLI_dynstr_new();
	char *code;
	int builtins;

#if 0
	BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);
#endif

	codegen_set_unique_ids(nodes);
	builtins = codegen_print_uniforms_functions(ds, nodes);

#if 0
	if (G.debug & G_DEBUG)
		BLI_dynstr_appendf(ds, "/* %s */\n", name);
#endif

	BLI_dynstr_append(ds, "void main(void)\n");
	BLI_dynstr_append(ds, "{\n");

	if (builtins & GPU_VIEW_NORMAL)
		BLI_dynstr_append(ds, "\tvec3 facingnormal = (gl_FrontFacing)? varnormal: -varnormal;\n");
	
	codegen_declare_tmps(ds, nodes);
	codegen_call_functions(ds, nodes, output);

	BLI_dynstr_append(ds, "}\n");

	/* create shader */
	code = BLI_dynstr_get_cstring(ds);
	BLI_dynstr_free(ds);

#if 0
	if (G.debug & G_DEBUG) printf("%s\n", code);
#endif

	return code;
}
Example #20
0
void GPU_code_generate_glsl_lib(void)
{
	DynStr *ds;

	/* only initialize the library once */
	if (glsl_material_library)
		return;

	ds = BLI_dynstr_new();

	if (GPU_bicubic_bump_support()) {
		BLI_dynstr_append(ds, "/* These are needed for high quality bump mapping */\n"
				"#version 130\n"
				"#extension GL_ARB_texture_query_lod: enable\n"
				"#define BUMP_BICUBIC\n");
	}
	BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);


	glsl_material_library = BLI_dynstr_get_cstring(ds);

	BLI_dynstr_free(ds);
}
Example #21
0
static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
{
	DynStr *ds = BLI_dynstr_new();
	GPUNode *node;
	GPUInput *input;
	char *code;
	char *vertcode;
	
	for (node = nodes->first; node; node = node->next) {
		for (input = node->inputs.first; input; input = input->next) {
			if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
				BLI_dynstr_appendf(ds, "attribute %s att%d;\n",
					GPU_DATATYPE_STR[input->type], input->attribid);
				BLI_dynstr_appendf(ds, "varying %s var%d;\n",
					GPU_DATATYPE_STR[input->type], input->attribid);
			}
		}
	}

	BLI_dynstr_append(ds, "\n");

	switch (type) {
		case GPU_MATERIAL_TYPE_MESH:
			vertcode = datatoc_gpu_shader_vertex_glsl;
			break;
		case GPU_MATERIAL_TYPE_WORLD:
			vertcode = datatoc_gpu_shader_vertex_world_glsl;
			break;
		default:
			fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n");
			break;
	}

	BLI_dynstr_append(ds, vertcode);
	
	for (node = nodes->first; node; node = node->next)
		for (input = node->inputs.first; input; input = input->next)
			if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
				if (input->attribtype == CD_TANGENT) { /* silly exception */
					BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n", input->attribid, input->attribid);
					BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
				}
				else
					BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
			}
			/* unfortunately special handling is needed here because we abuse gl_Color/gl_SecondaryColor flat shading */
			else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
				if (input->oglbuiltin == GPU_MATCAP_NORMAL) {
					/* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
					 * between shader stages and we want the full range of the normal */
					BLI_dynstr_appendf(ds, "\tvec3 matcapcol = vec3(0.5, 0.5, 0.5) * varnormal + vec3(0.5, 0.5, 0.5);\n");
					BLI_dynstr_appendf(ds, "\tgl_FrontSecondaryColor = vec4(matcapcol, 1.0);\n");
				}
				else if (input->oglbuiltin == GPU_COLOR) {
					BLI_dynstr_appendf(ds, "\tgl_FrontColor = gl_Color;\n");
				}
			}

	BLI_dynstr_append(ds, "}\n\n");

	code = BLI_dynstr_get_cstring(ds);

	BLI_dynstr_free(ds);

#if 0
	if (G.debug & G_DEBUG) printf("%s\n", code);
#endif

	return code;
}
Example #22
0
// A rather wasteful string-replacement utility, though this shall do for now...
// Feel free to replace this with an even safe + nicer alternative 
char *BLI_replacestr(char *str, const char *oldText, const char *newText)
{
	DynStr *ds= NULL;
	int lenOld= strlen(oldText);
	char *match;
	
	/* sanity checks */
	if ((str == NULL) || (str[0]==0))
		return NULL;
	else if ((oldText == NULL) || (newText == NULL) || (oldText[0]==0))
		return BLI_strdup(str);
	
	/* while we can still find a match for the old substring that we're searching for, 
	 * keep dicing and replacing
	 */
	while ( (match = strstr(str, oldText)) ) {
		/* the assembly buffer only gets created when we actually need to rebuild the string */
		if (ds == NULL)
			ds= BLI_dynstr_new();
			
		/* if the match position does not match the current position in the string, 
		 * copy the text up to this position and advance the current position in the string
		 */
		if (str != match) {
			/* replace the token at the 'match' position with \0 so that the copied string will be ok,
			 * add the segment of the string from str to match to the buffer, then restore the value at match
			 */
			match[0]= 0;
			BLI_dynstr_append(ds, str);
			match[0]= oldText[0];
			
			/* now our current position should be set on the start of the match */
			str= match;
		}
		
		/* add the replacement text to the accumulation buffer */
		BLI_dynstr_append(ds, newText);
		
		/* advance the current position of the string up to the end of the replaced segment */
		str += lenOld;
	}
	
	/* finish off and return a new string that has had all occurances of */
	if (ds) {
		char *newStr;
		
		/* add what's left of the string to the assembly buffer 
		 *	- we've been adjusting str to point at the end of the replaced segments
		 */
		if (str != NULL)
			BLI_dynstr_append(ds, str);
		
		/* convert to new c-string (MEM_malloc'd), and free the buffer */
		newStr= BLI_dynstr_get_cstring(ds);
		BLI_dynstr_free(ds);
		
		return newStr;
	}
	else {
		/* just create a new copy of the entire string - we avoid going through the assembly buffer 
		 * for what should be a bit more efficiency...
		 */
		return BLI_strdup(str);
	}
}