Easy word wrapping? [Mostly Solved]

Started by
3 comments, last by aaron_ds 18 years, 8 months ago
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]
Advertisement
http://www.catch22.net/tuts/

Perhaps his "Design and Implementation of a Win32 Text Editor". Perhaps he can help you out.
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?
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
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;}
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.

This topic is closed to new replies.

Advertisement