Custom WordWrapper
It seemed something simple and easy to answer, but I decided to check on Google if anyone else had a good resource on this. Without any luck, I found remarkably little info on creating your own wordwrap method, so I decided to write it myself in C#. He was happy with the answer, I cleaned the code up a bit, and here's the article about it :)
We begin with creating two projects. One Console App (WordWrapDriver) and one Class Library (WordWrap). Reference the library in the console app.
using
System;
using
WordWrapper = WordWrap.WordWrap;
namespace
WordWrapDriver {
class WordWrapDriver
{
static
void
// TODO
}
/* Main */
}
/* WordWrapDriver */
} /* WordWrapDriver */
Our wordwrapper will be a static method called Wrap. We're going to support a given width and a prefix (for example "> " to prefix like a reply mail).
using
System;
using
System.Collections;
namespace
WordWrap {
public
class WordWrap {
#region
Public Methods
public
static
string Wrap(string
originalText,
int maxWidth) {
return
Wrap(originalText, maxWidth, "");
}
/* Wrap */
public
static
string Wrap(string
originalText,
int maxWidth,
string preFix) {
// TODO
}
/* Wrap */
#endregion
}
/* WordWrap */
}
/* WordWrap */
Let's begin. In the
Wrap method we pass
our text as a
string to a
Wrapper method,
which gives us a
string array that we loop through and prefix.
public
static
string Wrap(string
originalText,
int maxWidth,
string preFix) {
string[] wrappedText =
Wrapper(originalText, maxWidth);
string wrappedBlock =
"";
foreach(string
textLine in wrappedText)
{
wrappedBlock = String.Format("{0}\n{1}{2}", wrappedBlock,
preFix, textLine);
}
wrappedBlock
= wrappedBlock.Substring(1);
return wrappedBlock;
} /* Wrap */
So what does
Wrapper do? First
we filter out \r\n and \r, after we split our text on \n to
create 'blocks'.
originalText = originalText.Replace("\r\n", "\n");
originalText = originalText.Replace("\r", "\n");
originalText = originalText.Replace("\t", " ");
string[] textParagraphs = originalText.Split('\n');
Now we take each paragraph and check if it's smaller then
our
maxWidth or not, if it isn't we just add the line. If it is longer
we'll have to break it up in seperate lines.
for
(int i = 0; i <
textParagraphs.Length; i++) {
if
(textParagraphs[i].Length <= maxWidth) {
// Block of text is smaller then width, add it
textLines.Add(textParagraphs[i]);
}
else {
// Block of text is longer, break it up in seperate
lines
string[] pLines =
BreakLines(textParagraphs[i], maxWidth);
for (int
j = 0; j < pLines.Length; j++) {
textLines.Add(pLines[j]);
}
}
}
And lastly we return our lines.
string[] wrappedText = new
string[textLines.Count];
textLines.CopyTo(wrappedText, 0);
return
wrappedText;
The only method remaining is the
BreakLines method.
Here we split up our
string into seperate words. With those words we re-create the
text, but with the correct width. Therefore we loop through
every word and add it to a temporary
string, which we check against the given
maxWidth. If it's
smaller, we continue, if it's not we add the temporary
string we had just before adding the word, and we continue, the
word causing the 'overflow' will be the first word of the
new line. If we have a line that is inside our required
length, we check if it's the last word and if that's the
case we add our temporary
string.
while
(wordIndex < textWords.Length) {
if (textWords[wordIndex]
== "") {
wordIndex++;
}
else {
string backupLine =
tmpLine;
if (tmpLine == "") {
tmpLine = textWords[wordIndex];
}
else {
tmpLine = tmpLine + " " + textWords[wordIndex];
}
if (tmpLine.Length <=
maxWidth) {
wordIndex++;
// If our line is still small enough, but we don't have
anymore words
// add the line to the collection
if (wordIndex ==
textWords.Length) {
textLines.Add(tmpLine);
}
}
else {
// Our line is too long, add the previous line to the
collection
// and reset the line, the word causing the 'overflow'
will be
// the first word of the new line
textLines.Add(backupLine);
tmpLine = "";
}
}
}
And here as well, we return our lines.
string[] textLinesStr = new
string[textLines.Count];
textLines.CopyTo(textLinesStr, 0);
return
textLinesStr;
In the
WordWrapDriver I added some test strings to test out the
WordWrapper.
string
strText = "The\t\tquick brown fox jumped over the lazy dog
bla.";
Console.WriteLine("20 chars, prefixed example.");
Console.WriteLine(strText);
Console.WriteLine();
Console.WriteLine("> #################### (20)");
Console.WriteLine(WordWrapper.Wrap(strText, 20, ">
"));
Console.ReadLine();
And here are the sources as usual. Hope you find it usefull.