home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 March / pcp161b.iso / handson / archive / Issue158 / delphi / LinesShowing / linesunit.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-13  |  5.8 KB  |  205 lines

  1. unit linesunit;
  2.  
  3. {  Demo application to illustrate the use of the LinesShowing() function.
  4.  
  5.    Calculate the indexes of 1st and last lines visible in RichEdit
  6.    then format only those lines.
  7.  
  8.    Maybe an interesting example, but far from ideal as a real-world
  9.    syntax-colouring editor!
  10.    
  11. }
  12. interface
  13.  
  14. uses
  15.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  16.   StdCtrls, ComCtrls, ExtCtrls, richeditutils, strutils;
  17.  
  18. type
  19.   TForm1 = class(TForm)
  20.     RichEdit1: TRichEdit;
  21.     Panel1: TPanel;
  22.     LinesShowingBtn: TButton;
  23.     RecolBtn: TButton;
  24.     LineIndexesBtn: TButton;
  25.     procedure LinesShowingBtnClick(Sender: TObject);
  26.     procedure FormCreate(Sender: TObject);
  27.     procedure FormResize(Sender: TObject);
  28.     procedure RecolBtnClick(Sender: TObject);
  29.     procedure LineIndexesBtnClick(Sender: TObject);
  30.   private
  31.     { Private declarations }
  32.   public
  33.     { Public declarations }
  34.     function GetCharFromPos( x, y : integer ) : LongInt;
  35.     function GetLineNumAt(x , y : integer) : LongInt;
  36.     procedure FormatLineAt( Red: TRichEdit; num : LongInt );
  37.     procedure SetDefAttributes;
  38.     procedure SetNormalAttributes;
  39.     procedure SetKeyWordAttributes;
  40.     function KeyWord( token : string ) : boolean;
  41.     procedure RecolourScreen;
  42.   end;
  43.  
  44.  
  45. var
  46.   Form1: TForm1;
  47. const
  48.   APPNAME = 'Working with Visible Lines Test Application';
  49.  
  50.   NUMKEYWORDS = 27;
  51.   Keywords : array[0..NUMKEYWORDS] of string =
  52.               ('unit','begin','end','procedure','function',
  53.               'if','while','do','then','else','repeat','until',
  54.               'const','var','type','uses','interface','implementation',
  55.               'string','of','array','program', 'private', 'public',
  56.               'published', 'and', 'with', 'or');
  57.  
  58. implementation
  59.  
  60. {$R *.DFM}
  61.  
  62.  
  63. procedure TForm1.SetDefAttributes;
  64. begin
  65.   RichEdit1.DefAttributes.Style := [];
  66.   RichEdit1.DefAttributes.Color := clWindowText;
  67. end;
  68.  
  69. procedure TForm1.setNormalAttributes;
  70. begin
  71.  // default text attributes
  72.   RichEdit1.SelAttributes.Style := [];
  73.   RichEdit1.selAttributes.Color := clWindowText;
  74. end;
  75.  
  76. procedure TForm1.setKeyWordAttributes;
  77. begin
  78.  // text attributes for a keyword
  79.   RichEdit1.SelAttributes.Style := [fsBold];
  80.   RichEdit1.selAttributes.Color := clBlue;
  81. end;
  82.  
  83. function TForm1.KeyWord( token : string ) : boolean;
  84. var
  85.    isKW : boolean;
  86.    i    : integer;
  87. begin
  88.    isKW := false;
  89.    i := 0;
  90.    while ((i <= NUMKEYWORDS) and (isKW = false )) do
  91.    begin
  92.    //!! Test is case-insensitive (OK for Pascal. Change this for C or Java)
  93.       if lowercase(token) = KeyWords[i] then
  94.          isKW := true
  95.       else
  96.          Inc(i);
  97.    end;
  98.    result := isKW;
  99. end;
  100.  
  101.  
  102. procedure TForm1.LinesShowingBtnClick(Sender: TObject);
  103. // calculate the number of lines showing in the Richedit control
  104. begin
  105.   Caption := 'Lines Showing (0-based index) = ' + IntToStr(LinesShowing( RichEdit1 ));
  106. end;
  107.  
  108. procedure TForm1.FormCreate(Sender: TObject);
  109. var
  110.    i : integer;
  111. begin
  112.    for i := 1 to 100 do
  113.        RichEdit1.Lines.Add(Format('[%d] This is Line %d. keywords=array, unit, begin end.', [i, i]));
  114.    RichEdit1.SelStart := 0;
  115.    Caption := APPNAME;
  116. end;
  117.  
  118. procedure TForm1.FormResize(Sender: TObject);
  119. begin
  120.   RichEdit1.Refresh; { a 'feature' in RichEdit can fail to refresh the
  121.                         display after the form has been resized. This
  122.                         forces an update }
  123. end;
  124.  
  125. // --- Note: Maybe We could add the next two functions to richeditutils.pas?
  126. function TForm1.GetCharFromPos( x, y : integer ) : LongInt;
  127. { return char index from x, y coordinates }
  128. var
  129.    P : TPoint;
  130. begin
  131.    P := Point(x,y);
  132.    result := SendMessage(RichEdit1.Handle, EM_CHARFROMPOS, 0, longint(@P){MAKELPARAM(1, 1)} );
  133. end;
  134.  
  135. function TForm1.GetLineNumAt(x , y : integer) : LongInt;
  136. { return line number containing point at specified coordinates }
  137. begin
  138.    result := GetLineNum(RichEdit1, GetCharFromPos(x,y));
  139. end;
  140.  
  141. procedure TForm1.FormatLineAt( Red: TRichEdit; num : LongInt ); // num is RichEdit1.Lines[num]
  142. var
  143.    ti : tokenindexes;
  144.    i, numfound : integer;
  145.    StartIndex : LongInt;
  146.    s : string;
  147. begin
  148.   s := red.Lines[num];
  149.   TokensFoundAt( s, numfound, ti );
  150.   StartIndex := GetLineSelStartIndex( Red, num );
  151.   for i := 1 to numfound do
  152.   begin
  153.      Red.SelStart := StartIndex + ti[i].tstart;
  154.      Red.SelLength := ti[i].tend;
  155.     if KeyWord( Red.SelText ) then
  156.         SetKeyWordAttributes
  157.      else
  158.         SetNormalAttributes;
  159.    end;
  160. end;
  161.  
  162. procedure TForm1.RecolourScreen;
  163. var
  164.    i, startSelPos, FirstVisLine, LastVisLine : LongInt;
  165. begin
  166.   Richedit1.Lines.BeginUpdate;    // hide caret, selection etc.
  167.   HideSelection(RichEdit1);
  168.   HideCaret(RichEdit1.Handle);
  169.   startSelPos := RichEdit1.selStart;
  170.   RichEdit1.WordWrap := false;
  171.   FirstVisLine := GetLineNumAt(0,0);
  172.   LastVisLine := FirstVisLine + LinesShowing(RichEdit1);
  173.   Richedit1.Lines.EndUpdate;
  174.  
  175.   RichEdit1.Lines.BeginUpdate;
  176.   for i := FirstVisLine to LastVisLine do     // then colour visible lines
  177.       FormatLineAt(RichEdit1, i);
  178.  
  179.   RichEdit1.selStart := startSelPos;
  180.   ShowCaret(RichEdit1.Handle);
  181.   ShowSelection(RichEdit1);
  182.   RichEdit1.selStart := startSelPos;
  183.   RichEdit1.Lines.EndUpdate;
  184.   RichEdit1.setFocus;
  185. end;
  186.  
  187. procedure TForm1.RecolBtnClick(Sender: TObject);
  188. begin
  189.    RecolourScreen;
  190. end;
  191.  
  192. procedure TForm1.LineIndexesBtnClick(Sender: TObject);
  193. // display indexes of visible lines. First line is at position 1.
  194. // last line is the index of the last line that's even partially visible
  195. var
  196.    FirstVisLine, LastVisLine : longint;
  197. begin
  198.   FirstVisLine := GetLineNumAt(0,0) +1;  // +1 to match Lines 1-based indexing
  199.   LastVisLine := FirstVisLine + LinesShowing(RichEdit1);
  200.   ShowMessage( Format( 'First visible line is %d, last visible line is %d.',
  201.                        [FirstVisLine, LastVisLine] ));
  202. end;
  203.  
  204. end.
  205.