{*********************************************************} {* O32PVLDR.PAS 4.06 *} {*********************************************************} {* ***** BEGIN LICENSE BLOCK ***** *} {* Version: MPL 1.1 *} {* *} {* The contents of this file are subject to the Mozilla Public License *} {* Version 1.1 (the "License"); you may not use this file except in *} {* compliance with the License. You may obtain a copy of the License at *} {* http://www.mozilla.org/MPL/ *} {* *} {* Software distributed under the License is distributed on an "AS IS" basis, *} {* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License *} {* for the specific language governing rights and limitations under the *} {* License. *} {* *} {* The Original Code is TurboPower Orpheus *} {* *} {* The Initial Developer of the Original Code is TurboPower Software *} {* *} {* Portions created by TurboPower Software Inc. are Copyright (C)1995-2002 *} {* TurboPower Software Inc. All Rights Reserved. *} {* *} {* Contributor(s): *} {* *} {* ***** END LICENSE BLOCK ***** *} {$I OVC.INC} {-Defines} unit o32pvldr; {Paradox Mask Validator} interface uses {$IFNDEF LCL} Windows, {$ELSE} LclIntf, MyMisc, {$ENDIF} O32Vldtr, Classes; const ParadoxMaskCount = 8; ParadoxMaskLength = 25; {Sample Paradox Masks} ParadoxMaskLookup : array [1..ParadoxMaskCount] of string = ('!\(999\)000-0000;1;_ Phone (415)555-1212', '!99999;1;_ Extension 15450', '000\-00\-0000;1;_ Social Security 555-55-5555', '00000;1;_ Short Zip Code 90504', '00000\-9999;1;_ Long Zip Code 90504-0000', '!99/99/00;1;_ Date 06/27/01', '!90:00:00>LL;1;_ Long Time 09:05:15PM', '!90:00;1;_ Short Time 13:45'); type {class - TO32ParadoxValidator} TO32ParadoxValidator = class(TO32BaseValidator) protected {private} FMaskBlank: Char; procedure SetInput(const Value: string); override; procedure SetMask(const Value: string); override; function GetValid: Boolean; override; function GetSampleMasks: TStringList; override; function Validate(const Value: string; var Pos: Integer): Boolean; function DoValidateChar(NewChar: Char; MaskOffset: Integer): Boolean; function ValidateChar(NewChar: Char; Offset: Integer): Boolean; function FindLiteralChar(MaskOffset: Integer; InChar: Char): Integer; public constructor Create(AOwner: TComponent); override; function IsValid: Boolean; override; property Valid; property Input; published {Properties} property Mask; {Events} property BeforeValidation; property AfterValidation; property OnValidationError; end; implementation uses {$IFNDEF LCL} Mask, {$IFDEF VERSION6} MaskUtils, {$ENDIF} {$ELSE} MaskEdit, {$ENDIF} SysUtils, O32VlReg; // In the original Orpheus, TurboPower had just copied the following // functions from the VCL Mask unit in order to use them with Delphi 5 // and earlier: MaskGetCharType, MaskOffsetToOffset, OffsetToMaskOffset, // MaskIntlLiteralToChar, and MaskGetCurrentDirectives. // With Delphi 6, these functions are now in MaskUtils unit and in the // interfaces section. However, these functions and the constants they // reference are not currently available with the LCL, so for now the // Paradox validator is not available for LCL. {===== TO32ParadoxValidator ==========================================} constructor TO32ParadoxValidator.Create(AOwner: TComponent); begin inherited; FMaskBlank := DefaultBlank; end; {=====} function TO32ParadoxValidator.GetValid: Boolean; begin result := IsValid; end; {=====} function TO32ParadoxValidator.GetSampleMasks: TStringList; var I : Integer; begin { Set the length of the mask portion of the string } FSampleMaskLength := ParadoxMaskLength; FSampleMasks.Clear; { Load the string list } for I := 1 to ParadoxMaskCount do FSampleMasks.Add(ParadoxMaskLookup[I]); result := FSampleMasks; end; {=====} function TO32ParadoxValidator.IsValid: Boolean; var ErrorPos: Integer; begin DoBeforeValidation; {assume the worst} FValid := false; {Set up validation and execute it against the input} FValid := Validate(FInput, ErrorPos); DoAfterValidation; if not FValid then begin DoOnError(self, 'Validation Error Encountered at string position ' + IntToStr(ErrorPos)); end; result := FValid; end; {=====} procedure TO32ParadoxValidator.SetInput(const Value: string); begin if FInput <> Value then FInput := Value; end; {=====} procedure TO32ParadoxValidator.SetMask(const Value: string); begin if FMask <> Value then FMask := Value; end; {=====} function TO32ParadoxValidator.Validate(const Value: string; var Pos: Integer): Boolean; var I : Integer; begin result := true; Pos := 0; for I := 1 to Length(Value) do begin if not ValidateChar(Value[I], I) then begin result := false; Pos := I; Exit; end; end; end; {=====} function TO32ParadoxValidator.ValidateChar(NewChar: Char; Offset: Integer): Boolean; var MaskOffset: Integer; begin Result := True; if FMask <> '' then begin Result := False; MaskOffset := OffsetToMaskOffset(FMask, Offset); if MaskOffset >= 0 then begin Result := DoValidateChar(NewChar, MaskOffset); end; end; end; {=====} function TO32ParadoxValidator.FindLiteralChar(MaskOffset: Integer; InChar: Char): Integer; var CType: TMaskCharType; LitChar: Char; begin Result := -1; while MaskOffset < Length(Mask) do begin Inc(MaskOffset); CType := MaskGetCharType(Mask, MaskOffset); if CType in [mcLiteral, mcIntlLiteral] then begin LitChar := Mask[MaskOffset]; if CType = mcIntlLiteral then LitChar := MaskIntlLiteralToChar(LitChar); if LitChar = InChar then Result := MaskOffset; Exit; end; end; end; {=====} function TO32ParadoxValidator.DoValidateChar(NewChar: Char; MaskOffset: Integer): Boolean; var Dir: TMaskDirectives; Str: string; CType: TMaskCharType; function IsKatakana(const Chr: Byte): Boolean; begin Result := (SysLocale.PriLangID = LANG_JAPANESE) and (Chr in [$A1..$DF]); end; function TestChar(NewChar: Char): Boolean; var Offset: Integer; begin Offset := MaskOffsetToOffset(FMask, MaskOffset); Result := not ((MaskOffset < Length(FMask)) and (UpCase(FMask[MaskOffset]) = UpCase(Mask[MaskOffset+1]))) or (ByteType(FMask, Offset) = mbTrailByte) or (ByteType(FMask, Offset+1) = mbLeadByte); end; begin Result := True; CType := MaskGetCharType(FMask, MaskOffset); if not (CType in [mcLiteral, mcIntlLiteral]) then begin Dir := MaskGetCurrentDirectives(FMask, MaskOffset); case FMask[MaskOffset] of mMskNumeric, mMskNumericOpt: begin if not ((NewChar >= '0') and (NewChar <= '9')) then Result := False; end; mMskNumSymOpt: begin if not (((NewChar >= '0') and (NewChar <= '9')) or (NewChar = ' ') or(NewChar = '+') or(NewChar = '-')) then Result := False; end; mMskAscii, mMskAsciiOpt: begin if (NewChar in LeadBytes) and TestChar(NewChar) then begin Result := False; Exit; end; if IsCharAlpha(NewChar) then begin Str := ' '; Str[1] := NewChar; if (mdUpperCase in Dir) then Str := AnsiUpperCase(Str) else if mdLowerCase in Dir then Str := AnsiLowerCase(Str); end; end; mMskAlpha, mMskAlphaOpt, mMskAlphaNum, mMskAlphaNumOpt: begin if (NewChar in LeadBytes) then begin if TestChar(NewChar) then Result := False; Exit; end; Str := ' '; Str[1] := NewChar; if IsKatakana(Byte(NewChar)) then Exit; if not IsCharAlpha(NewChar) then begin Result := False; if ((FMask[MaskOffset] = mMskAlphaNum) or (FMask[MaskOffset] = mMskAlphaNumOpt)) and (IsCharAlphaNumeric(NewChar)) then Result := True; end else if mdUpperCase in Dir then Str := AnsiUpperCase(Str) else if mdLowerCase in Dir then Str := AnsiLowerCase(Str); end; end; end; end; initialization RegisterValidator(TO32ParadoxValidator); finalization UnRegisterValidator(TO32ParadoxValidator); end.