22 Mar, 2007, Ugha wrote in the 1st comment:
Votes: 0
Seems like several people have problems designing a word wrapping function. I'm one of them.

My intention is to design a function that divides a string into an array and returns only the line
requested in the function call. This way you can put it in a loop to display the whole wordwrapped
string, or you can do what I'm trying to do, design an ASCII art menu and put a string in several
lines of ASCII art without screwing with the alignment of things.

Everything works but with one problem… I counts the length of the string AFTER adding each word.
I added in a "read-ahead" loop to prevent that but for some reason its not working. I must be blind
or something because I can NOT see what is wrong here.

Please note that I'm extremely rusty in C so my function is a mess… please don't mock my lack of skills.

char *wordwrap( int lines, int length, const char *argument )
{
static char strwrap[50][MAX_STRING_LENGTH];
int i,b,n,r,count, word;
count = word = n = b = i = r = 0;
for ( i = 0; i < strlen(argument); i++ )
{
count++;
for(r = i;argument[r] == ' ';r++)
word++;

if ( count+word > length && argument[i] == ' ' )
{
strwrap[n][b] = '\0';
count = 0;
b = 0;
n++;
word = 0;
}
else
{
strwrap[n][b] = argument[i];
b++;
word = 0;
}
}
if(lines > n)
{
n++;
for(i = 0;i < length;i++)
strwrap[n][i] = ' ';

strwrap[n][i+1] = '\0';
return strwrap[n];
}
else return strwrap[lines];
}


PS: Since this actually does work 100% (just not the way I want it to), feel free to use it if you want.
Just drop me a line and let me know that you do :)
23 Mar, 2007, Tyche wrote in the 2nd comment:
Votes: 0
#include <iostream>
#include <string>
#include <pcrecpp.h>
using namespace std;
using namespace pcrecpp;

string wordwrap(string s, int col) {
char width[10];
string str(s);
RE("\\n").GlobalReplace(" ", &str);
RE(" ").GlobalReplace(" ", &str);
sprintf(width,"%d",col);
RE("\\S{" + string(width) + "})(?=\\S)").GlobalReplace("\\1", &str);
RE("(.{1," + string(width) + "})(?:\\s+|$)").GlobalReplace("\\1\n", &str);
return str;
}

int main(int argc, char** argv) {
string test("These are the times that\n try men's souls");
cout << test << endl;
cout << wordwrap(test,10) << endl;
cout << wordwrap(test,20) << endl;
}
23 Mar, 2007, Ugha wrote in the 3rd comment:
Votes: 0
Umm… I'm afraid that all of that is quite a bit above me. I've never even seen most of those functions.

Is that C++? I've never needed to learn C++ as of yet.

I'm afraid that I must admit that I'm self-taught and thats left a lot of holes in my knowledge.

Can you explain the code you posted? Or perhaps someone else could enlighten me?
23 Mar, 2007, Scandum wrote in the 4th comment:
Votes: 0
char *wrap (char *input, int length)                                                                
{
static char wrapped_buf[MAX_STRING_LENGTH];
char *pti, *pto, *last_i_space, *last_o_space;
int cnt = 0;

last_o_space = pto = wrapped_buf;
last_i_space = pti = input;

while (TRUE)
{
*pto = *pti;

switch (*pto)
{
case '\0':
return wrapped_buf;
break;
case ' ':
last_o_space = pto;
last_i_space = pti;
break;
case '\n':
case '\r':
cnt = 0;
pto++;
pti++;
continue;
}
pto++;
pti++;
cnt++;

if (cnt >= length)
{
if (*pti == '\n' || *pti == '\0')
{
continue;
}
if (*pti == ' ')
{
last_o_space = pto;
last_i_space = pti;
}
if (pto - last_o_space > 20)
{
*pto = '\r';
pto++;
*pto = '\n';
pto++;
cnt = 0;
}
else
{
pto = last_o_space;
*pto = '\r';
pto++;
*pto = '\n';
pto++;
pti = last_i_space;
pti++;
cnt = 0;
}
}
}
return wrapped_buf;
}
24 Mar, 2007, kiasyn wrote in the 5th comment:
Votes: 0
24 Mar, 2007, Ugha wrote in the 6th comment:
Votes: 0
I see that I need to clear up a bit of what I'm asking for on two fronts.

First, what I want is a function that will split a single string into multiple
strings based on how many lines they are at a variable line length.
I do not want a function that does a carriage return (\n\r).

I want to be able to split up a string into lines of a value that I can preset
in the function call, and then use those new strings in some form of ASCII art.

For example:
___           ——————————————–           ___
/ \_______ /| |\ _______/ \
| | | This is a sample of text that is | | | |
| _______| | far too long to fit on this scroll | |_______| |
\___/ \| |/ \___/
——————————————–


If I were to use a carriage return, it would destroy the alignment of the
art on either side of the string.

But if my string sees that the line is over say… 35 characters long, it splits it off,
returns whatever line number I call for and then on the next call, splits off whatever
next line number I ask for.

Using a very simplistic example, the following code will print the above scroll:
send_to_char("  ___           ——————————————–           ___",ch);
send_to_char" / \_______ /| |\ _______/ \",ch);
sprintf(buf,"| | | %s | | | |",wordwrap(1,35,text));
send_to_char(buf,ch);
sprintf(buf,"| _______| | %s | |_______| |"wordwrap(2,35,text));
send_to_char(buf,ch);
send_to_char(" \___/ \| |/ \___/",ch);
send_to_char(" ——————————————– ",ch);


If I have an unknown number of lines, I can just design the art to have a lot of the same
lines repeated (like an unrolled scroll) and then just put it in a loop.


The second thing I think I didn't clear up completely, was what I was asking for in terms of
help.

I'm looking to learn, to become a better coder. I can't do that by you doing my work for me.
I can only do that by you telling me what I did wrong and how to fix it.

Please, if your going to help me, talk to me. Tell me what would improve this function.
Also feel free to pass on any advice about this type of coding in general. Any knowledge
that could help me is welcome.

I don't mean to sound ungreatful or demanding by asking for a different kind of help.

All I mean to do is ask to become a better coder. And by becoming a better coder, I can
improve the mud community as a whole.

Thank you.
24 Mar, 2007, Conner wrote in the 7th comment:
Votes: 0
Gee, I read that as "Thanks, but I don't understand the code, could someone please explain it?" not as "Could some other folks please confuse me further by posting even more code without explaination?" :tongue:
24 Mar, 2007, Ugha wrote in the 8th comment:
Votes: 0
Pretty much.

Is that a bad thing? :smile:
24 Mar, 2007, Tyche wrote in the 9th comment:
Votes: 0
Ugha said:
Umm… I'm afraid that all of that is quite a bit above me. I've never even seen most of those functions.

Is that C++? I've never needed to learn C++ as of yet.

I'm afraid that I must admit that I'm self-taught and thats left a lot of holes in my knowledge.

Can you explain the code you posted? Or perhaps someone else could enlighten me?


Well it's C++, but uses no special features except the PCRE C++ wrapper. That is you can use C if you'd prefer. All of the work is done by regular expressions. In the example I use the PCRE library, but you can also use the Regex library. For more info on regular expressions see - http://en.wikipedia.org/wiki/Regular_exp...

The function takes a string and the column width to use in word wrapping.
Explanation of the important lines of code follows:
RE("\\n").GlobalReplace(" ", &str);    // Replace all linefeeds with spaces
RE(" ").GlobalReplace(" ", &str); // Replace all double spaces with single spaces
sprintf(width,"%d",col); // copy column width to string
// Go through string breaking it into fixed size chunks column 'width' or less,
// ensuring that each chunk begins with a non whitespace characters and doesn't
// end on one. (don't break words up)
RE("\\S{" + string(width) + "})(?=\\S)").GlobalReplace("\\1", &str);
// Append linefeeds to end of column 'width' chunks.
RE("(.{1," + string(width) + "})(?:\\s+|$)").GlobalReplace("\\1\n", &str);


After reading your third post you've confused me. Wordwrap and preserving the formatting of ASCII artwork are incompatible, IMO. You either do one or the other.

HTH
24 Mar, 2007, Conner wrote in the 10th comment:
Votes: 0
Nope, not at all. I wasn't really addressing you, Ugha, you'd posted while I was typing, so I hadn't seen your post until just now in fact. Sorry for any confusion there. I think what you're asking for is the ideal, you want someone to help you with ideas of how to make this work rather than just give you a snippet. What I was saying was because after yuo asked for an explaination of Tyche's post, Scandum and Kiasyn went ahead and posted more unexplained code at you rather than actually addressed your actual concern. *shrug*
24 Mar, 2007, Conner wrote in the 11th comment:
Votes: 0
Tyche said:
After reading your third post you've confused me. Wordwrap and preserving the formatting of ASCII artwork are incompatible, IMO. You either do one or the other.


Again, my timing must just be off a hair today…

Anyway, Tyche, I think he did offer that what he could do would be to set the ascii art to an unrolled scroll so that all that would need to be 'preserved' would be the characters that begin and end the line rather than a whole group of them and in his example he's saying that he basically wants to do the word wrapping in a buffer for each line that it's been wrapped to so that he can past the buffers into his ascii art. So he's not inputing the art with the text he's word wrapping, just outputting the wrapped text into a pre-sized space within the art.. if that helps clear it up rather than to just make it more confusing.
24 Mar, 2007, Scandum wrote in the 12th comment:
Votes: 0
Tyche said:
After reading your third post you've confused me. Wordwrap and preserving the formatting of ASCII artwork are incompatible, IMO. You either do one or the other.

It's do-able to wrap both text and ascii art if the ascii stuff stays within the margin and the wrapper respects already set new lines.
24 Mar, 2007, Ugha wrote in the 13th comment:
Votes: 0
I've got it!

I figured it out and it works perfectly.

Take a look and let me know if its worthy to post in the snippets section to help other people:
char *wordwrap( int lines, int length, const char *argument )
{
static char strwrap[50][MAX_STRING_LENGTH];
int i,b,n,r,count, word;
count = n = b = 0;
for ( i = 0; i < strlen(argument); i++ )
{
count++;
word = 0;
if(argument[i] == ' ')
for(r = i+1;argument[r] != ' ';r++)
word++;

if(count+word > length && argument[i] == ' ')
{
strwrap[n][b] = '\0';
count = b = 0;
n++;
}
else
{
strwrap[n][b] = argument[i];
b++;
}
}
if(lines > n)
{
n++;
for(i = 0;i < length;i++)
strwrap[n][i] = ' ';

strwrap[n][i+1] = '\0';
return strwrap[n];
}
else return strwrap[lines];
}


Quote
All of the work is done by regular expressions. In the example I use the PCRE library, but you can also use the Regex library. For more info on regular expressions see - http://en.wikipedia.org/wiki/Regular_exp...

Thank you for explaining Tyche, Its always good to learn something new :)

Quote
Anyway, Tyche, I think he did offer that what he could do would be to set the ascii art to an unrolled scroll so that all that would need to be 'preserved' would be the characters that begin and end the line rather than a whole group of them and in his example he's saying that he basically wants to do the word wrapping in a buffer for each line that it's been wrapped to so that he can past the buffers into his ascii art. So he's not inputing the art with the text he's word wrapping, just outputting the wrapped text into a pre-sized space within the art..

That's exactly it. The problem is since I'm self-taught, I don't know how to express what I want to do with the correct terminology.

So what do you guys think? I haven't seen any snippets like this on the net so far… do you think that its A: problem-free and B: helpful
enough to be posted as a snippet? Or does pretty much everyone have something like this in their mud?

Thank you all again for your input and advice.
24 Mar, 2007, Conner wrote in the 14th comment:
Votes: 0
Ugha said:
I've got it!

I figured it out and it works perfectly.


Gratz! :biggrin:

Ugha said:
Take a look and let me know if its worthy to post in the snippets section to help other people:


Wait, are saying that some working code ideas aren't worthy of submission as snippets?? :wink:

Ugha said:
Quote
Anyway, Tyche, I think he did offer that what he could do would be to set the ascii art to an unrolled scroll so that all that would need to be 'preserved' would be the characters that begin and end the line rather than a whole group of them and in his example he's saying that he basically wants to do the word wrapping in a buffer for each line that it's been wrapped to so that he can past the buffers into his ascii art. So he's not inputing the art with the text he's word wrapping, just outputting the wrapped text into a pre-sized space within the art..

That's exactly it. The problem is since I'm self-taught, I don't know how to express what I want to do with the correct terminology.


No worries, I'm not always very good at using exactly the right terminology either, but I do seem to have a knack for understanding folks when others don't seem to be able to, and then paraphrasing what they'd meant to say. :shrug:

Ugha said:
So what do you guys think? I haven't seen any snippets like this on the net so far… do you think that its A: problem-free and B: helpful enough to be posted as a snippet? Or does pretty much everyone have something like this in their mud?

Thank you all again for your input and advice.


I haven't seen any snippets like this yet either, and while my collection isn't exhaustive, it's pretty big.
Problem-free? When's that ever stopped someone from posting a snippet before? :lol:
Helpful enough? You bet! :biggrin:
Everyone already has something like this? Not that I've seen, anywhere so far.
You're more than welcome, hopefully at least some of it was useful in some fashion. :wink:
25 Mar, 2007, Guest wrote in the 15th comment:
Votes: 0
Ugha,

Nice job on figuring out the code. When it comes to string work in C, I'm usually toast. I know a lot of other people are as well, so you've got an understanding of something people will find valuable. Most definitely feel free to submit it as a snippet. Even though it seems generic enough, not everyone has such a function available.

I'm also self taught so when I need to ask questions I generally don't know what the proper terms for things are either. It can get a bit frustrating since it leads to answers or examples that aren't quite what you were looking for. Being able to at least recognize that what you got back is wrong for your purpose is a good thing though. It'll save you a lot of time down the road.
26 Mar, 2007, Conner wrote in the 16th comment:
Votes: 0
Is that the trick? Realizing that you're getting help for something that wasn't really related to your problem?
29 Mar, 2007, Ugha wrote in the 17th comment:
Votes: 0
Turns out its not as functional as I thought.
Because I used a static variable, it bleeds data to new entries if the string isn't long enough.
I'm not sure how to fix this.

I'm thinking about a complete rewrite using pointers more, not sure.
0.0/17