1
votes

TMemo cannot handle Unix enters (LF) correctly. Two lines separated with a LF are shown and treated as one line. I want to handle all possible text formating (Mac, Win, Unix).

Obviously I could check the text and replace the LF with CRLF every time I:

  • load text form file
  • paste text
  • use the Add() function
  • use the Insert() function
  • use the Appen() function
  • change the content via Text property

But this won't be an elegant solution.

Lazarus solved this problem with the Lines.TextLineBreakStyle property. There is anything similar in Delphi XE?

2
Beware: You appear to be conflating the line-ending sequences with the key that generates them. Enter is a key. It's the same key whether the computer is running Windows, Unix, or anything else. Enter is not a character. Pressing it on Windows will cause most programs to insert two characters: a carriage return followed by a newline. Unix will tend to insert only the newline. The application is free to interpret the key differently, though. The application is also free to display the characters how it wants.Rob Kennedy
@RobKennedy-You are right. I fixed the question title.Z80

2 Answers

4
votes

You're asking specifically about line-ending sequences, but we can easily broaden the discussion to controlling the contents of an edit box in general.

In 2001, Peter Below wrote an outline of all the things you need to handle for an edit control that accepts only numerals. The techniques are still applicable today, at least for Windows development. Here's a summary:

  • Override KeyPress to filter out unwanted keystrokes. (In your case, you don't need this because there aren't any keys you want to exclude.)
  • Handle the wm_Paste message to account for text pasted from the clipboard.
  • Handle the wm_SetText message to account for text being set in most other conventional ways. (This takes care of most of your list: LoadFromFile, Add, Append, Insert, Text := ....)
  • Handle the em_ReplaceSel message to account for selected text being overwritten.

In Below's write-up, he simply rejects any non-conforming input. That's probably not what you want, though. Instead, you'll want to normalize the input so that it uses uniform line-ending sequences. Rather than just swallow the text-changing messages listed above, you'll want to massage the input and then forward it to the normal handler.

For controlling line endings, Delphi already provides a function that does the kind of massaging you want: AdjustLineBreaks. You can pick whether you want Unix- or Windows-style line endings. (Note that not even Macintosh uses Mac-style line endings anymore.) You probably want tlbsCRLF because that's the style the Windows edit control knows how to display; as you've noted, it doesn't display line breaks if there aren't any carriage returns.

For wm_SetText and em_ReplaceSel, the change is easy. Here's a sketch:

procedure TLineNormalizingMemo.WMSetText(var Message: TWMSetText);
var
  s: string;
begin
  s := Message.Text;
  s := AdjustLineBreaks(s);
  Message.Text := PChar(s);
  inherited;
end;

It's not quite so obvious for wm_Paste because you're not given the new text, and you're not supposed to change the text that's currently on the clipboard. Instead, you can opt not to call inherited, handling the effects of pasting yourself. Something like this:

procedure TLineNormalizingMemo.WMPaste(var Message: TWMPaste);
var
  s: string;
begin
  if Clipboard.HasFormat(cf_Text) then begin
    s := Clipboard.AsText;
    s := AdjustLineBreaks(s);
    SelText := s;
  end;
end;

Since assigning SelText goes through the em_ReplaceSel message, you might not even need to call AdjustLineBreaks there.

0
votes

Just set the Lines.LineBreak property to LF:

memo1.lines.LineBreak := #10;

The default is #13#10 in Windows.