• 14
• 12
• 9
• 10
• 9

Word Wrap function not working

This topic is 2811 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hey guys, I've made a text class using one of LazyFoo's tutorials and now I'm trying to make it go to a new line each time it reaches a certain wrapWidth (word wrapping, essentially).

The thing is, it seems to have problems with getting the 'next word' and counting its length. That much I have gathered from testing. But why doesn't the word length counting part work? I'm guessing I must be getting the word in a wrong way but I just can't figure it out. Please help? Code below.

void TextSystem::DrawWrapped(std::string text, int x, int y, int wrapWidth, int charWidth, GLfloat colorR, GLfloat colorG, GLfloat colorB){	int X = x, Y = y;	//If the font has been built	if( FontTex.Texture != NULL ){		//Go through the text		for( int show = 0; text[ show ] != '\0'; show++ )		{			//If the current character is a space			if( text[ show ] == ' ' ){ //Problems start about here				string nextWord = text.substr(show, text.find_first_of(' ', show));				int wordWidth;				wordWidth=0;				for( int showWord = 0; nextWord[ showWord ] != '\0'; showWord++ ){					int ascii = (unsigned char)nextWord[ showWord ];					int charW=32;					wordWidth+=charW;				} //Problems end about here				if(X+wordWidth > wrapWidth){					Y += (  charWidth / ( float(FontTex.Width)/16 )  ) *newLine;					X = x;				}				else				//Move over				X += space;			}			//If the current character is a newline			else if( text[ show ] == '\n' ){				//Move down				Y += (  charWidth / ( float(FontTex.Width)/16 )  ) *newLine;				//Move back				X = x;			}			else			{				//Get the ASCII value of the character				int ascii = (unsigned char)text[ show ];				//Show the character				int charW=(  charWidth / ( float(FontTex.Width)/16 )  ) *chars[ascii].w; //chars[ascii].w;				int charH=(  charWidth / ( float(FontTex.Width)/16 )  ) *chars[ascii].h;//chars[ascii].h;				int charSpace=(  charWidth / ( float(FontTex.Width)/16 )  ) *characterSpace;				Graphics.DrawTexturePart(FontTex, X, Y, charW, charH, chars[ascii].x, chars[ascii].y, chars[ascii].w, chars[ascii].h, colorR, colorG, colorB);				//Move over the width of the character with one pixel of padding				X += charW+charSpace;//+10;//chars[ ascii ].w + 10;			}		}	}}

[Edited by - Dandi8 on July 11, 2010 2:31:46 PM]

Share on other sites
First of all (I haven't taken a look at the code yet) you have to calculate the length of the next word in advance.
The code always has to be a word in front of the actual print.

EDIT: the logic I use (pseudo-code):
//input: strpos = 0;i = 0;line_width = 0;while( str ){    pos = i;    if( str == '\n' )    {	newline = true;	line_width = 0;	i++;    }    while( 1 )    {        if( str == ' ' || str == '\n' || !str )        {            word_width = measure_width(str+pos,i-pos);             // first param:string, second param: number of chars to measure            line_width += word_width;            if( line_width > MAX_WIDTH ) // a new line has to be started            {                line_width = word_width;                newline = true;            }            if( str == ' ' ) // a new line has to be started            {                line_width += width_of_space;                i++;            }            break;        }        i++;    }    if( newline = true )    {   Position_back_to_new_line();        newline = false;    }    Print_the_portion_of_the_string(str+pos,i-pos);     // first param:start of string, second param: number of chars to print}

EDITED: don't ask why the code is so strange. It was long ago when I made this. I always reuse it.

EDIT FINISHED.

[Edited by - szecs on July 11, 2010 2:45:39 PM]

Share on other sites
Yes, I know. That's what I'm doing, am I not?

Share on other sites
Edited the post.
I suggest to use a while instead of for, if you ad new features (newline character, coloured string etc) it's better to increase/manipulate the counter explicitly inside the loop.

Share on other sites
Did you notice that you calculate nextWord, but never actually do anything with it?

Share on other sites
Okay, I actually took a look at the code. Are you sure you have proportional string? I mean so all the characters have the same width?

I'll have to take another look at it...

Share on other sites
You seem to have a problem with your logic:
you look for a space, and if you find it and the string is wider than it should be, you start a new line.

BUT that's too late! The word already exceeds the allowed width! Otherwise it wouldn't trigger the new line. But the newline will only affect the next word, not the word that triggers it.

That's why I said you have to look one word after the actually printed word.

That's why my logic has an inner loop.
That actually means a word is looped through twice: once when checked, and once when it's printed.

You can't avoid this double check, because you have to know in advance, if a word will exceed the allowed width or not.

I hope that helps.

Share on other sites
It's kinda hard to read it because LazyFoo's stuff is itself hard to read and I yet have to do some major overhaul to make the code more readable.

@Sicrane:
Wow, how could I have missed that...!?
Updated the code (also in the post). Unfortunately, the problem is still the same :(

EDIT:
I AM checking the word in advance and it's inside a separate loop so then the reading is supposed to go normally (as if there was no check at all) after the line break.

for( int showWord = 0; nextWord[ showWord ] != '\0'; showWord++ ){					int ascii = (unsigned char)nextWord[ showWord ];					int charW=32;//(  charWidth / ( float(FontTex.Width)/16 )  ) *chars[ascii].w;					wordWidth+=charW;				}

This is the part of the code where there is a problem. Notice that I'm using a loop that uses showWord. After that the code continues with the normal 'show' loop.

Share on other sites

The checking for '\n' is done in front of the loop, because it affects the characters/word after the '\n'.

The checking for space and word wrap is done this way, because it affects the word before the space.