ASH - Automatic Syntax highlight (Attempt 2)
[Please note: I have my Delphi Editor colors set-to the [Ocean] colour speed settings for testing purposes. This setting works well on the default RichEdit white background, and most TokenTypes are in different colors from each other]
Okay now to do some real work. Most of the function have been written thereabouts. As a basis for writing this ASH Im going to use Project1.dpr which comes out of mpas2rtf.zip in the YourPasEdit zip file yrpasedit.zip. This is because it much smaller than YourPasEdit, and thus quicker to compile.
I suggest you put the contents of the mpas2rtf.zip into a separate directory. Also copy mwPas2Rtf.pas to testinput.pas using the Explorer shell - well be using this file as a sample pascal file for benchmarking.
Open Project1.dpr in Delphi, compile Project1, run it, and open the file testinput.pas by pressing [Button 1] and selecting it in the [OpenFile Dialog]. Do it a number of times, and record the time taken for each once the file is stabilised in the system cache. On my system it averages about 0.47 - 0.41 seconds once its in the cache (P133 - 16M - Win95b)
Preparing Project1s Unit1.pas
Now replace the contents of mpas2rtf.pas with that code in jhdpas2rtf.pas. Recompile. Now open up the testinput.pas sample file again by using [Button 1]. As you see - we get color - but it takes a "lot" longer: 1.20-1.25 seconds.
Try and speed it up if you like. You can start by commenting out the pascal-code that codes in the different Font and FontSizes in TPasConversion.SetRtf. Recompile and run again. This time it improves a bit to 1.10-1.15. Now try commenting out the code for different Colors. Wow - the speed decreases down to 0.49 - 0.44.
Hmm. This font and color stuff really packs a punch. We may need to look at this later in more detail if things end up too slow. For the moment well leave the code back in full working condition (so youll need to go back and uncomment the code).
Now put the following base code into the [OnChange] event of the RichEdit1 in Unit1.pas of Project1. Most of this code is just based on what we have already covered elsewhere.
var
WasSelStart,WasRow,Row,BeginSelStart,EndSelStart: Integer;
MyRe: TRichEdit;
MyPBuff: array[0..255] of char;
begin
MyRe := TRichEdit(Sender);
WasSelStart := MyRE.SelStart;
WasRow := MyRE.Perform(EM_LINEFROMCHAR, MyRE.SelStart, 0);
BeginSelStart := MyRe.Perform(EM_LINEINDEX, Row, 0);
EndSelStart := BeginSelStart + Length(MyRE.Lines.Strings[Row]);
Row := WasRow;
end;
Were going to use the GetToken() function to do all the hard work. Well need some extra variables to pass to the GetToken function, so add to the var section:
MyTokenStr:string;
MyTokenState:TTokenState;
MyRun:PChar;
MySelStart: Integer;
These are similar to the variables we used in the ConvertReadStream - in fact we want to do "exactly" the same thing, just one single line at a time. Add this code before the last end;
StrPCopy(MyPBuff,MyRE.Lines.Strings[Row]);
MYPBuff[Length(MyRE.Lines.Strings[Row])] := #0;
MySelStart := BeginSelStart;
MyRun := MyPBuff;while(MyRun^ <> #0) do
beginMyRun := PasCon.GetToken(MyRun,MyTokenState,MyTokenStr);
//
// ScanForRtf;
// SetRtf;
// WriteBuffer(Prefix + TokenStr + Postfix);
//end;
end;
NB: As we will be using PasCon youll have to move it from being a local variable of TForm1.Button1Click to be a global variable. This will mean youll have to move all the initialising:
PasCon:=TPasConversion.Create;
PasCon.UseDelphiHighlighting(3);
to a TForm1.Show, and the PasCon.Free to TForm1.Close procedure. It will still work if you only move the variable definition - but not for long... :-)
Ive left the code from the old ConvertReadStream in the example above to show what we "logically" still need to implement in the current context - that is manipulating the RichEdit Control directly. What we have now is the ability to cut up the current line in to different tokens, and know what type they are. We now have to add these tokens to current line with the right attributes (Fonts,Colors,Bold etc).
But wait. They are already on the line - well the text is anyway, but maybe not in the correct format (Color,Bold etc). So what actually could do is to select each token in its corresponding positon in the RichEdit control and just apply the appropriate attributes to them.
We did this back in the beginning remeber? When we set the >10 character lines to the color red. But how do we do this now? Lets look at what we have in the variables at hand when we hit "// SetRtf" the first time:
(these example uses Uni1.pas as the input file as its more interesting)
VARIABLES
01234567901234567890 Lines.Strings[R0] unit Unit1;