A quite fast unit to search/replace strings sequentially (while Seeker.Search() do...) in files/strings done mostly with pointers to improve speed. It's able to search backward, count end of lines, check case-sensitiveness, match whole words and handle wildcards (* and ?),
The search method was divided into 4 specialized methods, again to improve speed. The right method is choosed according to the options that were setted (wildcard, search backward, etc...)
This is an old code that doesn't match my current skills, anyway it has some cool techniques that I really enjoyed :)
The search method was divided into 4 specialized methods, again to improve speed. The right method is choosed according to the options that were setted (wildcard, search backward, etc...)
This is an old code that doesn't match my current skills, anyway it has some cool techniques that I really enjoyed :)
1 2 // 3 // TNotesSeeker - classe de buscas do Notes. 4 // 5 // Notes, http://notes.codigolivre.org.br 6 // Copyright (C) 2003-2004, Equipe do Notes. 7 // 8 // This program is free software; you can redistribute it and/or modify 9 // it under the terms of the GNU General Public License as published by 10 // the Free Software Foundation; either version 2 of the License, or 11 // (at your option) any later version. 12 // 13 // This program is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 // 18 // You should have received a copy of the GNU General Public License 19 // along with this program; if not, write to the Free Software 20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 // 22 // ************************************************************** 23 // Revision #0 24 // Version : 1.0.0 25 // Date : 2003-11-30 22:00:00 GMT -3:00 26 // Reviewer : Jonas Raoni Soares Silva 27 // Changes : Criada a classe. 28 // ************************************************************** 29 // Revision #1 30 // Version : 1.0.1 31 // Date : 2004-09-09 03:30:00 GMT -3:00 32 // Reviewer : Jonas Raoni Soares Silva 33 // Changes : Acho q acabaram-se os bugs... Será??? :] 34 // ************************************************************** 35 36 (* 37 @abstract(NotesSeeker - classe de buscas do Notes.) 38 @author(Jonas Raoni Soares Silva <jonblackjack@bol.com.br>) 39 @created(30 Nov 2003) 40 *) 41 42 unit NotesSeeker; 43 44 interface 45 46 uses 47 SysUtils, Classes; 48 49 type 50 51 { 52 @code(ENotesSeekerException) - 53 Notificar erros na classe TNotesSeeker de forma 54 profissional, facilitando a interceptação e/ou log de 55 erros 56 } 57 ENotesSeekerException = class ( Exception ) 58 public 59 constructor Create(const Msg: string); 60 constructor CreateFmt(const Msg: string; const Args: array of const); 61 end; 62 63 {Opões de pesquisa: <BR> 64 @code(nsHandleEOL) - se você precisar buscar por quebras de linhas, você precisa setar esta opção.<BR> 65 @code(nsCaseSensitive) - diferenciar maiúsculas de minúsculas.<BR> 66 @code(nsWholeWords) - retorna apenas palavras inteiras.<BR> 67 @code(nsBackward) - busca de traz para frente. <BR> 68 @code(nsHandleWildCard) - usa coringas * e ? na pesquisa.} 69 TNotesSeekerOption = ( nsHandleEOL, nsCaseSensitive, nsWholeWords, nsBackward, nsHandleWildCard ); 70 { Set de @link(TNotesSeekerOption).} 71 TNotesSeekerOptions = set of TNotesSeekerOption; 72 73 TSearchFunction = function: Boolean of object; 74 75 { 76 @code(TNotesSeeker) - 77 Permite fazer buscas em strings com várias opções 78 } 79 TNotesSeeker = class(TObject) 80 private 81 Jump, LineJump: Cardinal; 82 FList: TList; 83 protected 84 FMatches, FStartAt, FEOLLen, FSearchLen, FCurCol, 85 FCurLine, FMatchLen, FMatchLine, FMatchCol: Cardinal; 86 87 FBufferEnd, FBuffer, FBufferBegin, FBufferBackup, 88 FEOL, FSearchBegin, FSearch, FSearchEnd: PChar; 89 90 FOptions: TNotesSeekerOptions; 91 92 FContextRightLenght, FContextLeftLenght: Cardinal; 93 94 FKeepText: Boolean; 95 96 function GetText: string; 97 function GetReplacedText: string; 98 function GetContext: string; 99 function GetSearchStr: string; 100 function GetRemainingText: string; 101 function GetCurByte: Cardinal; 102 function GetEOL: string; 103 104 procedure SetOptions(const Value: TNotesSeekerOptions); 105 procedure SetText( const Value: string); 106 procedure SetSearchStr(const Value: string); 107 procedure SetEOL(const Value: string); 108 109 procedure FreeBuffer; 110 procedure FreeEOL; 111 procedure FreeSearchStr; 112 113 {Search Engines} 114 function SearchForward: Boolean; 115 function SearchForwardWithWildCard: Boolean; 116 function SearchBackward: Boolean; 117 function SearchBackwardWithWildCard: Boolean; 118 119 public 120 { Efetua a busca: se o termo procurado for encontrado, retorna true, caso contrário retorna false } 121 Search: TSearchFunction; 122 123 { Método construtor } 124 constructor Create; virtual; 125 { Método destruidor } 126 destructor Destroy; override; 127 128 { Armazena o tamanho do "match", quando a opção wildcard estiver desligada esta será igual ao tamanho da própria string procurada } 129 property MatchLength: Cardinal read FMatchLen; 130 { Quando HandleEOL fizer parte das opções, armazenará a linha onde a string procurada foi encontrada } 131 property CurLine: Cardinal read FMatchLine; 132 { Armazenará a coluna onde a string procurada foi encontrada, se HandleEOL não estiver nas opções, armazenará a mesma coisa que a propriedade CurByte } 133 property CurCol: Cardinal read FMatchCol; 134 { Armazena a posição ou byte "absoluto" onde a string foi encontrada } 135 property CurByte: Cardinal read GetCurByte; 136 { Especifica a posição/byte inicial onde a busca deverá começar } 137 property StartAt: Cardinal read FStartAt write FStartAt; 138 { Retorna o contexto onde a string procurada foi encontrada } 139 property Context: string read GetContext; 140 { Especifica a quantidade de caracteres que deverão fazer parte do contexto encontrado ao lado esquerdo da string procurada } 141 property ContextLeftLenght: Cardinal read FContextLeftLenght write FContextLeftLenght; 142 { Especifica a quantidade de caracteres que deverão fazer parte do contexto encontrado ao lado direito da string procurada } 143 property ContextRightLenght: Cardinal read FContextRightLenght write FContextRightLenght; 144 { Armazena o número de strings que coincidiram com a busca até o presente momento } 145 property Matches: Cardinal read FMatches; 146 { Permite alterar a sequência de caracteres que demarcam o fim de uma linha } 147 property EOL: string read GetEOL write SetEOL; 148 { Armazena as opções atualmente habilitadas para a busca, podendo ser alterada a qualquer momento } 149 property Options: TNotesSeekerOptions read FOptions write SetOptions; 150 { Termo a ser procurado no texto } 151 property SearchStr: string read GetSearchStr write SetSearchStr; 152 { Texto onde a busca será efetuada } 153 property Text: string read GetText write SetText; 154 { Texto restante ao término da busca } 155 property RemainingText: string read GetRemainingText; 156 { Especifica se a classe deverá manter uma cópia do texto setado inicialmente } 157 property KeepText: Boolean read FKeepText write FKeepText; 158 { Retorna o texto com os replaces, caso KeepText seja falso, essa propriedade se torna sinônimo da propriedade Text } 159 property ReplacedText: string read GetReplacedText; 160 161 { Prepara tudo para uma nova busca } 162 procedure StartSearch; 163 { Carrega o texto da busca a partir de um arquivo } 164 procedure LoadFromFile( const AFilename: string ); 165 { Carrega o texto da busca a partir de um stream } 166 procedure LoadFromStream( const AStream: TStream ); 167 { Carrega o texto da busca a partir de um buffer } 168 procedure LoadFromBuffer( const ABuffer: PChar ); 169 { Efetua a substituição da string encontrada pela string contida em "S" } 170 procedure Replace( const S: String ); 171 { Modo prático para setar as opções } 172 procedure EnableOptions( const CaseSensitive: Boolean = true; const WholeWords: Boolean = false; const HandleEOL: Boolean = true; const HandleWildCard: Boolean = false; const Backward: Boolean = false ); 173 174 end; 175 176 { Compara Str1 e Str2 de trás pra frente, se as duas forem iguais retorna true, caso contrário false } 177 function StrLRComp( S1, S2: PChar; const S2Begin: PChar ): Boolean; 178 { Converte para maiúsculo (ANSI) -> VALEUUUUU TIO RUSSÃO hahaha, o que tem no delphi "aplica a alteração" 179 Idéia de manter tabela com tudo maiúsculo arrancada de "QStrings 6.07.424 Copyright (C) 2000, 2003 Andrew Dryazgov [ andrewdr@newmail.ru ]" } 180 function AnsiUpCase(Ch: Char): Char; 181 182 const 183 { Caracteres que definem delimitadores de palavra, usada quando a opção WholeWords está ativa } 184 WhiteSpaces: set of Char = [' ',#9,#13,#10,'!','"','#','$','%','&','''','(',')','*','+','-','/',':',';','<','=','>','?','@','[','\',']','^','`','{','|','}','~']; 185 186 const 187 //fiz algumas alterações hehe, o tiozaum russo devia tá começano a ficar cego enqto fazia isso :) 188 ToUpperChars: array[0..255] of Char = 189 (#$00,#$01,#$02,#$03,#$04,#$05,#$06,#$07,#$08,#$09,#$0A,#$0B,#$0C,#$0D,#$0E,#$0F, 190 #$10,#$11,#$12,#$13,#$14,#$15,#$16,#$17,#$18,#$19,#$1A,#$1B,#$1C,#$1D,#$1E,#$1F, 191 #$20,#$21,#$22,#$23,#$24,#$25,#$26,#$27,#$28,#$29,#$2A,#$2B,#$2C,#$2D,#$2E,#$2F, 192 #$30,#$31,#$32,#$33,#$34,#$35,#$36,#$37,#$38,#$39,#$3A,#$3B,#$3C,#$3D,#$3E,#$3F, 193 #$40,#$41,#$42,#$43,#$44,#$45,#$46,#$47,#$48,#$49,#$4A,#$4B,#$4C,#$4D,#$4E,#$4F, 194 #$50,#$51,#$52,#$53,#$54,#$55,#$56,#$57,#$58,#$59,#$5A,#$5B,#$5C,#$5D,#$5E,#$5F, 195 #$60,#$41,#$42,#$43,#$44,#$45,#$46,#$47,#$48,#$49,#$4A,#$4B,#$4C,#$4D,#$4E,#$4F, 196 #$50,#$51,#$52,#$53,#$54,#$55,#$56,#$57,#$58,#$59,#$5A,#$7B,#$7C,#$7D,#$7E,#$7F, 197 #$80,#$81,#$82,#$81,#$84,#$85,#$86,#$87,#$88,#$89,#$8A,#$8B,#$8C,#$8D,#$8E,#$8F, 198 #$90,#$91,#$92,#$93,#$94,#$95,#$96,#$97,#$98,#$99,#$8A,#$9B,#$8C,#$9D,#$9E,#$9F, 199 #$A0,#$A1,#$A1,#$A3,#$A4,#$A5,#$A6,#$A7,#$A8,#$A9,#$AA,#$AB,#$AC,#$AD,#$AE,#$AF, 200 #$B0,#$B1,#$B2,#$B2,#$A5,#$B5,#$B6,#$B7,#$A8,#$B9,#$BA,#$BB,#$BC,#$BD,#$BE,#$BF, 201 #$C0,#$C1,#$C2,#$C3,#$C4,#$C5,#$C6,#$C7,#$C8,#$C9,#$CA,#$CB,#$CC,#$CD,#$CE,#$CF, 202 #$D0,#$D1,#$D2,#$D3,#$D4,#$D5,#$D6,#$D7,#$D8,#$D9,#$DA,#$DB,#$DC,#$DD,#$DE,#$DF, 203 #$C0,#$C1,#$C2,#$C3,#$C4,#$C5,#$C6,#$C7,#$C8,#$C9,#$CA,#$CB,#$CC,#$CD,#$CE,#$CF, 204 #$D0,#$D1,#$D2,#$D3,#$D4,#$D5,#$D6,#$F7,#$D8,#$D9,#$DA,#$DB,#$DC,#$DD,#$DE,#$9F); 205 206 implementation 207 208 function StrLRComp( S1, S2: PChar; const S2Begin: PChar ): Boolean; 209 begin 210 while ( S2 <> S2Begin ) and ( S1^ = S2^ ) do begin 211 dec( S1 ); 212 dec( S2 ); 213 end; 214 Result := ( S1^ = S2^ ) and ( S2 = S2Begin ); 215 end; 216 217 function AnsiUpCase(Ch: Char): Char; 218 begin 219 Result := ToUpperChars[ ord( ch ) ]; 220 end; 221 222 223 { class : TNotesSeeker } 224 225 { TNotesSeeker : protected } 226 227 function TNotesSeeker.GetText: string; 228 begin 229 if Assigned( FBufferBackup ) then 230 Result := StrPas( FBufferBackup ) 231 else 232 Result := ReplacedText; 233 end; 234 235 function TNotesSeeker.GetReplacedText: string; 236 begin 237 Result := StrPas( FBufferBegin ); 238 end; 239 240 function TNotesSeeker.GetContext: string; 241 var 242 BeginAt, EndAt: PChar; 243 begin 244 if not ( nsBackward in FOptions ) then begin 245 BeginAt := FBuffer - FMatchLen - FContextLeftLenght; 246 EndAt := FBuffer+FContextRightLenght; 247 end 248 else begin 249 BeginAt := FBuffer+1-FContextLeftLenght; 250 EndAt := FBuffer+1+FMatchLen+FContextRightLenght; 251 end; 252 if BeginAt > EndAt then 253 raise ENotesSeekerException.CreateFmt('GetContext::Range Error "BeginAt(%d) > EndAt(%d)"', [Integer(BeginAt), Integer(EndAt)]); 254 if BeginAt < FBufferBegin then 255 BeginAt := FBufferBegin; 256 if EndAt > FBufferEnd then 257 EndAt := FBufferEnd; 258 259 SetString( Result, BeginAt, EndAt-BeginAt ); 260 end; 261 262 function TNotesSeeker.GetSearchStr: string; 263 begin 264 Result := StrPas( FSearchBegin ); 265 end; 266 267 function TNotesSeeker.GetRemainingText: string; 268 begin 269 Result := ''; 270 if not ( nsBackward in FOptions ) then 271 Result := StrPas( FBuffer ) 272 else if FBuffer-FBufferBegin > -1 then 273 SetString( Result, FBufferBegin, FBuffer-FBufferBegin+1 ); 274 end; 275 276 function TNotesSeeker.GetCurByte: Cardinal; 277 begin 278 if nsBackward in FOptions then 279 Result := FBufferEnd-1 - FBuffer - FMatchLen 280 else 281 Result := FBuffer - FMatchLen - FBufferBegin; 282 end; 283 284 function TNotesSeeker.GetEOL: string; 285 begin 286 Result := StrPas( FEOL ); 287 end; 288 289 procedure TNotesSeeker.SetOptions(const Value: TNotesSeekerOptions); 290 begin 291 FOptions := Value; 292 if nsBackward in Value then 293 if nsHandleWildCard in Value then 294 Search := SearchBackwardWithWildCard 295 else 296 Search := SearchBackward 297 else if nsHandleWildCard in Value then 298 Search := SearchForwardWithWildCard 299 else 300 Search := SearchForward; 301 end; 302 303 procedure TNotesSeeker.SetText( const Value: string ); 304 begin 305 LoadFromBuffer( PChar( Value ) ); 306 end; 307 308 procedure TNotesSeeker.SetSearchStr(const Value: string); 309 begin 310 FreeSearchStr; 311 FSearchLen := Length( Value ); 312 GetMem( FSearchBegin, FSearchLen+1 ); 313 StrCopy( FSearchBegin, PChar( Value ) ); 314 FSearch := FSearchBegin; 315 FSearchEnd := StrEnd( FSearchBegin ); 316 end; 317 318 procedure TNotesSeeker.SetEOL(const Value: string); 319 begin 320 FreeEOL; 321 FEOLLen := Length( Value ); 322 GetMem( FEOL, FEOLLen+1 ); 323 StrCopy( FEOL, PChar( Value ) ); 324 end; 325 326 327 procedure TNotesSeeker.FreeBuffer; 328 begin 329 if Assigned( FBufferBegin ) then begin 330 FBufferEnd := nil; 331 FBuffer := nil; 332 FreeMem( FBufferBegin ); 333 end; 334 if Assigned( FBufferBackup ) then begin 335 FreeMem( FBufferBackup ); 336 FBufferBackup := nil; 337 end; 338 end; 339 340 procedure TNotesSeeker.FreeEOL; 341 begin 342 if Assigned( FEOL ) then begin 343 FreeMem( FEOL ); 344 FEOL := nil; 345 end; 346 end; 347 348 procedure TNotesSeeker.FreeSearchStr; 349 begin 350 if Assigned( FSearchBegin ) then begin 351 FreeMem( FSearchBegin ); 352 FSearchBegin := nil; 353 FSearch := nil; 354 FSearchEnd := nil; 355 end; 356 end; 357 358 359 360 { TNotesSeeker : public } 361 362 constructor TNotesSeeker.Create; 363 begin 364 EOL := #13#10; 365 FContextLeftLenght := 10; 366 FContextRightLenght := 20; 367 Search := SearchForward; 368 end; 369 370 destructor TNotesSeeker.Destroy; 371 begin 372 FreeBuffer; 373 FreeSearchStr; 374 FreeEOL; 375 inherited Destroy; 376 end; 377 378 procedure TNotesSeeker.LoadFromBuffer( const ABuffer: PChar ); 379 begin 380 FreeBuffer; 381 GetMem( FBufferBegin, StrLen( ABuffer )+1 ); 382 FBuffer := StrCopy( FBufferBegin, ABuffer ); 383 FBufferEnd := StrEnd( FBufferBegin ); 384 if FKeepText then begin 385 GetMem( FBufferBackup, StrLen( FBufferBegin )+1 ); 386 StrCopy( FBufferBackup, FBufferBegin ); 387 end; 388 end; 389 390 procedure TNotesSeeker.LoadFromFile(const AFilename: string); 391 var 392 FS: TFileStream; 393 begin 394 if not FileExists( AFilename ) then 395 raise ENotesSeekerException.CreateFmt( 'LoadFromFile::Arquivo "%s" não encontrado', [AFilename] ); 396 FS := TFileStream.Create( AFilename, fmOpenRead ); 397 try 398 LoadFromStream( FS ); 399 finally 400 FS.Free; 401 end; 402 end; 403 404 procedure TNotesSeeker.LoadFromStream(const AStream: TStream); 405 var 406 Size: Int64; 407 begin 408 FreeBuffer; 409 Size := AStream.Size; 410 GetMem( FBuffer, Size+1 ); 411 Size := AStream.Read( FBuffer^, Size ); 412 ( FBuffer+Size )^ := #0; 413 FBufferEnd := (FBuffer+Size); 414 FBufferBegin := FBuffer; 415 if FKeepText then begin 416 GetMem( FBufferBackup, StrLen( FBufferBegin )+1 ); 417 StrCopy( FBufferBackup, FBufferBegin ); 418 end; 419 end; 420 421 procedure TNotesSeeker.StartSearch; 422 begin 423 FMatches := 0; 424 FCurLine := 0; 425 FCurCol := 0; 426 427 if FSearchLen = 0 then 428 raise ENotesSeekerException.Create( 'StartSearch::Propriedade SearchStr está vazia.' ); 429 430 if ( FBufferBackup <> FBufferBegin ) and Assigned( FBufferBackup ) then begin 431 FreeMem( FBufferBegin ); 432 GetMem( FBufferBegin, StrLen( FBufferBackup )+1 ); 433 FBuffer := StrCopy( FBufferBegin, FBufferBackup ); 434 FBufferEnd := FBuffer + StrLen( FBufferBackup ); 435 end; 436 437 if nsBackward in FOptions then 438 FBuffer := FBufferEnd-1 439 else 440 FBuffer := FBufferBegin; 441 end; 442 443 procedure TNotesSeeker.Replace(const S: String); 444 var 445 TempBuff: PChar; 446 BufferOffset: Integer; 447 begin 448 TempBuff := nil; 449 if not ( nsBackward in FOptions ) then begin 450 BufferOffset := FBuffer-FMatchLen - FBufferBegin + Length( S ); 451 GetMem( TempBuff, ( FBuffer-FMatchLen - FBufferBegin) + Length(S) + ( FBufferEnd - FBuffer ) + 1 ); 452 FBufferEnd := StrLCopy( StrLCopy( StrLCopy( TempBuff, FBufferBegin, FBuffer-FMatchLen - FBufferBegin )+(FBuffer-FMatchLen - FBufferBegin), PChar( S ), Length( S ) )+Length( S ), FBuffer, FBufferEnd - FBuffer )+(FBufferEnd - FBuffer); 453 FreeMem( FBufferBegin ); 454 FBufferBegin := TempBuff; 455 FBuffer := FBufferBegin + BufferOffset; 456 end 457 else begin 458 BufferOffset := FBufferEnd - (FBuffer + FMatchLen) + Length( S ); 459 if FBuffer < FBufferBegin then 460 GetMem( TempBuff, FBufferEnd - (FBuffer+FMatchLen) + Length( S ) + ( FBuffer - FBufferBegin ) + 1 ) 461 else 462 GetMem( TempBuff, FBufferEnd - (FBuffer+FMatchLen) + Length( S ) + ( FBuffer - FBufferBegin ) + 1 ); 463 FBufferEnd := StrLCopy( StrLCopy( StrLCopy( TempBuff, FBufferBegin, FBuffer-FBufferBegin+1 )+(FBuffer-FBufferBegin+1), PChar( S ), Length( S ) )+Length( S ), FBuffer+FMatchLen+1, FBufferEnd-1 - (FBuffer+FMatchLen) )+ ( FBufferEnd-1 - (FBuffer+FMatchLen) ); 464 FreeMem( FBufferBegin ); 465 FBufferBegin := TempBuff; 466 FBuffer := FBufferEnd - BufferOffset; 467 end; 468 end; 469 470 471 { ENotesSeekerException } 472 { ENotesSeekerException : public } 473 474 constructor ENotesSeekerException.Create(const Msg: string); 475 begin 476 inherited Create( 'TNotesSeeker.'+Msg ); 477 end; 478 479 constructor ENotesSeekerException.CreateFmt(const Msg: string; const Args: array of const); 480 begin 481 inherited CreateFmt( 'TNotesSeeker.'+Msg, Args ); 482 end; 483 484 procedure TNotesSeeker.EnableOptions(const CaseSensitive, WholeWords, HandleEOL, HandleWildCard, Backward: Boolean); 485 var Opcoes: TNotesSeekerOptions; 486 begin 487 if CaseSensitive then Include( Opcoes, nsCaseSensitive ) else Exclude( Opcoes, nsCaseSensitive ); 488 if HandleEOL then Include( Opcoes, nsHandleEOL ) else Exclude( Opcoes, nsHandleEOL ); 489 if Backward then Include( Opcoes, nsBackward ) else Exclude( Opcoes, nsBackward ); 490 if HandleWildCard then Include( Opcoes, nsHandleWildCard ) else Exclude( Opcoes, nsHandleWildCard ); 491 if WholeWords then Include( Opcoes, nsWholeWords ) else Exclude( Opcoes, nsWholeWords ); 492 SetOptions( Opcoes ); 493 end; 494 495 function TNotesSeeker.SearchForward: Boolean; 496 begin 497 Result := True; 498 LineJump := 0; 499 FMatchLine := 0; 500 FMatchCol := 0; 501 FMatchLen := 0; 502 FSearch := FSearchBegin; 503 504 if FBufferBegin + FStartAt > FBufferEnd then 505 FStartAt := FBufferEnd - FBufferBegin; 506 while FStartAt > FBuffer-FBufferBegin do begin 507 if ( nsHandleEOL in FOptions ) and ( FBuffer^ = FEOL^ ) and ( StrLComp( FBuffer, FEOL, FEOLLen ) = 0 ) then begin 508 Inc( FBuffer, FEOLLen ); 509 Inc( FCurLine ); 510 FCurCol := 0; 511 Continue; 512 end 513 else 514 Inc( FCurCol ); 515 Inc( FBuffer ); 516 end; 517 518 while FBuffer <> FBufferEnd do begin 519 if ( (nsCaseSensitive in FOptions ) and ( FBuffer^ = FSearch^ ) ) or ( not(nsCaseSensitive in FOptions ) and ( AnsiUpCase( FBuffer^ ) = AnsiUpCase( FSearch^ ) ) ) then begin 520 Inc( FMatchLen ); 521 Inc( FSearch ); 522 if Result then begin 523 Result := False; 524 FMatchCol := FCurCol; 525 FMatchLine := FCurLine; 526 if ( nsWholeWords in FOptions ) and ( FBuffer > FBufferBegin ) and not ( (FBuffer-1)^ in WhiteSpaces ) then begin 527 FSearch := FSearchBegin; 528 FMatchLen := 0; 529 FMatchLine := 0; 530 FMatchCol := 0; 531 end; 532 end; 533 if ( nsWholeWords in FOptions ) and ( FMatchLen = FSearchLen ) and ( FBuffer < FBufferEnd-1 ) and not ( (FBuffer+1)^ in WhiteSpaces ) then begin 534 FSearch := FSearchBegin; 535 FMatchLen := 0; 536 FMatchLine := 0; 537 FMatchCol := 0; 538 end; 539 540 if ( nsHandleEOL in FOptions ) and ( FBuffer^ = FEOL^ ) and ( StrLComp( FBuffer, FEOL, FEOLLen ) = 0 ) then begin 541 Inc( FCurLine ); 542 FCurCol := 0; 543 LineJump := FEOLLen-1; 544 end 545 else if LineJump = 0 then 546 Inc( FCurCol ) 547 else 548 Dec( LineJump );