<p>Word wrap is one of the must-have features in a modern text editor.</p>

<p>How word wrap be handled? What is the best algorithm for word-wrap?</p>

<p>If text is several million lines, how can I make word-wrap very fast?</p>

<p>Why do I need the solution? Because my projects must draw text with various zoom level and simultaneously beautiful appearance.</p>

<p>The running environment is Windows Mobile devices. The maximum 600&nbsp;MHz speed with very small memory size.</p>

<p>How should I handle line information? Let's assume original data has three lines.</p>

<pre><code>THIS IS LINE 1.
THIS IS LINE 2.
THIS IS LINE 3.
</code></pre>

<p>Afterwards, the break text will be shown like this:</p>

<pre><code>THIS IS
LINE 1.
THIS IS
LINE 2.
THIS IS
LINE 3.
</code></pre>

<p>Should I allocate three lines more? Or any other suggestions?
­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­</p>

[{'answer_id': 17601, 'author': 'Sven Hecht', 'author_id': 1168, 'author_profile': 'https://Stackoverflow.com/users/1168', 'pm_score': 2, 'selected': False, 'text': '<p>With or without hyphenation?</p>\n\n<p>Without it\'s easy. Just encapsulate your text as wordobjects per word and give them a method getWidth(). Then start at the first word adding up the rowlength until it is greater than the available space. If so, wrap the last word and start counting again for the next row starting with this one, etc.</p>\n\n<p>With hyphenation you need hyphenation rules in a common format like: hy-phen-a-tion</p>\n\n<p>Then it\'s the same as the above except you need to split the last word which has caused the overflow.</p>\n\n<p>A good example and tutorial of how to structure your code for an excellent text editor is given in the Gang of Four <em><a href="http://en.wikipedia.org/wiki/Design_Patterns" rel="nofollow noreferrer">Design Patterns</a></em> book. It\'s one of the main samples on which they show the patterns.</p>\n'}, {'answer_id': 17603, 'author': 'Yaakov Ellis', 'author_id': 51, 'author_profile': 'https://Stackoverflow.com/users/51', 'pm_score': 3, 'selected': False, 'text': "<p>I don't know of any specific algorithms, but the following could be a rough outline of how it should work:</p>\n\n<ol>\n<li>For the current text size, font, display size, window size, margins, etc., determine how many characters can fit on a line (if fixed-type), or how many pixels can fit on a line (if not fixed-type).</li>\n<li>Go through the line character by character, calculating how many characters or pixels have been recorded since the beginning of the line.</li>\n<li>When you go over the maximum characters/pixels for the line, move back to the last space/punctuation mark, and move all text to the next line.</li>\n<li>Repeat until you go through all text in the document.</li>\n</ol>\n\n<p>In .NET, word wrapping functionality is built into controls like TextBox. I am sure that a similar built-in functionality exists for other languages as well.</p>\n"}, {'answer_id': 17635, 'author': 'ICR', 'author_id': 214, 'author_profile': 'https://Stackoverflow.com/users/214', 'pm_score': 5, 'selected': False, 'text': '<p>Here is a word-wrap algorithm I\'ve written in C#. It should be fairly easy to translate into other languages (except perhaps for <code>IndexOfAny</code>).</p>\n\n<pre class="lang-cs prettyprint-override"><code>static char[] splitChars = new char[] { \' \', \'-\', \'\\t\' };\n\nprivate static string WordWrap(string str, int width)\n{\n    string[] words = Explode(str, splitChars);\n\n    int curLineLength = 0;\n    StringBuilder strBuilder = new StringBuilder();\n    for(int i = 0; i &lt; words.Length; i += 1)\n    {\n        string word = words[i];\n        // If adding the new word to the current line would be too long,\n        // then put it on a new line (and split it up if it\'s too long).\n        if (curLineLength + word.Length &gt; width)\n        {\n            // Only move down to a new line if we have text on the current line.\n            // Avoids situation where wrapped whitespace causes emptylines in text.\n            if (curLineLength &gt; 0)\n            {\n                strBuilder.Append(Environment.NewLine);\n                curLineLength = 0;\n            }\n\n            // If the current word is too long to fit on a line even on it\'s own then\n            // split the word up.\n            while (word.Length &gt; width)\n            {\n                strBuilder.Append(word.Substring(0, width - 1) + "-");\n                word = word.Substring(width - 1);\n\n                strBuilder.Append(Environment.NewLine);\n            }\n\n            // Remove leading whitespace from the word so the new line starts flush to the left.\n            word = word.TrimStart();\n        }\n        strBuilder.Append(word);\n        curLineLength += word.Length;\n    }\n\n    return strBuilder.ToString();\n}\n\nprivate static string[] Explode(string str, char[] splitChars)\n{\n    List&lt;string&gt; parts = new List&lt;string&gt;();\n    int startIndex = 0;\n    while (true)\n    {\n        int index = str.IndexOfAny(splitChars, startIndex);\n\n        if (index == -1)\n        {\n            parts.Add(str.Substring(startIndex));\n            return parts.ToArray();\n        }\n\n        string word = str.Substring(startIndex, index - startIndex);\n        char nextChar = str.Substring(index, 1)[0];\n        // Dashes and the likes should stick to the word occuring before it. Whitespace doesn\'t have to.\n        if (char.IsWhiteSpace(nextChar))\n        {\n            parts.Add(word);\n            parts.Add(nextChar.ToString());\n        }\n        else\n        {\n            parts.Add(word + nextChar);\n        }\n\n        startIndex = index + 1;\n    }\n}\n</code></pre>\n\n<p>It\'s fairly primitive - it splits on spaces, tabs and dashes. It does make sure that dashes stick to the word before it (so you don\'t end up with stack\\n-overflow) though it doesn\'t favour moving small hyphenated words to a newline rather than splitting them. It does split up words if they are too long for a line.</p>\n\n<p>It\'s also fairly culturally specific, as I don\'t know much about the word-wrapping rules of other cultures.</p>\n'}, {'answer_id': 285475, 'author': 'Bjarke Ebert', 'author_id': 31890, 'author_profile': 'https://Stackoverflow.com/users/31890', 'pm_score': 5, 'selected': False, 'text': '<p>Donald E. Knuth did a lot of work on the line breaking algorithm in his TeX typesetting system. This is arguably one of the best algorithms for line breaking - "best" in terms of visual appearance of result.</p>\n\n<p>His algorithm avoids the problems of greedy line filling where you can end up with a very dense line followed by a very loose line.</p>\n\n<p>An efficient algorithm can be implemented using dynamic programming.</p>\n\n<p><a href="http://www.tug.org/TUGboat/tb21-3/tb68fine.pdf" rel="noreferrer">A paper on TeX\'s line breaking</a>.</p>\n'}, {'answer_id': 857770, 'author': 'Instance Hunter', 'author_id': 65393, 'author_profile': 'https://Stackoverflow.com/users/65393', 'pm_score': 5, 'selected': False, 'text': '<p>I had occasion to write a word wrap function recently, and I want to share what I came up with.</p>\n\n<p>I used a <a href="http://en.wikipedia.org/wiki/Test-driven_development" rel="nofollow noreferrer">TDD</a> approach almost as strict as the one from the <a href="http://gojko.net/2009/02/27/thought-provoking-tdd-exercise-at-the-software-craftsmanship-conference/" rel="nofollow noreferrer">Go example</a>. I started with the test that wrapping the string "Hello, world!" at 80 width should return "Hello, World!". Clearly, the simplest thing that works is to return the input string untouched. Starting from that, I made more and more complex tests and ended up with a recursive solution that (at least for my purposes) quite efficiently handles the task.</p>\n\n<p>Pseudocode for the recursive solution:</p>\n\n<pre>\nFunction WordWrap (inputString, width)\n    Trim the input string of leading and trailing spaces.\n\n    If the trimmed string\'s length is &lt;= the width,\n        Return the trimmed string.\n    Else,\n        Find the index of the last space in the trimmed string, starting at width\n\n        If there are no spaces, use the width as the index.\n\n        Split the trimmed string into two pieces at the index.\n\n        Trim trailing spaces from the portion before the index,\n        and leading spaces from the portion after the index.\n\n        Concatenate and return:\n          the trimmed portion before the index,\n          a line break,\n          and the result of calling WordWrap on the trimmed portion after\n            the index (with the same width as the original call).\n</pre>\n\n<p>This only wraps at spaces, and if you want to wrap a string that already contains line breaks, you need to split it at the line breaks, send each piece to this function and then reassemble the string. Even so, in VB.NET running on a fast machine, this can handle about 20 MB/second.</p>\n'}, {'answer_id': 857828, 'author': 'Aaron Digulla', 'author_id': 34088, 'author_profile': 'https://Stackoverflow.com/users/34088', 'pm_score': 2, 'selected': False, 'text': '<p>I wondered about the same thing for my own editor project. My solution was a two-step process:</p>\n\n<ol>\n<li>Find the line ends and store them in an array.</li>\n<li>For very long lines, find suitable break points at roughly 1K intervals and save them in the line array, too. This is to catch the "4&nbsp;MB text without a single line break".</li>\n</ol>\n\n<p>When you need to display the text, find the lines in question and wrap them on the fly. Remember this information in a cache for quick redraw. When the user scrolls a whole page, flush the cache and repeat.</p>\n\n<p>If you can, do loading/analyzing of the whole text in a background thread. This way, you can already display the first page of text while the rest of the document is still being examined. The most simple solution here is to cut the first 16&nbsp;KB of text away and run the algorithm on the substring. This is very fast and allows you to render the first page instantly, even if your editor is still loading the text.</p>\n\n<p>You can use a similar approach when the cursor is initially at the end of the text; just read the last 16&nbsp;KB of text and analyze that. In this case, use two edit buffers and load all but the last 16&nbsp;KB into the first while the user is locked into the second buffer. And you\'ll probably want to remember how many lines the text has when you close the editor, so the scroll bar doesn\'t look weird.</p>\n\n<p>It gets hairy when the user can start the editor with the cursor somewhere in the middle, but ultimately it\'s only an extension of the end-problem. Only you need to remember the byte position, the current line number, and the total number of lines from the last session, plus you need three edit buffers or you need an edit buffer where you can cut away 16&nbsp;KB in the middle.</p>\n\n<p>Alternatively, lock the scrollbar and other interface elements while the text is loading; that allows the user to look at the text while it loads completely.</p>\n'}, {'answer_id': 4086347, 'author': 'Johan Andersson', 'author_id': 66883, 'author_profile': 'https://Stackoverflow.com/users/66883', 'pm_score': 0, 'selected': False, 'text': '<p>@ICR, thanks for sharing the C# example.</p>\n\n<p>I did not succeed using it, but I came up with another solution. If there is any interest in this, please feel free to use this:\n<em><a href="https://web.archive.org/web/20160403050733/http://johan.andersson.net/2010/11/03/wordwrap-function-in-c/" rel="nofollow noreferrer">WordWrap function in C#</a></em>. The source is available <a href="https://github.com/anderssonjohan/snippets/tree/master/wordwrap" rel="nofollow noreferrer">on GitHub</a>.</p>\n\n<p>I\'ve included unit tests / samples.</p>\n'}, {'answer_id': 29807751, 'author': 'BigBangBuddha', 'author_id': 4821288, 'author_profile': 'https://Stackoverflow.com/users/4821288', 'pm_score': 1, 'selected': False, 'text': '<p>I cant claim the bug-free-ness of this, but I needed one that word wrapped and obeyed boundaries of indentation.   I claim nothing about this code other than it has worked for me so far.  This is an extension method and violates the integrity of the StringBuilder but it could be made with whatever inputs / outputs you desire.  </p>\n\n<pre><code>public static void WordWrap(this StringBuilder sb, int tabSize, int width)\n{\n    string[] lines = sb.ToString().Replace("\\r\\n", "\\n").Split(\'\\n\');\n    sb.Clear();\n    for (int i = 0; i &lt; lines.Length; ++i)\n    {\n        var line = lines[i];\n        if (line.Length &lt; 1)\n            sb.AppendLine();//empty lines\n        else\n        {\n            int indent = line.TakeWhile(c =&gt; c == \'\\t\').Count(); //tab indents \n            line = line.Replace("\\t", new String(\' \', tabSize)); //need to expand tabs here\n            string lead = new String(\' \', indent * tabSize); //create the leading space\n            do\n            {\n                //get the string that fits in the window\n                string subline = line.Substring(0, Math.Min(line.Length, width));\n                if (subline.Length &lt; line.Length &amp;&amp; subline.Length &gt; 0)\n                {\n                    //grab the last non white character\n                    int lastword = subline.LastOrDefault() == \' \' ? -1 : subline.LastIndexOf(\' \', subline.Length - 1);\n                    if (lastword &gt;= 0)\n                        subline = subline.Substring(0, lastword);\n                    sb.AppendLine(subline);\n\n                    //next part\n                    line = lead + line.Substring(subline.Length).TrimStart();\n                }\n                else  \n                {\n                    sb.AppendLine(subline); //everything fits\n                    break;\n                }\n            }\n            while (true);\n        }\n    }\n}\n</code></pre>\n'}, {'answer_id': 34097833, 'author': 'Jeff Y', 'author_id': 5379657, 'author_profile': 'https://Stackoverflow.com/users/5379657', 'pm_score': 0, 'selected': False, 'text': '<p>I may as well chime in with a perl solution that I made, because gnu <code>fold -s</code> was leaving trailing spaces and other bad behavior. This solution does not (properly) handle text containing tabs or backspaces or embedded carriage returns or the like, although it does handle CRLF line-endings, converting them all to just LF. It makes minimal change to the text, in particular it never splits a word (doesn\'t change <code>wc -w</code>), and for text with no more than single space in a row (and no CR) it doesn\'t change <code>wc -c</code> (because it <em>replaces</em> space with LF rather than <em>inserting</em> LF).</p>\n\n<pre><code>#!/usr/bin/perl\n\nuse strict;\nuse warnings;\n\nmy $WIDTH = 80;\n\nif ($ARGV[0] =~ /^[1-9][0-9]*$/) {\n  $WIDTH = $ARGV[0];\n  shift @ARGV;\n}\n\nwhile (&lt;&gt;) {\n\ns/\\r\\n$/\\n/;\nchomp;\n\nif (length $_ &lt;= $WIDTH) {\n  print "$_\\n";\n  next;\n}\n\n@_=split /(\\s+)/;\n\n# make @_ start with a separator field and end with a content field\nunshift @_, "";\npush @_, "" if @_%2;\n\nmy ($sep,$cont) = splice(@_, 0, 2);\ndo {\n  if (length $cont &gt; $WIDTH) {\n    print "$cont";\n    ($sep,$cont) = splice(@_, 0, 2);\n  }\n  elsif (length($sep) + length($cont) &gt; $WIDTH) {\n    printf "%*s%s", $WIDTH - length $cont, "", $cont;\n    ($sep,$cont) = splice(@_, 0, 2);\n  }\n  else {\n    my $remain = $WIDTH;\n    { do {\n      print "$sep$cont";\n      $remain -= length $sep;\n      $remain -= length $cont;\n      ($sep,$cont) = splice(@_, 0, 2) or last;\n    }\n    while (length($sep) + length($cont) &lt;= $remain);\n    }\n  }\n  print "\\n";\n  $sep = "";\n}\nwhile ($cont);\n\n}\n</code></pre>\n'}, {'answer_id': 37738188, 'author': 'Philippe Carphin', 'author_id': 5795941, 'author_profile': 'https://Stackoverflow.com/users/5795941', 'pm_score': 1, 'selected': False, 'text': '<p>Here is mine that I was working on today for fun in C:</p>\n<p>Here are my considerations:</p>\n<ol>\n<li><p>No copying of characters, just printing to standard output. Therefore, since I don\'t like to modify the argv[x] arguments, and because I like a challenge, I wanted to do it without modifying it.  I did not go for the idea of inserting <code>\'\\n\'</code>.</p>\n</li>\n<li><p>I don\'t want</p>\n<pre><code> This line breaks     here\n</code></pre>\n<p>to become</p>\n<pre><code> This line breaks\n      here\n</code></pre>\n<p>so changing characters to <code>\'\\n\'</code> is not an option given this objective.</p>\n</li>\n<li><p>If the linewidth is set at say 80, and the 80th character is in the middle of a word, the entire word must be put on the next line.  So as you\'re scanning, you have to remember the position of the end of the last word that didn\'t go over 80 characters.</p>\n<p>So here is mine, it\'s not clean; I\'ve been breaking my head for the past hour trying to get it to work, adding something here and there.  It works for all edge cases that I know of.</p>\n<pre class="lang-cpp prettyprint-override"><code>#include &lt;stdlib.h&gt;\n#include &lt;string.h&gt;\n#include &lt;stdio.h&gt;\n\nint isDelim(char c){\n   switch(c){\n      case \'\\0\':\n      case \'\\t\':\n      case \' \' :\n         return 1;\n         break; /* As a matter of style, put the \'break\' anyway even if there is a return above it.*/\n      default:\n         return 0;\n   }\n}\n\nint printLine(const char * start, const char * end){\n   const char * p = start;\n   while ( p &lt;= end )\n       putchar(*p++);\n   putchar(\'\\n\');\n}\n\nint main ( int argc , char ** argv ) {\n\n   if( argc &lt;= 2 )\n       exit(1);\n\n   char * start = argv[1];\n   char * lastChar = argv[1];\n   char * current = argv[1];\n   int wrapLength = atoi(argv[2]);\n\n   int chars = 1;\n   while( *current != \'\\0\' ){\n      while( chars &lt;= wrapLength ){\n         while ( !isDelim( *current ) ) ++current, ++chars;\n         if( chars &lt;= wrapLength){\n            if(*current == \'\\0\'){\n               puts(start);\n               return 0;\n            }\n            lastChar = current-1;\n            current++,chars++;\n         }\n      }\n\n      if( lastChar == start )\n         lastChar = current-1;\n\n      printLine(start,lastChar);\n      current = lastChar + 1;\n      while(isDelim(*current)){\n         if( *current == \'\\0\')\n            return 0;\n         else\n            ++current;\n      }\n      start = current;\n      lastChar = current;\n      chars = 1;\n   }\n   return 0;\n}\n</code></pre>\n<p>So basically, I have <code>start</code> and <code>lastChar</code> that I want to set as the start of a line and the last character of a line.  When those are set, I output to standard output all the characters from start to end, then output a <code>\'\\n\'</code>, and move on to the next line.</p>\n<p>Initially everything points to the start, then I skip words with the <code>while(!isDelim(*current)) ++current,++chars;</code>.  As I do that, I remember the last character that was before 80 chars (<code>lastChar</code>).</p>\n<p>If, at the end of a word, I have passed my number of chars (80), then I get out of the <code>while(chars &lt;= wrapLength)</code> block. I output all the characters between <code>start</code> and <code>lastChar</code> and a <code>newline</code>.</p>\n<p>Then I set <code>current</code> to <code>lastChar+1</code> and skip delimiters (and if that leads me to the end of the string, we\'re done, <code>return 0</code>).  Set <code>start</code>, <code>lastChar</code> and <code>current</code> to the start of the next line.</p>\n<p>The</p>\n<pre class="lang-cpp prettyprint-override"><code>if(*current == \'\\0\'){\n    puts(start);\n    return 0;\n}\n</code></pre>\n<p>part is for strings that are too short to be wrapped even once.  I added this just before writing this post because I tried a short string and it didn\'t work.</p>\n<p>I feel like this might be doable in a more elegant way.  If anyone has anything to suggest I\'d love to try it.</p>\n<p>And as I wrote this I asked myself &quot;what\'s going to happen if I have a string that is one word that is longer than my wraplength&quot;  Well it doesn\'t work.  So I added the</p>\n<pre class="lang-cpp prettyprint-override"><code>if( lastChar == start )\n    lastChar = current-1;\n</code></pre>\n<p>before the <code>printLine()</code> statement (if <code>lastChar</code> hasn\'t moved, then we have a word that is too long for a single line so we just have to put the whole thing on the line anyway).</p>\n<p>I took the comments out of the code since I\'m writing this but I really feel that there must be a better way of doing this than what I have that wouldn\'t need comments.</p>\n<p>So that\'s the story of how I wrote this thing.  I hope it can be of use to people and I also hope that someone will be unsatisfied with my code and propose a more elegant way of doing it.</p>\n<p>It should be noted that it works for all edge cases: words too long for a line, strings that are shorter than one wrapLength, and empty strings.</p>\n</li>\n</ol>\n'}]
['https://Stackoverflow.com/questions/17586', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1556/']