Jump to content
  • Advertisement
Sign in to follow this  
aaron_ds

Easy word wrapping? [Mostly Solved]

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm implementing some gui elements and I must say, I'm stumped at an easy way to manually wrap text. My first instinct was to try it by hand. The input is a std::string and the number of characters to wrap at and the output is std::vector<std::string>. I tried my luck with some dirty C-esque string techniques and realized that wrapping at ends of words is hard enough let along trying to break words that don't fit at all. It quickly became a for/while/if/else nightmare. That having not worked, I tried the C++ way. Something like this:
    std::stringstream ss(text);
    ss.width(max_chars_per_line);
    char* line=new char[max_chars_per_line];
    while(ss.getline(line, max_chars_per_line)) {
        lines.push_back(std::string(line));
    }
    delete[] line;


Ahh, but the original string is one long line of text. I'd have to insert '\n' whereever I wanted to break; back to the drawing board. I then tried looking up boost.org, maybe boost::format would do what I want. Is there a simple way to wrap text, or is brute-forcing it the usual way of wraping text? Thank you. [Edited by - aaron_ds on August 17, 2005 4:31:20 PM]

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
http://www.catch22.net/tuts/

Perhaps his "Design and Implementation of a Win32 Text Editor". Perhaps he can help you out.

Share this post


Link to post
Share on other sites
So this is for a fixed-width font?
If so, it shouldn't be too hard at all. I don't think there's an easier algorithm than the obvious method.

What did you C-esque version look like?

Share this post


Link to post
Share on other sites
Here's some code I used in an old app. It uses a lot of bad things, but the basic word wrap technique isn't very bad. (And yeah, you don't spell length that way)


char** WrapLine(char* str, int w)
{
static char* lines[16];
int currentLine = 0;
int place = 0;

while (str[place] != 0)
{
int lenght = w / FONTW;

if (strlen(&str[place]) < lenght)
lenght = strlen(&str[place]);
else
{
while (str[place + lenght] != ' ' && lenght != 0)
lenght--;
if (lenght == 0)
lenght = w / FONTW;
}

lines[currentLine] = new char[lenght + 1];
memcpy(lines[currentLine], &str[place], lenght);
lines[currentLine][lenght] = 0;
place += lenght;
if (str[place] == ' ')
place++;
currentLine++;
}

lines[currentLine] = NULL;

return lines;
}

Share this post


Link to post
Share on other sites
Well, I came up with this after all too much time.

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <ios>
int main(int argc, char * argv[]) {
std::string text("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Curabitur id magna. Suspendisse semper, neque quis consectetuer suscipit, elit tellus bibendum sem, eu faucibus tellus erat at magna. Aliquam nisl magna, viverra sodales, semper in, sodales eu, risus. Pellentesque bibendum.");
int max_chars_per_line = 30;
std::vector < std::string > lines;
std::string wrapped_text(text);
int length = text.length();
int endline=0;
for(int i = 0; i < wrapped_text.length(), endline< wrapped_text.length(); ) {
// j= the max chars per line or the length of the remaining text, whichever is smaller
endline = wrapped_text.length() < max_chars_per_line + i ? wrapped_text.length() : max_chars_per_line + i;
int j;
for(j = endline; j > i; --j) {
//if there is a space, make it a new line
if(wrapped_text[j] == ' ') {
wrapped_text[j] = '\n';
i = j + 1;
break;
}
}
if(j == i) {
wrapped_text.insert(endline - 1, "\n");
i += endline;
}
}
lines.clear();
//std::cout<<wrapped_text<<std::endl;
std::stringstream ss(wrapped_text);
char * line = new char[max_chars_per_line+1];
while(ss.getline(line,max_chars_per_line+1, '\n') ) {
lines.push_back(std::string(line));
}
delete[] line;

std::vector < std::string >::iterator itr = lines.begin();
for( ; itr != lines.end(); ++itr) {
std::cout << * itr << std::endl;
}

std::cin.get();
return 0;
}



Much to my dismay, ios_base::width ( streamsize wide ); does not effect output when the output extends past width.

The code above is far from perfect, but its a start.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!