lazarus-ccr/components/rtfview/rtfview.pas
2007-02-21 18:10:07 +00:00

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.