lazarus-ccr/components/xdev_toolkit/RtfDoc.pas

261 lines
6.8 KiB
ObjectPascal

unit RtfDoc;
{
Class for creating RTF document.
Author: Phil Hess.
Copyright: Copyright (C) 2007 Phil Hess. All rights reserved.
License: Modified LGPL. This means you can link your code to this
compiled unit (statically in a standalone executable or
dynamically in a library) without releasing your code. Only
changes to this unit need to be made publicly available.
}
interface
{$IFDEF FPC}
{$MODE Delphi}
{$ENDIF}
uses
SysUtils,
RtfPars;
type
TRtfDoc = class(TObject)
private
FParser : TRTFParser;
procedure DoGroup;
procedure DoCtrl;
procedure DoText;
{$IFDEF FPC}
procedure HandleError(s : ShortString);
{$ELSE} {Delphi}
procedure HandleError(s : string);
{$ENDIF}
protected
FFileName : string;
FFileVar : TextFile;
public
constructor Create;
destructor Destroy; override;
property Parser : TRTFParser read FParser;
property FileName : string read FFileName;
procedure Start(const FileName : string); virtual;
procedure Done; virtual;
procedure OutDefaultFontTable(DefFont : Integer); virtual;
procedure OutToken( AClass : Integer;
Major : Integer;
Minor : Integer;
Param : Integer;
const Text : string); virtual;
procedure OutCtrl(Major : Integer;
Minor : Integer;
Param : Integer); virtual;
procedure OutText(const Text : string); virtual;
end;
implementation
constructor TRtfDoc.Create;
begin
inherited Create;
FParser := TRTFParser.Create(nil);
end;
destructor TRtfDoc.Destroy;
begin
Parser.Free;
inherited Destroy;
end;
procedure TRtfDoc.Start(const FileName : string);
var
CurYear : Word;
CurMonth : Word;
CurDay : Word;
CurHour : Word;
CurMinute : Word;
CurSecond : Word;
CurSec100 : Word;
begin
FFileName := FileName;
AssignFile(FFileVar, FFileName);
Rewrite(FFileVar);
Parser.ResetParser;
Parser.ClassCallbacks[rtfGroup] := DoGroup;
Parser.ClassCallbacks[rtfText] := DoText;
Parser.ClassCallbacks[rtfControl] := DoCtrl;
Parser.DestinationCallbacks[rtfFontTbl] := nil;
Parser.DestinationCallbacks[rtfColorTbl] := nil;
Parser.DestinationCallbacks[rtfInfo] := nil;
Parser.OnRTFError := HandleError;
OutToken(rtfGroup, rtfBeginGroup, -1, rtfNoParam, '');
OutCtrl(rtfVersion, -1, 1);
OutCtrl(rtfCharSet, rtfAnsiCharSet, rtfNoParam);
{Output document creation date and time}
DecodeDate(Now, CurYear, CurMonth, CurDay);
DecodeTime(Now, CurHour, CurMinute, CurSecond, CurSec100);
OutToken(rtfGroup, rtfBeginGroup, -1, rtfNoParam, '');
OutCtrl(rtfDestination, rtfInfo, rtfNoParam);
OutToken(rtfGroup, rtfBeginGroup, -1, rtfNoParam, '');
OutCtrl(rtfSpecialChar, rtfICreateTime, rtfNoParam);
OutCtrl(rtfSpecialChar, rtfIYear, CurYear);
OutCtrl(rtfSpecialChar, rtfIMonth, CurMonth);
OutCtrl(rtfSpecialChar, rtfIDay, CurDay);
OutCtrl(rtfSpecialChar, rtfIHour, CurHour);
OutCtrl(rtfSpecialChar, rtfIMinute, CurMinute);
OutToken(rtfGroup, rtfEndGroup, -1, rtfNoParam, '');
OutToken(rtfGroup, rtfEndGroup, -1, rtfNoParam, '');
WriteLn(FFileVar);
end; {TRtfDoc.Start}
procedure TRtfDoc.OutDefaultFontTable(DefFont : Integer);
begin
{Output default font number}
OutCtrl(rtfDefFont, -1, DefFont);
{Output font table}
OutToken(rtfGroup, rtfBeginGroup, -1, rtfNoParam, '');
OutCtrl(rtfDestination, rtfFontTbl, rtfNoParam);
OutToken(rtfGroup, rtfBeginGroup, -1, rtfNoParam, '');
OutCtrl(rtfCharAttr, rtfFontNum, 0);
OutToken(rtfControl, rtfFontFamily, rtfFFModern, rtfNoParam,
'Courier New;');
OutToken(rtfGroup, rtfEndGroup, -1, rtfNoParam, '');
OutToken(rtfGroup, rtfBeginGroup, -1, rtfNoParam, '');
OutCtrl(rtfCharAttr, rtfFontNum, 1);
OutToken(rtfControl, rtfFontFamily, rtfFFRoman, rtfNoParam,
'Times New Roman;');
OutToken(rtfGroup, rtfEndGroup, -1, rtfNoParam, '');
OutToken(rtfGroup, rtfBeginGroup, -1, rtfNoParam, '');
OutCtrl(rtfCharAttr, rtfFontNum, 2);
OutToken(rtfControl, rtfFontFamily, rtfFFSwiss, rtfNoParam,
'Arial;');
OutToken(rtfGroup, rtfEndGroup, -1, rtfNoParam, '');
OutToken(rtfGroup, rtfEndGroup, -1, rtfNoParam, '');
WriteLn(FFileVar);
end; {TRtfDoc.OutDefaultFontTable}
procedure TRtfDoc.Done;
begin
WriteLn(FFileVar);
OutToken(rtfGroup, rtfEndGroup, -1, rtfNoParam, '');
CloseFile(FFileVar);
end;
procedure TRtfDoc.OutToken( AClass : Integer;
Major : Integer;
Minor : Integer;
Param : Integer;
const Text : string);
begin
Parser.SetToken(AClass, Major, Minor, Param, Text);
Parser.RouteToken;
if Text <> '' then
Write(FFileVar, Text);
end;
procedure TRtfDoc.OutCtrl(Major : Integer;
Minor : Integer;
Param : Integer);
begin
OutToken(rtfControl, Major, Minor, Param, '');
end;
procedure TRtfDoc.OutText(const Text : string);
var
CharNum : Integer;
begin
for CharNum := 1 to Length(Text) do
OutToken(rtfText, Ord(Text[CharNum]), 0, rtfNoParam, '');
end;
procedure TRtfDoc.DoGroup;
begin
if Parser.rtfMajor = rtfBeginGroup then
Write(FFileVar, '{')
else
Write(FFileVar, '}');
end;
procedure TRtfDoc.DoCtrl;
var
RtfIdx : Integer;
begin
if (Parser.rtfMajor = rtfSpecialChar) and
(Parser.rtfMinor = rtfPar) then
WriteLn(FFileVar); {Make RTF file more human readable}
RtfIdx := 0;
while rtfKey[RtfIdx].rtfKStr <> '' do
begin
if (Parser.rtfMajor = rtfKey[RtfIdx].rtfKMajor) and
(Parser.rtfMinor = rtfKey[RtfIdx].rtfKMinor) then
begin
Write(FFileVar, '\');
Write(FFileVar, rtfKey[RtfIdx].rtfKStr);
if Parser.rtfParam <> rtfNoParam then
Write(FFileVar, IntToStr(Parser.rtfParam));
if rtfKey[RtfIdx].rtfKStr <> '*' then
Write(FFileVar, ' ');
Exit;
end;
Inc(RtfIdx);
end;
end; {TRtfDoc.DoCtrl}
procedure TRtfDoc.DoText;
var
AChar : Char;
begin
{rtfMajor contains the character ASCII code,
so just output it for now, preceded by \
if special char.}
AChar := Chr(Parser.rtfMajor);
case AChar of
'\' : Write(FFileVar, '\\');
'{' : Write(FFileVar, '\{');
'}' : Write(FFileVar, '\}');
else
begin
if AChar > #127 then {8-bit ANSI character?}
Write(FFileVar, '\''' + IntToHex(Ord(AChar), 2)) {Encode using 7-bit chars}
else {7-bit ANSI character}
Write(FFileVar, AChar);
end;
end;
end; {TRtfDoc.DoText}
{$IFDEF FPC}
procedure TRtfDoc.HandleError(s : ShortString);
begin
WriteLn(StdErr, s);
end;
{$ELSE} {Delphi}
procedure TRtfDoc.HandleError(s : string);
begin
WriteLn(ErrOutput, S);
end;
{$ENDIF}
end.