
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@75 8e941d3f-bd1b-0410-a28a-d453659cc2b4
1181 lines
33 KiB
ObjectPascal
1181 lines
33 KiB
ObjectPascal
{ TRTFView a component to view documents in RTF format.
|
|
|
|
Copyright (C) 2007 Jesus Reyes Aguilar jesusrmx@yahoo.com.mx
|
|
|
|
This library is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU Library General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or (at your
|
|
option) any later version with the following modification:
|
|
|
|
As a special exception, the copyright holders of this library give you
|
|
permission to link this library with independent modules to produce an
|
|
executable, regardless of the license terms of these independent modules,and
|
|
to copy and distribute the resulting executable under terms of your choice,
|
|
provided that you also meet, for each linked independent module, the terms
|
|
and conditions of the license of that module. An independent module is a
|
|
module which is not derived from or based on this library. If you modify
|
|
this library, you may extend this exception to your version of the library,
|
|
but you are not obligated to do so. If you do not wish to do so, delete this
|
|
exception statement from your version.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; if not, write to the Free Software Foundation,
|
|
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
}
|
|
|
|
unit RTFView;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, RichView,
|
|
RVStyle,
|
|
// RTFPars is a fpc/fcl provided unit.
|
|
// Some changes that are needed for this component were fixed in
|
|
// fpc 2.1.1 revision 6507. For older systems UsePre211RTFPars conditional
|
|
// could be used.
|
|
{$ifdef UsePre211RtfPars}
|
|
RTFParsPre211
|
|
{$else}
|
|
RTFPars
|
|
{$endif}
|
|
;
|
|
|
|
{.$define Debug}
|
|
{.$define DumpText}
|
|
{.$define DumpRtf}
|
|
|
|
type
|
|
TTextAttributes=class
|
|
Color: TColor;
|
|
FontName: TFontName;
|
|
Style: TFontStyles;
|
|
Size: Integer;
|
|
end;
|
|
|
|
PStyleRec=^TStyleRec;
|
|
TStyleRec=record
|
|
FontDef: Integer;
|
|
Font,FontSize: Integer;
|
|
FontStyles: TFontStyles;
|
|
ForeColor,BackColor: Integer;
|
|
Centered: boolean;
|
|
StyleChanged: boolean;
|
|
LastStyle: Integer;
|
|
NoText: boolean;
|
|
GrpText: boolean;
|
|
// aditional info
|
|
OptionalDest: boolean;
|
|
end;
|
|
|
|
|
|
{ TRTFView }
|
|
|
|
TRTFView = class(TCustomRichView)
|
|
private
|
|
FCurStyle: TStyleRec;
|
|
|
|
FParrafoParcial: boolean;
|
|
FGroupLevel: Integer;
|
|
FStyleGroupChanged: boolean;
|
|
|
|
FStack: array of TStyleRec;
|
|
FNoText: boolean;
|
|
FGroupText: boolean;
|
|
FPendingLine: boolean;
|
|
FExpandingStyleLevel:Integer;
|
|
|
|
FParser : TRTFParser;
|
|
FIdent: Integer;
|
|
FCurText: string;
|
|
FDefaultForeColor: TColor;
|
|
FDefaultBackColor: TColor;
|
|
|
|
procedure ClearCurStyle;
|
|
Procedure DoDestination;
|
|
procedure doSpecialchar;
|
|
procedure doCharAttribute;
|
|
procedure doParAttributes;
|
|
procedure doDocAttribute;
|
|
procedure doSectAttribute;
|
|
procedure DoCtrl;
|
|
procedure DoGroup;
|
|
Procedure DoWrite;
|
|
function GetCheckPoints: TStringlist;
|
|
procedure HandleError ( s : shortstring);
|
|
function ParValue: string;
|
|
{$IFDEF Debug}
|
|
procedure DumpFonts;
|
|
procedure DumpColors;
|
|
procedure DumpStyles;
|
|
{$ENDIF}
|
|
// rutinas para cargar los estilos
|
|
function FindStyle: Integer;
|
|
procedure StyleModified;
|
|
procedure EmitirInterParrafo;
|
|
procedure PopStyle;
|
|
procedure PushStyle;
|
|
procedure MergePreviousLine(txt: string; center: boolean; Rv: Integer);
|
|
// debug
|
|
procedure MyWriteLn(msg: string); overload;
|
|
procedure MyWriteLn(msg1, Msg2: string); overload;
|
|
procedure DebugSt(St: TStyleRec; msg:string='');
|
|
procedure MyWriteLn(Msg: string; aInt: Integer);
|
|
|
|
protected
|
|
function GetCredits: string; override;
|
|
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure LoadFromFile(aRTFFile: string);
|
|
property ChkPoints:TStringlist read GetCheckPoints;
|
|
//property Style;
|
|
private
|
|
Flog: TextFile;
|
|
FLogIdent: Integer;
|
|
FWaitingFirstControlWord: boolean;
|
|
procedure ReadHandler;
|
|
|
|
published
|
|
property Align;
|
|
property AllowSelection;
|
|
property Anchors;
|
|
property BackgroundBitmap;
|
|
property BackgroundStyle;
|
|
property DefaultForeColor:TColor read FDefaultForeColor write FDefaultForeColor;
|
|
property DefaultBackColor:TColor read FDefaultBackColor write FDefaultBackColor;
|
|
property FirstJumpNo;
|
|
property HelpContext;
|
|
property LeftMargin;
|
|
property MaxTextWidth;
|
|
property MinTextWidth;
|
|
property PopupMenu;
|
|
property RightMargin;
|
|
property SingleClick;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Tracking;
|
|
property Visible;
|
|
property VScrollVisible;
|
|
|
|
property OnClick;
|
|
property OnJump;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnResized;
|
|
property OnRVDblClick;
|
|
property OnRVMouseMove;
|
|
property OnRVRightClick;
|
|
property OnSaveComponentToFile;
|
|
property OnSelect;
|
|
property OnURLNeeded;
|
|
property OnVScrolled;
|
|
|
|
//property OnSaveComponentToFile;
|
|
//property Delimiters;
|
|
end;
|
|
|
|
procedure Register;
|
|
|
|
implementation
|
|
|
|
procedure Register;
|
|
begin
|
|
RegisterComponents('RichView',[TRTFView]);
|
|
end;
|
|
|
|
{ Generic routines }
|
|
|
|
function SomeText(Msg,Txt: string): string;
|
|
begin
|
|
if txt<>'' then begin
|
|
result:=Msg+'"'+Copy(Txt, 1, 15)+'|-->"';
|
|
end else
|
|
result:='';
|
|
end;
|
|
|
|
procedure TRTFView.MyWriteLn(msg: string);
|
|
begin
|
|
{$IFDEF DEBUG}
|
|
WriteLn(StringOfChar(' ', FIdent),Msg)
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TRTFView.MyWriteLn(msg1, Msg2: string);
|
|
begin
|
|
{$IFDEF DEBUG}
|
|
WriteLn(StringOfChar(' ', FIdent),Msg1, Msg2);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TRTFView.MyWriteLn(Msg: string; aInt: Integer);
|
|
begin
|
|
{$IFDEF DEBUG}
|
|
WriteLn(StringOfChar(' ', FIdent),Msg, aInt);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TRTFView.ReadHandler;
|
|
begin
|
|
case FParser.rtfClass of
|
|
rtfGroup:
|
|
begin
|
|
if FParser.rtfMajor=rtfBeginGroup then begin;
|
|
{$ifdef Debug}
|
|
Write(FLog, StringOfChar(' ', FLogIdent),'{');
|
|
{$endif}
|
|
Inc(FLogIdent, 2);
|
|
FWaitingFirstControlWord:=True;
|
|
end else
|
|
if FParser.rtfMajor=rtfEndGroup then begin
|
|
FWaitingFirstControlWord:=False;
|
|
Dec(FLogIdent, 2);
|
|
{$IFDEF DEBUG}
|
|
WriteLn(FLog, StringOfChar(' ', FLogIdent), '}');
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
rtfControl:
|
|
begin
|
|
if FWaitingFirstControlWord then begin
|
|
{$IFDEF DEBUG}
|
|
WriteLn(FLog, FParser.GetRtfText);
|
|
{$ENDIF}
|
|
FWaitingFirstControlWord:=False;
|
|
end
|
|
{$IFDEF DEBUG}
|
|
else
|
|
WriteLn(FLog, StringOfChar(' ', FLogIdent), FParser.GetRtfText);
|
|
if FCurText<>'' then begin
|
|
WriteLn(FLog, SomeText('',FCurText));
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
{
|
|
rtfText:
|
|
begin
|
|
WriteLn(FLog, StringOfChar(' ', FLogIdent), SomeText('',FCurText));
|
|
end;
|
|
}
|
|
rtfUnknown:
|
|
begin
|
|
if FWaitingFirstControlWord then begin
|
|
{$IFDEF DEBUG}
|
|
WriteLn(FLog, '[',FParser.GetRtfText,']');
|
|
//WriteLn(FLog, StringOfChar(' ', FLogIdent), FParser.GetRtfText);
|
|
{$ENDIF}
|
|
FWaitingFirstControlWord:=False;
|
|
end else
|
|
{$IFDEF DEBUG}
|
|
WriteLn(FLog, StringOfChar(' ', FLogIdent), '[',FParser.GetRtfText,']');
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function NumEstilo(Num:Integer): string;
|
|
begin
|
|
if Num=rtfBasedOnNone then
|
|
result := 'none'
|
|
else
|
|
result := IntToStr(Num);
|
|
end;
|
|
|
|
function FStoS(Fs:TFontstyles): string;
|
|
begin
|
|
result:='';
|
|
if fsBold in Fs then result := Result +'B';
|
|
if fsItalic in Fs then result := result + 'I';
|
|
if fsUnderline in Fs then result:=result +'U';
|
|
if fsStrikeout in fs then result := result + 'S';
|
|
result:='['+result+']';
|
|
end;
|
|
|
|
procedure TRTFView.DebugSt(St: TStyleRec; msg:string='');
|
|
var
|
|
s: string;
|
|
begin
|
|
if msg<>'' then
|
|
msg:=msg+': ';
|
|
s := StringOfChar(' ',FIdent);
|
|
WriteLn(s, msg,
|
|
'Fn=',St.Font,' FnSz=',St.FontSize,' Clr=',St.ForeColor,
|
|
' St=',fstos(St.FontStyles),' Cen=',St.Centered,' SC=',St.StyleChanged,
|
|
' LS=',St.LastStyle,' Nt=',St.NoText);
|
|
end;
|
|
|
|
function RGB(R,G,B: byte): TColor;
|
|
begin
|
|
//result := (byte(b) shl 16) or (byte(g) shl 8) or byte(r);
|
|
result := StringToColor('$'+IntToHex(b,2)+IntToHex(g,2)+IntToHex(r,2));
|
|
end;
|
|
|
|
function rtfColorToColor(C: PRtfColor; DefColor:TColor): TColor;
|
|
begin
|
|
if (C^.rtfCBlue=-1)and(C^.rtfCGreen=-1)and(C^.rtfCRed=-1) then
|
|
result := DefColor
|
|
else
|
|
result := Rgb(C^.rtfCRed, C^.rtfCGreen, C^.rtfCBlue);
|
|
end;
|
|
|
|
|
|
{ TRTFView }
|
|
|
|
procedure TRTFView.ClearCurStyle;
|
|
begin
|
|
FCurStyle.Font := FCurStyle.FontDef;
|
|
FCurStyle.FontSize := 12;
|
|
FCurStyle.FontStyles := [];
|
|
FCurStyle.ForeColor := -1;
|
|
FCurStyle.BackColor := -1;
|
|
FCurStyle.Centered := False;
|
|
end;
|
|
|
|
procedure TRTFView.DoDestination;
|
|
begin
|
|
FParser.skipgroup;
|
|
MyWriteLn('DoDestination Group Skipped', FIdent);
|
|
end;
|
|
|
|
procedure TRTFView.doSpecialchar;
|
|
var
|
|
RV: Integer;
|
|
S: String;
|
|
Li: TLineInfo;
|
|
i: Integer;
|
|
begin
|
|
case FParser.RTFMinor of
|
|
rtfCurHeadPage : MyWriteLn('rtfCurHeadPage');
|
|
rtfCurFNote : MyWriteLn('rtfCurFNote');
|
|
rtfCurHeadPict : MyWriteLn('rtfCurHeadPict');
|
|
rtfCurHeadDate : MyWriteLn('rtfCurHeadDate');
|
|
rtfCurHeadTime : MyWriteLn('rtfCurHeadTime');
|
|
rtfFormula : MyWriteLn('rtfFormula');
|
|
rtfNoBrkSpace : MyWriteLn('rtfNoBrkSpace');
|
|
rtfNoReqHyphen : MyWriteLn('rtfNoReqHyphen');
|
|
rtfNoBrkHyphen : MyWriteLn('rtfNoBrkHyphen');
|
|
rtfPage : MyWriteLn('rtfPage');
|
|
rtfLine:
|
|
begin
|
|
MyWriteLn('<--| NOTED rtfLine');
|
|
FPendingLine:=True;
|
|
if FNoText then begin
|
|
MyWriteLn(' Saltandose el texto');
|
|
exit;
|
|
end;
|
|
RV := FindStyle;
|
|
if FCurStyle.Centered then
|
|
AddCenterLine(FCurText, Rv)
|
|
else begin
|
|
if FCurText='' then
|
|
AddFromNewLine(' ', Rv)
|
|
else begin
|
|
if FParrafoParcial then
|
|
Add(FCurText, RV)
|
|
else
|
|
AddFromNewLine(FCurText, Rv);
|
|
end;
|
|
end;
|
|
{$IFDEF DUMPTEXT}
|
|
WriteLn;
|
|
{$ENDIF}
|
|
FParrafoParcial:=False;
|
|
FCurStyle.LastStyle:=RV;
|
|
FCurStyle.StyleChanged:=False;
|
|
FCurText := '';
|
|
end;
|
|
rtfpar:
|
|
begin
|
|
MyWriteLn('<--| NOTED rtfpar');
|
|
if FNoText then begin
|
|
MyWriteLn(' Saltandose el texto');
|
|
exit;
|
|
end;
|
|
RV := FindStyle;
|
|
if FCurStyle.Centered then begin
|
|
// if FPendingLine then merge previous line with
|
|
// this
|
|
if FPendingLine then
|
|
MergePreviousLine(FCurText, True, Rv)
|
|
else
|
|
AddCenterLine(FCurText, Rv)
|
|
end else begin
|
|
if FCurText='' then
|
|
AddFromNewLine(' ', Rv)
|
|
else begin
|
|
if FParrafoParcial then
|
|
Add(FCurText, RV)
|
|
else
|
|
AddFromNewLine(FCurText, Rv);
|
|
end;
|
|
end;
|
|
{$IFDEF DUMPTEXT}
|
|
WriteLn;
|
|
{$ENDIF}
|
|
FPendingLine:=False;
|
|
FParrafoParcial:=False;
|
|
FCurStyle.LastStyle:=RV;
|
|
FCurStyle.StyleChanged:=False;
|
|
FCurText := '';
|
|
end;
|
|
rtfSect : MyWriteLn('rtfSect');
|
|
rtfTab : MyWriteLn('rtfTab');
|
|
rtfCell : MyWriteLn('rtfCell');
|
|
rtfRow : MyWriteLn('rtfRow');
|
|
rtfCurAnnot : MyWriteLn('rtfCurAnnot');
|
|
rtfAnnotation : MyWriteLn('rtfAnnotation');
|
|
rtfAnnotID : MyWriteLn('rtfAnnotID');
|
|
rtfCurAnnotRef : MyWriteLn('rtfCurAnnotRef');
|
|
rtfFNoteSep : MyWriteLn('rtfFNoteSep');
|
|
rtfFNoteCont : MyWriteLn('rtfFNoteCont');
|
|
rtfColumn : MyWriteLn('rtfColumn');
|
|
rtfOptDest:
|
|
begin
|
|
MyWriteLn('NOTED rtfOptDest');
|
|
if FExpandingStyleLevel=0 then
|
|
FNoText := True;
|
|
//Fparser.SkipGroup;
|
|
end;
|
|
rtfIIntVersion : MyWriteLn('rtfIIntVersion');
|
|
rtfICreateTime : MyWriteLn('rtfICreateTime');
|
|
rtfIRevisionTime : MyWriteLn('rtfIRevisionTime');
|
|
rtfIPrintTime : MyWriteLn('rtfIPrintTime');
|
|
rtfIBackupTime : MyWriteLn('rtfIBackupTime');
|
|
rtfIEditTime : MyWriteLn('rtfIEditTime');
|
|
rtfIYear : MyWriteLn('rtfIYear');
|
|
rtfIMonth : MyWriteLn('rtfIMonth');
|
|
rtfIDay : MyWriteLn('rtfIDay');
|
|
rtfIHour : MyWriteLn('rtfIHour');
|
|
rtfIMinute : MyWriteLn('rtfIMinute');
|
|
rtfINPages : MyWriteLn('rtfINPages');
|
|
rtfINWords : MyWriteLn('rtfINWords');
|
|
rtfINChars : MyWriteLn('rtfINChars');
|
|
rtfIIntID : MyWriteLn('rtfIIntID');
|
|
else
|
|
MyWriteLn('rtfSpecialChar, ??? rtfMinor=',FParser.rtfMinor);
|
|
end;
|
|
end;
|
|
|
|
procedure TRTFView.doCharAttribute;
|
|
function ParColor: string;
|
|
var
|
|
c: PRTFColor;
|
|
begin
|
|
c := FParser.Colors[Fparser.rtfParam];
|
|
result := ' Color '+IntToStr(Fparser.rtfParam)+' =';
|
|
if c=nil then
|
|
result := Result + 'nil'
|
|
else
|
|
with c^ do
|
|
result := Result + '['+SysUtils.Format('R=%d G=%d B=%d',
|
|
[rtfCRed,rtfCGreen,rtfCBlue])+']';
|
|
end;
|
|
function Fuente: string;
|
|
var
|
|
f: PRTFFont;
|
|
begin
|
|
f := FParser.Fonts[FParser.rtfParam];
|
|
result := ' Fuente '+IntToStr(Fparser.rtfParam)+' =';
|
|
if f=nil then
|
|
result := result + 'nil'
|
|
else
|
|
result := result + '['+SysUtils.Format('Name=%s Family=%d',
|
|
[f^.rtfFName, f^.rtfFFamily])+']';
|
|
end;
|
|
function FontSize: string;
|
|
begin
|
|
result := ' Size='+IntToStr(Fparser.rtfParam);
|
|
end;
|
|
function CheckStyle(Fs: TFontStyle): boolean;
|
|
var
|
|
oldbool,Newbool: boolean;
|
|
begin
|
|
OldBool := Fs in FCurStyle.FontStyles;
|
|
if FParser.rtfParam=rtfNoParam then
|
|
NewBool := true
|
|
else
|
|
Newbool := FParser.rtfParam > 0;
|
|
result := NewBool<>OldBool;
|
|
if NewBool then
|
|
Include(FCurStyle.FontStyles, Fs)
|
|
else
|
|
Exclude(FCurStyle.FontStyles, Fs);
|
|
if Result then
|
|
StyleModified;
|
|
end;
|
|
begin
|
|
case Fparser.RTFMinor of
|
|
rtfPlain:
|
|
begin
|
|
StyleModified;
|
|
FCurStyle.FontStyles := [];
|
|
MyWriteLn('NOTED rtfPlain');
|
|
end;
|
|
rtfBold:
|
|
begin
|
|
CheckStyle(fsBold);
|
|
MyWriteLn('NOTED rtfBold', ParValue);
|
|
end;
|
|
rtfItalic:
|
|
begin
|
|
CheckStyle(fsItalic);
|
|
MyWriteLn('NOTED rtfItalic', ParValue);
|
|
end;
|
|
rtfStrikeThru:
|
|
begin
|
|
StyleModified;
|
|
Include(FCurStyle.FontStyles, fsStrikeOut);
|
|
MyWriteLn('NOTED rtfStrikeThru');
|
|
end;
|
|
rtfOutline : MyWriteLn('rtfOutline');
|
|
rtfShadow : MyWriteLn('rtfShadow');
|
|
rtfSmallCaps : MyWriteLn('rtfSmallCaps');
|
|
rtfAllCaps : MyWriteLn('rtfAllCaps');
|
|
rtfInvisible : MyWriteLn('rtfInvisible');
|
|
rtfFontNum:
|
|
begin
|
|
StyleModified;
|
|
FCurStyle.Font := FParser.rtfParam;
|
|
MyWriteLn('NOTED rtfFontNum', Fuente);
|
|
end;
|
|
rtfFontSize:
|
|
begin
|
|
StyleModified;
|
|
MyWriteLn('NOTED rtfFontSize', FontSize);
|
|
FCurStyle.FontSize := FParser.rtfParam div 2;
|
|
end;
|
|
rtfExpand : MyWriteLn('rtfExpand');
|
|
rtfUnderline:
|
|
begin
|
|
StyleModified;
|
|
Include(FCurStyle.FontStyles, fsUnderline);
|
|
MyWriteLn('NOTED rtfUnderline');
|
|
end;
|
|
rtfWUnderline:
|
|
begin
|
|
StyleModified;
|
|
Include(FCurStyle.FontStyles, fsUnderline);
|
|
MyWriteLn('TWEAK rtfWUnderline');
|
|
end;
|
|
rtfDUnderline:
|
|
begin
|
|
StyleModified;
|
|
Include(FCurStyle.FontStyles, fsUnderline);
|
|
MyWriteLn('TWEAK rtfDUnderline');
|
|
end;
|
|
rtfDbUnderline:
|
|
begin
|
|
StyleModified;
|
|
Include(FCurStyle.FontStyles, fsUnderline);
|
|
MyWriteLn('TWEAK rtfDbUnderline');
|
|
end;
|
|
rtfNoUnderline:
|
|
begin
|
|
StyleModified;
|
|
Exclude(FCurStyle.FontStyles, fsUnderline);
|
|
MyWriteLn('NOTED rtfNoUnderline');
|
|
end;
|
|
rtfSuperScript : MyWriteLn('rtfSuperScript');
|
|
rtfSubScript : MyWriteLn('rtfSubScript');
|
|
rtfRevised : MyWriteLn('rtfRevised');
|
|
rtfForeColor:
|
|
begin
|
|
FCurStyle.ForeColor := FParser.rtfParam;
|
|
MyWriteLn('NOTED rtfForeColor', ParColor);
|
|
end;
|
|
rtfBackColor:
|
|
begin
|
|
FCurStyle.BackColor := FParser.rtfParam;
|
|
MyWriteLn('NOTED rtfBackColor', ParColor);
|
|
end;
|
|
rtfGray : MyWriteLn('rtfGray');
|
|
end;
|
|
end;
|
|
|
|
procedure TRTFView.doParAttributes;
|
|
var
|
|
n: Integer;
|
|
begin
|
|
case Fparser.RTFMinor of
|
|
rtfStyleNum :
|
|
begin
|
|
n := Fparser.rtfParam;
|
|
MyWriteLn('NOTED rtfStyleNum Value=',NumEstilo(n));
|
|
MyWriteLn('INI Expandiendo estilo FNoText='+BoolToStr(FnoText));
|
|
Inc(FExpandingStyleLevel);
|
|
Inc(FIdent, 3);
|
|
Fparser.ExpandStyle(n);
|
|
Dec(FExpandingStyleLevel);
|
|
Dec(FIdent, 3);
|
|
MyWriteLn('FIN Expandiendo estilo '+NumEstilo(n),
|
|
' FNoText='+BoolToStr(FnoText));
|
|
end;
|
|
rtfParDef:
|
|
begin
|
|
StyleModified;
|
|
ClearCurStyle;
|
|
MyWriteLn('NOTED rtfParDef');
|
|
end;
|
|
rtfQuadCenter:
|
|
begin
|
|
StyleModified;
|
|
FCurStyle.Centered := True;
|
|
MyWriteLn('NOTED rtfQuadCenter');
|
|
end;
|
|
rtfQuadLeft : MyWriteLn('rtfQuadLeft');
|
|
rtfQuadRight : MyWriteLn('rtfQuadRight');
|
|
rtfQuadJust : MyWriteLn('rtfQuadJust');
|
|
rtfFirstIndent : MyWriteLn('rtfFirstIndent');
|
|
rtfLeftIndent : MyWriteLn('rtfLeftIndent', ParValue);
|
|
rtfRightIndent : MyWriteLn('rtfRightIndent', ParValue);
|
|
rtfSpaceBefore : MyWriteLn('rtfSpaceBefore', ParValue);
|
|
rtfSpaceAfter : MyWriteLn('rtfSpaceAfter', ParValue);
|
|
rtfSpaceBetween : MyWriteLn('rtfSpaceBetween', ParValue);
|
|
rtfKeepNext : MyWriteLn('rtfKeepNext');
|
|
else
|
|
MyWriteLn('rtfParAttr, ??? rtfMinor=',FParser.rtfMinor);
|
|
end;
|
|
end;
|
|
|
|
procedure TRTFView.doDocAttribute;
|
|
begin
|
|
case FParser.RTFMinor of
|
|
rtfPaperWidth : MyWriteLn('rtfPaperWidth', ParValue);
|
|
rtfPaperHeight : MyWriteLn('rtfPaperHeight', ParValue);
|
|
rtfLeftMargin : MyWriteLn('rtfLeftMargin', ParValue);
|
|
rtfRightMargin : MyWriteLn('rtfRightMargin', ParValue);
|
|
rtfTopMargin : MyWriteLn('rtfTopMargin', ParValue);
|
|
rtfBottomMargin : MyWriteLn('rtfBottomMargin', ParValue);
|
|
rtfFacingPage : MyWriteLn('rtfFacingPage');
|
|
rtfGutterWid : MyWriteLn('rtfGutterWid');
|
|
rtfDefTab : MyWriteLn('rtfDefTab');
|
|
rtfWidowCtrl : MyWriteLn('rtfWidowCtrl');
|
|
rtfHyphHotZone : MyWriteLn('rtfHyphHotZone');
|
|
rtfFNoteEndSect : MyWriteLn('rtfFNoteEndSect');
|
|
rtfFNoteEndDoc : MyWriteLn('rtfFNoteEndDoc');
|
|
rtfFNoteText : MyWriteLn('rtfFNoteText');
|
|
rtfFNoteBottom : MyWriteLn('rtfFNoteBottom');
|
|
rtfFNoteStart : MyWriteLn('rtfFNoteStart');
|
|
rtfFNoteRestart : MyWriteLn('rtfFNoteRestart');
|
|
rtfPageStart : MyWriteLn('rtfPageStart');
|
|
rtfLineStart : MyWriteLn('rtfLineStart');
|
|
rtfLandscape : MyWriteLn('rtfLandscape');
|
|
rtfFracWidth : MyWriteLn('rtfFracWidth');
|
|
rtfNextFile : MyWriteLn('rtfNextFile');
|
|
rtfTemplate : MyWriteLn('rtfTemplate');
|
|
rtfMakeBackup : MyWriteLn('rtfMakeBackup');
|
|
rtfRTFDefault : MyWriteLn('rtfRTFDefault');
|
|
rtfRevisions : MyWriteLn('rtfRevisions');
|
|
rtfMirrorMargin : MyWriteLn('rtfMirrorMargin');
|
|
rtfRevDisplay : MyWriteLn('rtfRevDisplay');
|
|
rtfRevBar : MyWriteLn('rtfRevBar');
|
|
else
|
|
MyWriteLn('rtfDocAttr, ??? rtfMinor=',FParser.rtfMinor);
|
|
end;
|
|
end;
|
|
|
|
procedure TRTFView.doSectAttribute;
|
|
begin
|
|
case FParser.RTFMinor of
|
|
rtfSectDef : MyWriteLn('rtfSectDef');
|
|
rtfNoBreak : MyWriteLn('rtfNoBreak');
|
|
rtfColBreak : MyWriteLn('rtfColBreak');
|
|
rtfPageBreak : MyWriteLn('rtfPageBreak');
|
|
rtfEvenBreak : MyWriteLn('rtfEvenBreak');
|
|
rtfOddBreak : MyWriteLn('rtfOddBreak');
|
|
rtfPageStarts : MyWriteLn('rtfPageStarts');
|
|
rtfPageCont : MyWriteLn('rtfPageCont');
|
|
rtfPageRestart : MyWriteLn('rtfPageRestart');
|
|
rtfPageDecimal : MyWriteLn('rtfPageDecimal');
|
|
rtfPageURoman : MyWriteLn('rtfPageURoman');
|
|
rtfPageLRoman : MyWriteLn('rtfPageLRoman');
|
|
rtfPageULetter : MyWriteLn('rtfPageULetter');
|
|
rtfPageLLetter : MyWriteLn('rtfPageLLetter');
|
|
rtfPageNumLeft : MyWriteLn('rtfPageNumLeft');
|
|
rtfPageNumTop : MyWriteLn('rtfPageNumTop');
|
|
rtfHeaderY : MyWriteLn('rtfHeaderY');
|
|
rtfFooterY : MyWriteLn('rtfFooterY');
|
|
rtfLineModulus : MyWriteLn('rtfLineModulus');
|
|
rtfLineDist : MyWriteLn('rtfLineDist');
|
|
rtfLineStarts : MyWriteLn('rtfLineStarts');
|
|
rtfLineRestart : MyWriteLn('rtfLineRestart');
|
|
rtfLineRestartPg : MyWriteLn('rtfLineRestartPg');
|
|
rtfLineCont : MyWriteLn('rtfLineCont');
|
|
rtfTopVAlign : MyWriteLn('rtfTopVAlign');
|
|
rtfBottomVAlign : MyWriteLn('rtfBottomVAlign');
|
|
rtfCenterVAlign : MyWriteLn('rtfCenterVAlign');
|
|
rtfJustVAlign : MyWriteLn('rtfJustVAlign');
|
|
rtfColumns : MyWriteLn('rtfColumns');
|
|
rtfColumnSpace : MyWriteLn('rtfColumnSpace');
|
|
rtfColumnLine : MyWriteLn('rtfColumnLine');
|
|
rtfENoteHere : MyWriteLn('rtfENoteHere');
|
|
rtfTitleSpecial : MyWriteLn('rtfTitleSpecial');
|
|
else
|
|
MyWriteLn('rtfSectAttr, ??? rtfMinor=',FParser.rtfMinor);
|
|
end;
|
|
end;
|
|
|
|
procedure TRTFView.doctrl;
|
|
begin
|
|
case Fparser.rtfmajor of
|
|
rtfdestination : dodestination;
|
|
rtfspecialchar : dospecialchar;
|
|
rtfcharattr : doCharAttribute;
|
|
rtfparattr : doParAttributes;
|
|
rtfPosAttr:
|
|
begin
|
|
case Fparser.rtfMinor of
|
|
rtfPosXCenter: MyWriteLn('rtfPosXCenter');
|
|
else
|
|
MyWriteLn('rtfPosAttr, ??? rtfMinor=',FParser.rtfMinor);
|
|
end;
|
|
end;
|
|
rtfVersion:
|
|
MyWriteLn('rtfversion ', ParValue);
|
|
rtfDefFont:
|
|
begin
|
|
FCurStyle.FontDef := Fparser.rtfParam;
|
|
MyWriteLn('NOTED rtfdeffont', ParValue);
|
|
end;
|
|
rtfCharSet:
|
|
begin
|
|
case FParser.rtfMinor of
|
|
rtfMacCharSet: MyWriteLn('rtfcharset Mac');
|
|
rtfAnsiCharSet: MyWriteLn('rtfcharset Ansi');
|
|
rtfPcCharSet: MyWriteLn('rtfcharset PC');
|
|
rtfPcaCharSet: MyWriteLn('rtfcharset PCA');
|
|
else
|
|
MyWriteLn('rtfcharset Desconocido');
|
|
end;
|
|
end;
|
|
rtfStyleAttr:
|
|
case FParser.rtfMinor of
|
|
rtfBasedOn: MyWriteLn('rtfStyleAttr Basado en ', ParValue);
|
|
rtfNext: MyWriteLn('rtfStyleAttr Siguiente ', ParValue);
|
|
end;
|
|
|
|
rtfDocAttr: doDocAttribute;
|
|
rtfSectAttr: doSectAttribute;
|
|
|
|
else
|
|
MyWriteLn('doCtrl, ??? rtfMajor=',FParser.rtfMajor);
|
|
end;
|
|
end;
|
|
|
|
procedure TRTFView.doGroup;
|
|
var
|
|
rv: integer;
|
|
s: string;
|
|
begin
|
|
case FParser.RTFMajor of
|
|
rtfBeginGroup:
|
|
begin
|
|
if FGroupText and (FCurText<>'') then begin
|
|
MyWriteLn('*** DOGROUP__BeginGroup', SomeText(' WillWrite=',FCurText));
|
|
EmitirInterParrafo;
|
|
end;
|
|
MyWriteLn('INI GROUP FNoText='+BoolToStr(FNoText));
|
|
Inc(FGroupLevel);
|
|
Inc(FIdent,3);
|
|
PushStyle;
|
|
FGroupText:=False;
|
|
end;
|
|
rtfEndGroup:
|
|
begin
|
|
//
|
|
if FGroupText and (FCurText<>'') then begin
|
|
// emitir el texto del grupo actual
|
|
MyWriteLn('*** DOGROUP__EndGroup'{ FCurText="',FCurText+'"'});
|
|
EmitirInterParrafo;
|
|
end;
|
|
PopStyle;
|
|
Dec(FIdent,3);
|
|
Dec(FGroupLevel);
|
|
MyWriteLn('FIN GROUP FNoText='+BoolToStr(FNoText));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TRTFView.Dowrite;
|
|
var
|
|
c: Char;
|
|
n: Integer;
|
|
begin
|
|
c := chr(FParser.RTFMajor);
|
|
|
|
if FNoText then begin
|
|
MyWriteLn('DoWrite: Skipping '+c);
|
|
exit;
|
|
end;
|
|
|
|
// checar si el estilo ha cambiado en medio de
|
|
// un parrafo
|
|
if FCurStyle.StyleChanged and (FCurText<>'') then
|
|
EmitirInterParrafo;
|
|
|
|
FCurText := FCurText + c;
|
|
FGroupText := True;
|
|
{$IFDEF DumpText}
|
|
Write(c);
|
|
{$ENDIF}
|
|
|
|
|
|
// check for changes in style
|
|
FCurStyle.StyleChanged := False;
|
|
end;
|
|
|
|
function TRTFView.GetCheckPoints: TStringlist;
|
|
begin
|
|
result := CheckPoints;
|
|
end;
|
|
|
|
procedure TRTFView.handleerror(s: shortstring);
|
|
begin
|
|
MyWriteLn ('ERROR: ', s);
|
|
end;
|
|
|
|
function TRTFView.ParValue: string;
|
|
begin
|
|
if FParser.rtfParam=rtfNoParam then
|
|
result := ' <NoParam>'
|
|
else
|
|
result := ' Value='+IntToStr(Fparser.rtfParam);
|
|
end;
|
|
|
|
{$IFDEF Debug}
|
|
procedure TRTFView.DumpFonts;
|
|
var
|
|
F: PRtfFont;
|
|
i,k: Integer;
|
|
begin
|
|
WriteLn('FontDump ------');
|
|
k:=0;
|
|
for i:=0 to 100 do begin
|
|
F := FParser.Fonts[i];
|
|
if F=nil then
|
|
continue;
|
|
inc(k);
|
|
WriteLn(' ',i,' Num=', F^.rtfFNum,' Name=', F^.rtfFName,
|
|
' Family=', F^.rtfFFamily);
|
|
end;
|
|
if k=0 then
|
|
WriteLn(' -- NO FONTS FOUND --');
|
|
end;
|
|
|
|
procedure TRTFView.DumpColors;
|
|
var
|
|
C: PRTFColor;
|
|
i,k: Integer;
|
|
begin
|
|
WriteLn('ColorDump -----');
|
|
k:=0;
|
|
for i:=0 to 100 do begin
|
|
C := FParser.Colors[i];
|
|
if C =nil then
|
|
continue;
|
|
inc(k);
|
|
WriteLn(' ',i:2,' Num=',C^.rtfCNum:2,' R=',C^.rtfCRed:3,
|
|
' G=',C^.rtfCGreen:3,' B=',C^.rtfCBlue:3);
|
|
end;
|
|
if k=0 then
|
|
WriteLn(' -- NO COLORS FOUND --');
|
|
|
|
end;
|
|
|
|
procedure TRTFView.DumpStyles;
|
|
var
|
|
S: PRTFSTyle;
|
|
i,k: Integer;
|
|
begin
|
|
WriteLn('StylesDump -----');
|
|
k:=0;
|
|
for i:=0 to 100 do begin
|
|
S := FParser.Styles[i];
|
|
if S=nil then
|
|
continue;
|
|
inc(k);
|
|
WriteLn(' ',i,' Num=',S^.rtfSNum,' Name=',S^.rtfSName,' BasedOn=',
|
|
NumEstilo(S^.rtfSBasedOn));
|
|
end;
|
|
if k=0 then
|
|
WriteLn(' -- NO STYLES FOUND --');
|
|
end;
|
|
{$ENDIF}
|
|
|
|
function TRTFView.FindStyle: Integer;
|
|
function TxFont(const Fname: String): string;
|
|
var
|
|
I, IndxOrg,IndxDest: Integer;
|
|
const
|
|
FontEqArray:array[1..3,1..2] of string =
|
|
(
|
|
('Arial', 'nimbus sans l'),//'Suse Sans'),//'Helvetica'),
|
|
('Times New Roman', 'Times'),
|
|
('Courier New', 'Courier [Adobe]')
|
|
);
|
|
begin
|
|
{$IFDEF MSWINDOWS}
|
|
IndxOrg:=2;
|
|
IndxDest:=1;
|
|
{$ELSE}
|
|
IndxOrg:=1;
|
|
IndxDest:=2;
|
|
{$ENDIF}
|
|
|
|
for i:=low(FontEqArray) to High(FontEqArray) do
|
|
if CompareText(FName, FontEqArray[i, IndxOrg])=0 then begin
|
|
result := FontEqArray[i, IndxDest];
|
|
exit;
|
|
end;
|
|
|
|
result := FName;
|
|
end;
|
|
var
|
|
C: PRtfColor;
|
|
F: PRtfFont;
|
|
Clr: TColor;
|
|
N: String;
|
|
i: Integer;
|
|
begin
|
|
// usando los valores actuales buscar un estilo
|
|
// que tenga estos mismos datos
|
|
{$IFDEF DumpRTF}
|
|
MyWriteLn('======BUSCANDO ESTILO=======-');
|
|
{$ENDIF}
|
|
|
|
Clr := FDefaultForeColor;
|
|
if FCurStyle.ForeColor=-1 then
|
|
MyWriteLn('------ Color no ajustado, usando DefaultForeColor')
|
|
else begin
|
|
C := FParser.Colors[FCurStyle.ForeColor];
|
|
if C<>nil then begin
|
|
Clr := RtfColorToColor(C, Clr);
|
|
MyWriteLn('------ Color ['+IntToStr(FCurStyle.ForeColor)+']=',
|
|
ColorToString(Clr));
|
|
end else
|
|
MyWriteLn('------ Color ['+IntToStr(FCurStyle.ForeColor)+']',
|
|
' NO HAYADO usando Default');
|
|
end;
|
|
|
|
F := Fparser.Fonts[FCurStyle.Font];
|
|
if F<>nil then
|
|
N := F^.rtfFName
|
|
else
|
|
N := 'Times New Roman';
|
|
|
|
N := TxFont(N);
|
|
|
|
with Style do
|
|
for i:=0 to TextStyles.Count-1 do begin
|
|
if (FCurStyle.FontSize = TextStyles[i].Size) and
|
|
(Clr = TextStyles[i].Color) and
|
|
(FCurStyle.FontStyles= TextStyles[i].Style) and
|
|
(CompareText(N,TextStyles[i].FontName)=0)
|
|
then begin
|
|
{$IFDEF DumpRTF}
|
|
MyWriteLn('------ESTILO HALLADO ------');
|
|
MyWriteLn('------ Indx =', i);
|
|
{$ENDIF}
|
|
Result := i;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
// aun no existe, darlo de alta
|
|
result := Style.AddTextStyle;
|
|
with Style.TextStyles[result] do begin
|
|
Size := FCurStyle.FontSize;
|
|
Style := FCurStyle.FontStyles;
|
|
FontName := N;
|
|
Color := Clr;
|
|
{$IFDEF DumpRTF}
|
|
MyWriteLn('------CREANDO ESTILO------');
|
|
MyWriteLn('------ Indx = ', result);
|
|
MyWriteLn('------ Size = ', Size);
|
|
MyWriteLn('------ Name = ', FontName);
|
|
MyWriteLn('------ Color = ', ColorToString(Clr));
|
|
MyWriteLn('------ Bold = ', BoolToStr(fsBold in Style));
|
|
MyWriteLn('------ Italic = ', BoolToStr(fsItalic in Style));
|
|
MyWriteLn('------ Under = ', BoolToStr(fsUnderLine in Style));
|
|
MyWriteLn('------ Strike = ', BoolToStr(fsStrikeOut in Style));
|
|
{$ENDIF}
|
|
//Color := clBlack;
|
|
end;
|
|
end;
|
|
|
|
procedure TRTFView.StyleModified;
|
|
begin
|
|
if FCurText<>'' then
|
|
EmitirInterParrafo;
|
|
FCurStyle.StyleChanged:=True;
|
|
end;
|
|
|
|
procedure TRTFView.EmitirInterParrafo;
|
|
var
|
|
N: Integer;
|
|
begin
|
|
if FNoText then begin
|
|
MyWriteLn(' Saltandose el texto');
|
|
exit;
|
|
end;
|
|
MyWriteLn('*** Emitiendo InterParrafo');
|
|
N:=FindStyle;
|
|
if FCurStyle.LastStyle<>N then
|
|
FCurStyle.LastStyle := N;
|
|
|
|
if FCurStyle.Centered then begin
|
|
if FPendingLine then begin
|
|
MergePreviousLine(FCurText,True, N);
|
|
FPendingLine:=False;
|
|
end else
|
|
AddCenterLine(FCurText, N)
|
|
end else begin
|
|
if FParrafoParcial then
|
|
if FPendingLine then begin
|
|
MergePreviousLine(FCurText, False, N);
|
|
FPendingLine:=False;
|
|
end else
|
|
Add(FCurText, N)
|
|
else begin
|
|
if FPendingLine then begin
|
|
MergePreviousLine(FCurText, False, N);
|
|
FPendingLine:=False;
|
|
end else
|
|
AddFromNewLine(FCurText, N);
|
|
end;
|
|
end;
|
|
|
|
FParrafoParcial:=True;
|
|
FCurText := '';
|
|
end;
|
|
|
|
procedure TRTFView.PopStyle;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i := Length(FStack)-1;
|
|
{$IFDEF DEBUG}
|
|
DebugSt(FStack[i],'PopStyle');
|
|
{$ENDIF}
|
|
FGroupText := FStack[i].GrpText;
|
|
FNoText := FStack[i].NoText;
|
|
FCurStyle.BackColor := FStack[i].BackColor;
|
|
FCurStyle.Centered := FStack[i].Centered;
|
|
FCurStyle.ForeColor := FStack[i].ForeColor;
|
|
FCurStyle.Font := FStack[i].Font;
|
|
FCurStyle.FontSize := FStack[i].FontSize;
|
|
FCurStyle.FontStyles := FStack[i].FontStyles;
|
|
FCurStyle.StyleChanged := FStack[i].StyleChanged;
|
|
FCurStyle.LastStyle := FStack[i].LastStyle;
|
|
SetLength(FStack, i);
|
|
end;
|
|
|
|
procedure TRTFView.PushStyle;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
i := Length(FStack);
|
|
SetLength(FStack, i+1);
|
|
FStack[i].BackColor := FCurStyle.BackColor;
|
|
FStack[i].Centered := FCurStyle.Centered;
|
|
FStack[i].ForeColor := FCurStyle.ForeColor;
|
|
FStack[i].Font := FCurStyle.Font;
|
|
FStack[i].FontSize := FCurStyle.FontSize;
|
|
FStack[i].FontStyles := FCurStyle.FontStyles;
|
|
FStack[i].StyleChanged := FCurStyle.StyleChanged;
|
|
FStack[i].LastStyle := FCurStyle.LastStyle;
|
|
FStack[i].NoText := FNoText;
|
|
FStack[i].GrpText := FGroupText;
|
|
{$IFDEF DEBUG}
|
|
DebugSt(FStack[i],'PushStyle');
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TRTFView.MergePreviousLine(txt: string; center: boolean; Rv: Integer
|
|
);
|
|
var
|
|
i: Integer;
|
|
Li: TLineInfo;
|
|
begin
|
|
i := LineCount-1;
|
|
Li := TLineInfo(lines.Objects[i]);
|
|
MyWriteLn('******** Pending Line "', Lines[i]+'"');
|
|
MyWriteLn('******** New Line "', txt+'"');
|
|
Li.Center := Center;
|
|
Li.StyleNo := Rv;
|
|
Lines[i] := Txt;
|
|
end;
|
|
|
|
function TRTFView.GetCredits: string;
|
|
begin
|
|
result := 'TRTFView based on '+ inherited GetCredits;
|
|
end;
|
|
|
|
constructor TRTFView.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
Style := TRVStyle.Create(nil);
|
|
FDefaultForeColor:=clBlack;
|
|
FDefaultBackColor:=clWindow;
|
|
end;
|
|
|
|
destructor TRTFView.Destroy;
|
|
begin
|
|
Style.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TRTFView.LoadFromFile(aRTFFile: string);
|
|
var
|
|
Stream : TFilestream;
|
|
begin
|
|
FCurText := '';
|
|
Style.TextStyles.Clear;
|
|
Clear;
|
|
Stream:=TFileStream.Create(aRTFFile,fmopenread);
|
|
FParser:=TRTFParser.Create(Stream);
|
|
{$ifdef debug}
|
|
AssignFile(FLog, 'rtf.txt');
|
|
Rewrite(FLog);
|
|
WriteLn(FLog, 'procesando: ', aRTFFile);
|
|
{$endif}
|
|
FLogIdent:=0;
|
|
FWaitingFirstControlWord:=False;
|
|
try
|
|
FParser.classcallbacks[rtfText]:=@DoWrite;
|
|
FParser.classcallbacks[rtfcontrol]:=@DoCtrl;
|
|
FParser.classcallbacks[rtfGroup]:=@DoGroup;
|
|
FParser.onRTFError:=@HandleError;
|
|
FParser.SetReadHook(@ReadHandler);
|
|
FParser.StartReading;
|
|
{$IFDEF DEBUG}
|
|
DumpFonts;
|
|
DumpColors;
|
|
DumpStyles;
|
|
{$ENDIF}
|
|
finally
|
|
{$IFDEF DEBUG}
|
|
CloseFile(FLog);
|
|
{$ENDIF}
|
|
Fparser.Free;
|
|
Stream.free;
|
|
Format;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
initialization
|
|
|
|
{$I rtfview.lrs}
|
|
|
|
end.
|