2

I have used some code from another question to get word wrapping to affect whole words and not split them.

I would like to have additional strings included that contain formatting, but have not been able to figure it out or find anything on the Google machine.

See code below.

using System;
using System.Collections.Generic;

/// <summary>
///     Writes the specified data, followed by the current line terminator, 
///     to the standard output stream, while wrapping lines that would otherwise 
///     break words.
/// </summary>
/// <param name="paragraph">The value to write.</param>
/// <param name="tabSize">The value that indicates the column width of tab 
///   characters.</param>
public static void WordWrap(string paragraph, int tabSize = 8)
{
   string[] lines = paragraph
               .Replace("\t", new String(' ', tabSize))
               .Split(new string[] { Environment.NewLine }, StringSplitOptions.None);

   for (int i = 0; i < lines.Length; i++) {
        string process = lines[i];
        List<String> wrapped = new List<string>();

        while (process.Length > Console.WindowWidth) {
            int wrapAt = process.LastIndexOf(' ', Math.Min(Console.WindowWidth - 1, process.Length));
            if (wrapAt <= 0) break;

            wrapped.Add(process.Substring(0, wrapAt));
            process = process.Remove(0, wrapAt + 1);
        }

        foreach (string wrap in wrapped) {
            Console.WriteLine(wrap);
        }

        Console.WriteLine(process);
    }
}

The formatting I would like to use is simply changing the colour for a dialogue when someone is speaking, or for certain key words (place names, items and character names etc).

See code below.

public static void townName(string town)
{
    Console.ForegroundColor = ConsoleColor.Magenta;
    Game.WordWrap(town);
    Console.ResetColor();
}

public static void Dialog(string message)
{
    Console.ForegroundColor = ConsoleColor.DarkCyan;
    Game.WordWrap(message);
    Console.ResetColor();
}

public static void Villain()
{
    Console.ForegroundColor = ConsoleColor.DarkRed;
    Game.WordWrap("Zanbar Bone");
    Console.ResetColor();
}

Any help is greatly appreciated, be gentle with me though as I am still learning. Layman's terms would be very helpful :)

TheGeneral
  • 79,002
  • 9
  • 103
  • 141
Aelari
  • 31
  • 1
  • 6
  • 2
    I am **up-voting**, because for a new user question you have code!; the code is actually formatted!!!; you have asked a coherent question; and shown you have an understanding of what you want to do. great work – TheGeneral Mar 15 '19 at 04:54

1 Answers1

0

So, we're going to write line by line as needed for color, and then end the paragraphs manually.

    //keep track of the end width right here
    static int endWidth = 0;
    public static void WordWrap(string paragraph, int tabSize = 8)
    {
        //were only doing one bit at a time
        string process = paragraph;
        List<String> wrapped = new List<string>();

        //if were going to pass the end
        while (process.Length + endWidth > Console.WindowWidth)
        {
            //reduce the wrapping in the first line by the ending with
            int wrapAt = process.LastIndexOf(' ', Math.Min(Console.WindowWidth - 1 - endWidth, process.Length));

            //if there's no space
            if (wrapAt == -1)
            {
                //if the next bit won't take up the whole next line
                if (process.Length < Console.WindowWidth - 1)
                {
                    //this will give us a new line
                    wrapped.Add("");
                    //reset the width
                    endWidth = 0;
                    //stop looping
                    break;
                }
                else
                {
                    //otherwise just wrap the max possible
                    wrapAt = Console.WindowWidth - 1 - endWidth;
                }
            }

            //add the next string as normal
            wrapped.Add(process.Substring(0, wrapAt));

            //shorten the process string
            process = process.Remove(0, wrapAt + 1);

            //now reset that to zero for any other line in this group
            endWidth = 0;
        }

        //write a line for each wrapped line
        foreach (string wrap in wrapped)
        {
            Console.WriteLine(wrap);

        }

        //don't write line, just write. You can add a new line later if you need it, 
        //but if you do, reset endWidth to zero
        Console.Write(process);

        //endWidth will now be the lenght of the last line.
        //if this didn't go to another line, you need to add the old endWidth
        endWidth = process.Length + endWidth;

    }


    //use this to end a paragraph
    static void EndParagraph()
    {
        Console.WriteLine();
        endWidth = 0;
    }

Here's an example of using this:

        Console.BackgroundColor = ConsoleColor.Blue;
        WordWrap("First Line. ");
        Console.BackgroundColor = ConsoleColor.Red;
        WordWrap("This is a much longer line. There are many lines like it but this one is my line "+  
            "which is a very long line that wraps.");
        EndParagraph();
        WordWrap("Next Paragraph");

You see we write a line, change the color, write another line. We have to end the paragraphs manually instead of as part of the text block.

There are other strategies but this one allows use of most of your code.

Kyle Olson
  • 116
  • 6
  • Thank you! I missed putting in the EndParagraph method and was confused for a bit. But I have punched a huge chunk of what I had out and put yours in. Works a charm for me! – Aelari Mar 15 '19 at 08:26
  • A little request if possible, I was tossing the idea of having the lines of text print out a character at a time. I found some code that works on the Write but not the WriteLine. [Printing Code](https://stackoverflow.com/questions/27718901/writing-one-character-at-a-time-in-a-c-sharp-console-application) – Aelari Mar 19 '19 at 15:16