예제 #1
0
    // This method formats a sequence of words (Strings obtained from
    // an enumerator) into lines of text, padding the inter-word
    // gaps with extra spaces to obtain lines of length lineWidth, and
    // thus a straight right margin.
    //
    // There are the following exceptions:
    //  * if a word is longer than lineWidth, it is put on a line by
    //    itself (producing a line longer than lineWidth)
    //  * a single word may appear on a line by itself (producing a line
    //     shorter than lineWidth) if adding the next word to the line
    //     would make the line longer than lineWidth
    //  * the last line of the output is not padded with extra spaces.
    //
    // The algorithm for padding with extra spaces ensures that the
    // spaces are evenly distributed over inter-word gaps, using modulo
    // arithmetics.  An Assert method call asserts that the resulting
    // output line has the correct length unless the line contains only
    // a single word or is the last line of the output.

    public static void Format(IEnumerator <String> words, int lineWidth,
                              TextWriter tw)
    {
        lineWidth = Math.Max(0, lineWidth);
        WordList curLine   = new WordList();
        bool     moreWords = words.MoveNext();

        while (moreWords)
        {
            while (moreWords && curLine.Length < lineWidth)
            {
                String word = words.Current;
                if (word != null && word != "")
                {
                    curLine.AddLast(word);
                }
                moreWords = words.MoveNext();
            }
            int wordCount = curLine.Count;
            if (wordCount > 0)
            {
                int extraSpaces = lineWidth - curLine.Length;
                if (wordCount > 1 && extraSpaces < 0) // last word goes on next line
                {
                    int lastWordLength = curLine.GetLast.Length;
                    extraSpaces += 1 + lastWordLength;
                    wordCount   -= 1;
                }
                else if (!moreWords)            // last line, do not pad
                {
                    extraSpaces = 0;
                }
                // Pad inter-word space with evenly distributed extra blanks
                int           holes  = wordCount - 1;
                int           spaces = holes / 2;
                StringBuilder sb     = new StringBuilder();
                sb.Append(curLine.RemoveFirst());
                for (int i = 1; i < wordCount; i++)
                {
                    spaces += extraSpaces;
                    appendBlanks(sb, 1 + spaces / holes);
                    spaces %= holes;
                    sb.Append(curLine.RemoveFirst());
                }
                String res = sb.ToString();
                Debug.Assert(res.Length == lineWidth || wordCount == 1 || !moreWords);
                tw.WriteLine(res);
            }
        }
        tw.Flush();
    }