Autosizing string

Posted By: Ercoles

Autosizing string - 12/10/12 19:25

Can someone suggest a routine where if a string is greater than a certain length it is made to become multiline by inserting \n at certain instances of the string.

This way a string would never get out of the allocated text view but would be truncated on to the next line if it is longer that the text view.
Posted By: Ercoles

Re: Autosizing string - 12/11/12 17:19

I am trying to do this but I stumbled with a strange bug can anyone shed light?

#include <acknex.h>
#include <default.c>
#include <strio.c>

STRING* tester="This is a test to check something.";


function getword(STRING* kelma)
{ int i;
int ii;
i=str_len(kelma);
ii=str_stri(kelma," ");
if(ii==0){return(kelma);}
str_trunc(kelma,i-ii);
return(kelma);
}
function removeword(STRING* kelmab)
{
int i;
i=str_stri(kelmab," ");
if(i==0){str_cpy(kelmab," ");return(kelmab);}
str_clip(kelmab,i);
return(kelmab);
}
function main()
{
STRING* kelma2="";
STRING* kelma3="";
STRING* kelma4="";
STRING* kelma5="";
str_cpy(kelma2,tester);
kelma4=getword(kelma2);
str_cat(kelma4," ");
str_cpy(kelma2,tester);
kelma5=removeword(kelma2);
error(kelma5); //<----------This should give same result
str_cpy(kelma2,kelma5);
error(kelma5); //<-----------As this why contents dissappear here?
while(str_len(kelma2)>0)
{
kelma3=getword(kelma2);
str_cpy(kelma2,kelma5);
kelma5=removeword(kelma2);
str_cpy(kelma2,kelma5);
str_cat(kelma4,kelma3);
str_cat(kelma4," ");
}
error(kelma4);
}
Posted By: Superku

Re: Autosizing string - 12/12/12 01:25

I did not check your code but are you aware of the feature/ text flag WWRAP?
Posted By: Talemon

Re: Autosizing string - 12/12/12 08:01

Just yesterday, I wrote some code to manually word-wrap my strings so I'll just paste it here. Maybe it'll help you or someone. If it's not clear, just tell me.

P.S: This is written for unicode strings so you may need to change here and there.

First function finds where to split, it's called by the second one. UnT_WordWrap takes a string, splits it where it should be wrapped and fills a pre-allocated string array which it takes as the first argument.

Code:
short    const_null_uchar 			= 0x0;

int UnT_WrapSplit(STRING* arg_str, FONT* arg_font, var arg_width)
{
	if(arg_str == NULL || arg_font == NULL)
	{
		diag("\nUnT_WrapSplit: bad argument");
		return -1;
	}
	if(str_len(arg_str) < 1)
	{
		diag("\nUnT_WrapSplit: str_len(arg_str) < 1");
		return -1;
	}
	
	if(str_width(arg_str, arg_font) < arg_width) return str_len(arg_str);
	var chr = str_chr(arg_str, -str_len(arg_str) + 1, 0x20);
	if(chr == 0) 
	{
		STRING* temp_s = str_createw(&const_null_uchar);
		var temp_w = 0;
		chr = str_len(arg_str) - 1;
		do
		{
			str_cut(temp_s, arg_str, 0, chr);
			temp_w = str_width(temp_s, arg_font);
			chr -= 1;
		}while(temp_w > arg_width);
		ptr_remove(temp_s);
		return chr;
	}
	STRING* temp_s = str_cut(NULL, arg_str, 0, chr);
	var temp_v = UnT_WrapSplit(temp_s, arg_font, arg_width);
	ptr_remove(temp_s);
	return temp_v;
}

int UnT_WordWrap(STRING** out_str_array, int arg_arrayCapacity, STRING* arg_in_str, FONT* arg_font, var arg_width)
{
	if(out_str_array == NULL || arg_in_str == NULL || arg_font == NULL)
	{
		diag("\nUnT_WordWrap: bad argument");
		return -1;
	}
	
	var loc_str_len = str_len(arg_in_str);
	int loc_idx = 0;
	STRING* loc_temp_str = str_createw(&const_null_uchar);
	STRING* loc_temp_str_rest = str_createw(&const_null_uchar);
	str_cpy(loc_temp_str, arg_in_str);
	
	while(loc_idx < arg_arrayCapacity)
	{
		var end = UnT_WrapSplit(loc_temp_str, arg_font, arg_width);
		if(end < 1) break;
		str_cut(out_str_array[loc_idx], loc_temp_str, 0, end);
		str_trim(out_str_array[loc_idx]);
		str_cut(loc_temp_str_rest, loc_temp_str, end, 0);
		ptr_remove(loc_temp_str);
		loc_temp_str = loc_temp_str_rest;
		loc_idx++;
	}
	return loc_idx;
}

Posted By: Ercoles

Re: Autosizing string - 12/12/12 17:15

Thanks all of you. In the meantime I had made this routine:

function Stringer(STRING* kelma)
{ var i; var ii; var iii;
STRING* kelma2="";
STRING* kelma3="";
STRING* kelma4="";
iii=str_len(kelma);
kelma2=str_parse(NULL,kelma,1);
str_cat(kelma3,kelma2);
str_cat(kelma3," ");
ii=str_len(kelma3);
while(ii<iii)
{
str_parse(kelma2,kelma,0);
str_cat(kelma3,kelma2);
ii +=(str_len(kelma2)+1);
str_cat(kelma3," ");
i=str_len(kelma3);
if(i>65){str_cat(kelma3,"\n");str_cat(kelma4,kelma3);str_cpy(kelma3,"");}
}
str_cat(kelma4,kelma3);
return(kelma4);
}

I do not need it because the WWRAP method solved my problem but can anyone tell me why the function I wrote above works well only when called the first time and when called the second time it leaves fragments from the previous call string?
Posted By: Ch40zzC0d3r

Re: Autosizing string - 12/12/12 17:25

I think STRING* anyname = "" overwrites the old strings in memory.
I had problems with it smirk
str_cpy same problem. I just used str_create every time, and now it works just fine laugh
Posted By: Uhrwerk

Re: Autosizing string - 12/12/12 18:33

Code:
STRING* kelma2="";


That's wrong. "" is a char array or a pointer to a char but never a STRING. You can define strings globally this way but not local.
Posted By: Ercoles

Re: Autosizing string - 12/12/12 19:29

So how should they be defined locally?
Posted By: Ch40zzC0d3r

Re: Autosizing string - 12/12/12 20:30

As I said via str_create ......
Posted By: Uhrwerk

Re: Autosizing string - 12/12/12 21:26

Originally Posted By: Ercoles
So how should they be defined locally?

Not at all. A STRING* is an engine object. Allocation is costly. You should use global or static strings whereever possible. If you have good reason to create a local string with str_create don't forget to free them afterwards, or you'll create a memory leak.
Posted By: Talemon

Re: Autosizing string - 12/12/12 23:34

Originally Posted By: Uhrwerk
Originally Posted By: Ercoles
So how should they be defined locally?

Not at all. A STRING* is an engine object. Allocation is costly. You should use global or static strings whereever possible. If you have good reason to create a local string with str_create don't forget to free them afterwards, or you'll create a memory leak.

Well when you define them globally, they will still be allocated. Also, if you don't free them it won't technically be a memory leak since the engine frees them on exit. It would be memory bloat though in the course of the game's runtime.
Posted By: Uhrwerk

Re: Autosizing string - 12/13/12 02:19

When defining strings globally they are allocated exactly one time. When you create strings in functions with str_create they will be created as many times as the function is called.

I don't think it's of any interest if the engine frees them before exiting or if the memory gets freed when the process is being killed by the operating system. In fact it's memory that was allocated and still cannot be used. Also note that the number of engine objects is limited. So not freeing strings when creating them in a function is a rather bad idea, regardless if that counts technically as a memory leak or not.
Posted By: WretchedSid

Re: Autosizing string - 12/13/12 04:19

It technically is a memory leak since you lost all references to it. It doesn't matter if there are still references to it somewhere else, it becomes a memory leak as soon as you lose the last reference to it. Obviously you can have indirect references to an object (ie store it in an array and throw the pointer away but keep a reference to the array), but the engine doesn't count as indirect reference but as blackbox that you don't have a control over.
Posted By: Ercoles

Re: Autosizing string - 12/13/12 09:56

I am a bit confused. When I declare a variable I use:

var x;

for integer I use int, for floating point I use float and for string I use:

STRING* word;

or is there another way?
© 2024 lite-C Forums