For my application using RTF text saved in a database BLOB field, I copied the Action List Editor and changed its Save method to return the modified RTF to the caller. I also modified the editor's OnShow event to load the caller-supplied initial RTF into the editor.
The editor is called in my application when the user double-clicks a RichEdit embedded in a grid linked to the database. Grid and RichEdit are from WolltoWoll (InfoPower).
My code works correctly, but several doubts linger:
1: Are there unnecessary encoding conversions being done ?? Unicode to ansi string or whatever.
2: Are there points where conversions are missing or could mess up my text ?? The application only handles English, Spanish and French text.
3: Is the code suppressing the extra paragraphs TRichView adds still required, and correct ?? Is there some better way to do this, or suppress the addition of paragraphs ??
I would be very grateful if someone would review my code and make any comments they think appropriate. If you have any questions I will, of course, answer them as best I can.
JF
Code: Select all
Test Program:
=============
procedure TRichViewEditorTest.MyDBRichEditDblClick (Sender: TObject);
var
Local_RTF_Text: string;
begin
RichViewEditor_15_3_2 := TRichViewEditor_15_3_2.Create (RichViewEditorTest);
try
RichViewEditor_15_3_2.Text_In_RTF := AnsiString(MyDBRichEdit.GetRTFText);
RichViewEditor_15_3_2.PopupParent := RichViewEditorTest;
RichViewEditor_15_3_2.ShowModal;
if (RichViewEditor_15_3_2.Text_Changed) then
begin
if ((MyQuery.State <> dsEdit) and
(MyQuery.State <> dsInsert)) then
MyQuery.Edit;
MyDBRichEdit.Clear;
MyDBRichEdit.SetRTFText(string(RichViewEditor_15_3_2.Text_In_RTF));
MyDBRichEdit.CopyRichEdittoBlob(MyQueryCLOB_FIELD);
Local_RTF_Text := MyQueryCLOB_FIELD.AsString; // These 3 lines remove the extra
Strip_Redundant_Final_Paragraph (Local_RTF_Text); // paragraph appended when text is
MyQueryCLOB_FIELD.AsString := Local_RTF_Text; // saved.
MyQuery.Post;
end;
finally
RichViewEditor_15_3_2.Free;
end;
end;
################################################################
FormRichViewEditor_15_3_2:
==========================
public
Text_In_RTF: AnsiString;
Text_Changed: Boolean;
// Load the text to be edited into the RichViewEdit object.
procedure TRichViewEditor_15_3_2.FormShow (Sender: TObject);
var
Text_Memory_Stream: TMemoryStream;
begin
Text_Memory_Stream := TMemoryStream.Create;
try
Text_Memory_Stream.WriteBuffer(PRVAnsiChar(Text_In_RTF)^, Length(Text_In_RTF));
Text_Memory_Stream.Position := 0;
RichViewEdit.Clear;
RichViewEdit.LoadRTFFromStream(Text_Memory_Stream);
RichViewEdit.Format;
finally
Text_Memory_Stream.Free;
end;
Text_Changed := False;
end;
################################################################
procedure TRichViewEditor_15_3_2.rvActionSave1Execute (Sender: TObject);
var
My_Memory_Stream: TMemoryStream;
begin
// Get the RTF text into the output AnsiString variable "Text_In_RTF".
My_Memory_Stream := TMemoryStream.Create;
try
RichViewEdit.SaveRTFToStream (My_Memory_Stream, False);
Text_In_RTF := '';
SetLength (Text_In_RTF, My_Memory_Stream.Size);
My_Memory_Stream.Position := 0;
My_Memory_Stream.ReadBuffer(PRVAnsiChar(Text_In_RTF)^, Length(Text_In_RTF));
// Change all instances of the "\chcbpat<N>" keyword to "\highlight<N>".
Text_In_RTF := System.AnsiStrings.AnsiReplaceStr (Text_In_RTF, '\chcbpat', '\highlight');
finally
Defn_Text_Memory_Stream.Free;
end;
Text_Changed := True;
end;
################################################################
{--------------------------------------------------------------------------------------------------}
{ The end of an RTF text created by the RichView editor includes the last three lines: }
{ <maybe some text or directives>\par }
{ \pard\lang3082<maybe other directives>\par }
{ <right curly bracket> }
{ An extra paragraph was introduced in TRichView for compatibility with Word but causes an extra }
{ blank line to be added at the end of a Rich Text on screen and when printed using FastReport. }
{ The problem on screen is mostly cosmetic. On the printed report, however, it means all single- }
{ line texts become two (or more) lines, one extra being added each time the data is edited and }
{ the changes saved. This is a massive waste in the vertical dimension. }
{ To solve this problem, this routine should be called immediately following the line which copies }
{ the Rich Text to the database CLOB field on returning from the editor: }
{ <MyDBRichEdit>.CopyRichEdittoBlob(<MyQuery><MyCLOBField>); }
{ }
{ Local_RTF_Text := <MyQuery><MyCLOBField>.AsString; }
{ Strip_Redundant_Final_Paragraph (Local_RTF_Text); }
{ <MyQuery><MyCLOBField>.AsString := Local_RTF_Text; }
{ }
{--------------------------------------------------------------------------------------------------}
procedure Strip_Redundant_Final_Paragraph (var RTF_String: string);
var
Local_Length: Integer;
Line_To_Modify: string;
begin
Printable_RTF := TStringList.Create;
try
Printable_RTF.Text := RTF_String;
if (Printable_RTF.Count >= 2) then
begin
Local_Length := Length(Printable_RTF.Strings[Printable_RTF.Count-3]);
if (Local_Length >= 4) then
begin
Line_To_Modify := Printable_RTF.Strings[Printable_RTF.Count-3];
if (CompareText(Copy(Line_To_Modify, Local_Length-3, 4), '\par') = 0) then
begin
Line_To_Modify := Copy(Line_To_Modify, 1, Local_Length-4);
if (Line_To_Modify <> '') then
Printable_RTF.Strings[Printable_RTF.Count-3] := Line_To_Modify
else
Printable_RTF.Delete(Printable_RTF.Count-3);
RTF_String := Printable_RTF.Text;
end;
end;
end;
finally
Printable_RTF.Free;
end;
end;