123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- {
- "SHEdit" - Text editor with syntax highlighting
- Copyright (C) 1999-2000 by Sebastian Guenther ([email protected])
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- 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.
- }
- // Syntax highlighting class for Pascal sources
- // !!! Slightly modified version for fpDoc !!!
- {$MODE objfpc}
- {$H+}
- {$IFDEF Debug}
- {$ASSERTIONS On}
- {$ENDIF}
- unit sh_pas;
- interface
- const
- LF_SH_Valid = $01;
- LF_SH_Multiline1 = $02;
- LF_SH_Multiline2 = $04;
- LF_SH_Multiline3 = $08;
- LF_SH_Multiline4 = $10;
- LF_SH_Multiline5 = $20;
- LF_SH_Multiline6 = $40;
- LF_SH_Multiline7 = $80;
- LF_Escape = #10;
- shDefault = 1;
- shInvalid = 2;
- shSymbol = 3;
- shKeyword = 4;
- shComment = 5;
- shDirective = 6;
- shNumbers = 7;
- shCharacters = 8;
- shStrings = 9;
- shAssembler = 10;
- procedure DoPascalHighlighting(var flags: Byte; source, dest: PChar);
- implementation
- uses Strings;
- const
- LF_SH_Comment1 = LF_SH_Multiline1; { Normal braced Comments}
- LF_SH_Comment2 = LF_SH_Multiline2; { (* *) Comments}
- LF_SH_Asm = LF_SH_Multiline3;
- MaxKeywordLength = 15;
- MaxKeyword = 60;
- KeywordTable: array[0..MaxKeyword] of PChar =
- ('AND', 'ARRAY', 'ASM', 'ASSEMBLER',
- 'BEGIN', 'BREAK',
- 'CASE', 'CONST', 'CONSTRUCTOR', 'CLASS',
- 'DEFAULT', 'DESTRUCTOR', 'DIV', 'DO', 'DOWNTO',
- 'ELSE', 'END', 'EXCEPT', 'EXIT',
- 'FINALIZATION', 'FINALLY', 'FOR', 'FUNCTION',
- 'GOTO',
- 'IF', 'IMPLEMENTATION', 'IN', 'INHERITED', 'INITIALIZATION', 'INTERFACE',
- 'NIL', 'NOT',
- 'OBJECT', 'OF', 'ON', 'OR', 'OVERRIDE',
- 'PACKED', 'PRIVATE', 'PROCEDURE', 'PROGRAM', 'PROPERTY', 'PROTECTED',
- 'PUBLIC', 'PUBLISHED',
- 'RAISE', 'RECORD', 'REPEAT', 'RESOURCESTRING',
- 'SET',
- 'THEN', 'TRY', 'TYPE',
- 'UNIT', 'UNTIL', 'USES',
- 'VAR', 'VIRTUAL',
- 'WHILE', 'WITH',
- 'XOR');
- KeywordAsmIndex = 2;
- procedure DoPascalHighlighting(var flags: Byte; source, dest: PChar);
- var
- dp: Integer; // Destination position - current offset in dest
- LastSHPos: Integer; // Position of last highlighting character, or 0
- procedure AddSH(sh: Byte);
- begin
- ASSERT(sh > 0);
- if (LastSHPos > 0) and (dp = LastSHPos + 1) then Dec(dp, 2);
- dest[dp] := LF_Escape; Inc(dp);
- LastSHPos := dp;
- dest[dp] := Chr(sh); Inc(dp);
- end;
- procedure PutChar;
- begin
- dest[dp] := source[0]; Inc(dp); Inc(source);
- end;
- procedure ProcessComment1;
- begin
- while source[0] <> #0 do begin
- if source[0] = '}' then begin
- PutChar;
- flags := flags and not LF_SH_Comment1;
- AddSH(shDefault);
- break;
- end;
- PutChar;
- end;
- end;
- procedure ProcessComment2;
- begin
- while source[0] <> #0 do begin
- if (source[0] = '*') and (source[1] = ')') then begin
- PutChar; PutChar;
- flags := flags and not LF_SH_Comment2;
- AddSH(shDefault);
- break;
- end;
- PutChar;
- end;
- end;
- { Checks if we are at the beginning of a comment (or directive) and processes
- all types of comments and directives, or returns False }
- function CheckForComment: Boolean;
- begin
- Result := True;
- if source[0] = '{' then begin
- if source[1] = '$' then
- AddSH(shDirective)
- else
- AddSH(shComment);
- PutChar;
- flags := flags or LF_SH_Comment1;
- ProcessComment1;
- end else if (source[0] = '(') and (source[1] = '*') then begin
- AddSH(shComment);
- PutChar; PutChar;
- flags := flags or LF_SH_Comment2;
- ProcessComment2;
- end else if (source[0] = '/') and (source[1] = '/') then begin
- AddSH(shComment);
- repeat PutChar until source[0] = #0;
- AddSH(shDefault);
- end else
- Result := False;
- end;
- procedure ProcessAsm;
- var
- LastChar: Char;
- begin
- LastChar := ' ';
- while source[0] <> #0 do begin
- if (LastChar in [' ', #9, #10, #13]) and
- (UpCase(source[0]) = 'E') and (UpCase(source[1]) = 'N') and
- (UpCase(source[2]) = 'D') then begin
- AddSH(shKeyword);
- PutChar; PutChar; PutChar;
- flags := flags and not LF_SH_Asm;
- AddSH(shDefault);
- break;
- end else
- if CheckForComment then LastChar := ' '
- else begin
- LastChar := source[0];
- PutChar;
- end;
- end;
- end;
- procedure ProcessSymbol;
- begin
- AddSH(shSymbol);
- if (source[0] = ':') and (source[1] = '=') then
- PutChar;
- PutChar;
- AddSH(shDefault);
- end;
- function CheckForKeyword: Boolean;
- var
- keyword, ukeyword: array[0..MaxKeywordLength] of Char;
- i, j: Integer;
- begin
- i := 0;
- while (source[i] <> #0) and (i < MaxKeywordLength) and
- (source[i] in ['0'..'9', 'A'..'Z', 'a'..'z']) do begin
- keyword[i] := source[i];
- ukeyword[i] := UpCase(source[i]);
- Inc(i);
- end;
- keyword[i] := #0; ukeyword[i] := #0;
- Result := False;
- if i < MaxKeywordLength then
- for j := 0 to MaxKeyword do
- if StrIComp(KeywordTable[j], ukeyword) = 0 then begin
- Result := True; break;
- end;
- if not Result then exit;
- Inc(source, i);
- AddSH(shKeyword);
- StrCopy(dest + dp, keyword);
- Inc(dp, i);
- if j <> KeywordAsmIndex then
- AddSH(shDefault)
- else begin
- AddSH(shAssembler);
- flags := flags or LF_SH_Asm;
- ProcessAsm;
- end;
- end;
- var
- StringLength: Integer;
- begin
- dp := 0;
- LastSHPos := 0;
- if (flags and LF_SH_Comment1) <> 0 then begin
- AddSH(shComment);
- ProcessComment1;
- end;
- if (flags and LF_SH_Comment2) <> 0 then begin
- AddSH(shComment);
- ProcessComment2;
- end;
- if (flags and LF_SH_Asm) <> 0 then begin
- AddSH(shAssembler);
- ProcessAsm;
- end;
- while source[0] <> #0 do begin
- if CheckForComment then continue;
- case source[0] of
- ',', ';', ':', '.', '(', ')', '[', ']', '<', '>', '=',
- '*', '/', '+', '-', '^', '&', '@': ProcessSymbol;
- '#': begin
- AddSH(shCharacters);
- PutChar;
- if source[0] = '$' then PutChar;
- while (source[0] >= '0') and (source[0] <= '9') do PutChar;
- AddSH(shDefault);
- end;
- '$': begin
- AddSH(shNumbers);
- PutChar;
- while source[0] in ['0'..'9', 'A'..'F', 'a'..'f'] do PutChar;
- AddSH(shDefault);
- end;
- '0'..'9': begin
- AddSH(shNumbers);
- PutChar;
- while (source[0] >= '0') and (source[0] <= '9') do PutChar;
- AddSH(shDefault);
- end;
- '''': begin
- AddSH(shStrings);
- PutChar;
- StringLength := 0;
- while source[0] <> #0 do begin
- if source[0] = '''' then
- if source[1] = '''' then PutChar
- else begin
- PutChar; break;
- end;
- Inc(StringLength);
- PutChar;
- end;
- if StringLength = 1 then
- dest[LastSHPos] := Chr(shCharacters);
- if (source[0] = #0) and (dest[dp - 1] <> '''') then
- dest[LastSHPos] := Chr(shInvalid);
- AddSH(shDefault);
- end;
- '_', 'A'..'Z', 'a'..'z': begin
- if not CheckForKeyword then
- repeat
- PutChar
- until not (source[0] in ['0'..'9', '_', 'A'..'Z', 'a'..'z']);
- end;
- ' ': PutChar;
- else begin
- AddSH(shInvalid);
- PutChar; // = found an invalid char!
- AddSH(shDefault);
- end;
- end;
- end;
- dest[dp] := #0;
- end;
- end.
|