Paragraph pouring from a text editor

In a word processor, you can work on paragraphs and then pour them

into other programs as single lines, wrapped by the receiving windows. Here's how to write this into an ordinary text editor.

Paragraph "pouring" from a text editor

By Gene Fowler

[email protected]


1: If you are putting code from my several articles about mdi text editors into one copy of TextEdit, there is a correction to be made in the SaveAs1Click routine you have in there. The line

OpenFiles.Insert(Tag, Pathname);

should be replaced by

OpenFiles.Insert(0, Pathname);

This matters here, because saving a New File is affected. Your first tests will undoubtedly be made in a New File. I assume TextEdit's original SaveAs1Click will not prsent any problem. I brought in my code from the very much more complex eWriter.

2: The test-bed for this code is Borland's TextEdit demo that comes with Delphi. If you are compiling in Delphi 5 or 5.01, you will need the modified forms.pas which I direct you to in my earlier article, Programming System/Next (Prev) in MDI editors.

You can ignore the warning about 5.0x, because you do not need to do any child-window handling. One writing window is all you need to test the feature. I used the feature in my textwriter, eWriter, to pour this article into the page you are reading right now. You can use TextEdit to test the feature.

Actually, TextEdit wraps lines at the window edge and exports paragraphs as single lines. You will have to widen TextEdit far enough beyond the line ends you create with your Enter key to prevent forgetting to Enter so the window wraps. In eWriter, I use "column wrap" so Enter isn't used for every line. The idea in a text editor or textwriter, though, is that you have column wrap or use the Enter key. Shaping the text is the writer's choice. It isn't a stream. However, the writer, then, may want to pour text into some windows and let them wrap or, as I do with Outlook Express, let the program wrap. OE wraps when it sends the text.

TextEdit is an ordinary text editor. I say ordinary rather than plain, because it prints 8-bit characters, but it is ordinary in that it isn't an rtf editor. It's closer to Notepad than to Wordpad. But as you know, it is in a RichEdit control. This allows a good deal of magic. Want visual bookmarks? Mark blocks of text (phrases, titles, etc.) and color them red. Then, you can scroll among them quickly. Or, if you are working on html files, color your tags on loading (as an option). You can do all these things backstage in the RichEdit and those colorings do not affect your text at all. On the other hand, suppose you want to print your html text with colored tags. Export to another file as rtf and print from Wordpad.

In the code below, I use a pair of memory streams to run the text through and pull out every #13#10 except where there are two, so that empty lines separating paragraphs remain to separate the filled lines. Editor.PlainText is set to False at the beginning and back to True at the end. This is how the magic box works. No doubt my reading and modifying the text stream could be simplified, but this works.

Menu item:

Caption: Pull n lines into 1

Name: NLinestoOne1


procedure TEditForm.NLinestoOne1Click(Sender: TObject);




  Stream1, Stream2: TMemoryStream;

  p, q: PChar;

  c: Char;

  IsPar: integer;

procedure SetStreams;


  if Editor.Text <> '' then

    Editor.PlainText := False



  Stream1 := nil;

  Stream2 := nil;


  Stream1 := TMemoryStream.Create;

  Stream2 := TMemoryStream.Create;



  Stream2.SetSize(2 * Stream1.Size);

  p := Stream1.Memory;

  q := Stream2.Memory;


  if Stream1 <> nil then


  if Stream2 <> nil then





  if messageDlg('You may want the lines in blocks separated ' +

  'by empty lines pulled up into single lines. You may ' +

  'want paragraphs without line breaks so they can wrap at ' +

  'a window edge. This will do it.'#13#13 +

  'WARNING: This processes the entire file. If you wish to apply ' +

  'this to only a block from the file, move it to another window ' +

  'and process it there before moving it back.',

    mtInformation, [mbOK, mbCancel],0)= mrCancel then Exit;

  If Editor.Text = '' then Exit;

  IsPar := 0;



  While not (p^ = #0) do


      c := p^;


      if (IsPar = 4) and (c = ' ') then

        IsPar := 5


      if (IsPar = 3) and (c = 'r') then

        IsPar := 4


      if (IsPar = 2) and (c = 'a') then

        IsPar := 3


      if (IsPar = 1) and (c = 'p') then

        IsPar := 2


      if c = '\' then

        IsPar := 1

      else IsPar := 0;

      if (IsPar = 5) then


          if not (p^ = #13) then

            q := q - 4 // removes \par, leaves following space




              q^ := c;


              q^ := '\';


              q^ := 'p';


              q^ := 'a';


              q^ := 'r';


              p := p + 7; // skip #13#10\par(sp)



      q^ := c;


      if p^ = #0 then

         q^ := #0;


  Editor.Text := '';



  if Stream1 <> nil then


  if Stream2 <> nil then


  Editor.PlainText := True;

  Editor.Modified := True;



Interlaced Bibliography
I began ad-libbing these articles on doing some of the things I do

 in eWriter in the Delphi demo TextEdit (from which I built eWriter).

 It's natural to accumulate all these in one copy of TextEdit. And

 you might have to go back and forth to fill in new, missed, or

 changed support routines. Boxed notes appear most places. Figure

 it's on-going "shop" conversation...

  1. Programming System/Next (Prev) in MDI editors

  2. Selective Tiling in MDI Editors

  3. Tracking Window Numbers in MDI Editors

  4. Paragraph "pouring" from a text editor


Share this article!

Follow us!

Find more helpful articles: