home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 October / Chip_2001-10_cd1.bin / zkuste / delphi / kolekce / d456 / DCSLIB25.ZIP / DCMaskTools.pas < prev    next >
Pascal/Delphi Source File  |  2001-05-23  |  17KB  |  637 lines

  1. {
  2.  BUSINESS CONSULTING
  3.  s a i n t - p e t e r s b u r g
  4.  
  5.          Components Library for Borland Delphi 4.x, 5.x
  6.          Copyright (c) 1998-2001 Alex'EM
  7.  
  8. }
  9. unit DCMaskTools;
  10.  
  11. (*
  12.  ⌠ε≡∞α≥ ∞α±ΩΦ Σδ  ΓΓεΣα
  13.    'L'  - ┴≤ΩΓ√ , ═┼╬┴╒╬─╚╠█┼ φα ΣαφφεΘ ∩ετΦ÷ΦΦ
  14.         Γετ∞εµφ√ ±δσΣ≤∙Φσ Γα≡Φαφ≥√ τα∩Φ±Φ:
  15.           a. L          - δ■ß√σ ß≤ΩΓ√
  16.           ß. L[a1a2.. ] - Σε∩≤±≥Φ∞√ ≥εδⁿΩε ß≤ΩΓ√ + [a1, a2, ...]
  17.           Γ. L(a1a2.. ) - Σε∩≤±≥Φ∞√ δ■ß√σ ß≤ΩΓ√ τα Φ±Ωδ■≈σφΦσ∞ [a1, a2, ...]
  18.  
  19.    'l'  - ┴≤ΩΓ√, ∩ετΦ÷Φ  Ωε≥ε≡α  φσ εß τα≥σδⁿφα 
  20.         Γετ∞εµφ√ ±δσΣ≤∙Φσ Γα≡Φαφ≥√ τα∩Φ±Φ:
  21.           a. l
  22.           ß. l[a1a2.. ] - Σε∩≤±≥Φ∞√ ≥εδⁿΩε ß≤ΩΓ√ + [a1, a2, ...]
  23.           Γ. l(a1a2.. )
  24.  
  25.    'A'  - ┴≤ΩΓ√ Φ ÷Φ⌠≡√, ═┼╬┴╒╬─╚╠█┼ φα ΣαφφεΘ ∩ετΦ÷ΦΦ
  26.         Γετ∞εµφ√ ±δσΣ≤∙Φσ Γα≡Φαφ≥√ τα∩Φ±Φ:
  27.           a. A
  28.           ß. A[a1a2.. ] - Σε∩≤±≥Φ∞√ ≥εδⁿΩε ß≤ΩΓ√ + [a1, a2, ...]
  29.           Γ. A(a1a2.. )
  30.  
  31.    'a'  - ┴≤ΩΓ√ Φ ÷Φ⌠≡√, ∩ετΦ÷Φ  Ωε≥ε≡α  φσ εß τα≥σδⁿφα 
  32.         Γετ∞εµφ√ ±δσΣ≤∙Φσ Γα≡Φαφ≥√ τα∩Φ±Φ:
  33.           a. a
  34.           ß. a[a1a2.. ]
  35.           Γ. a(a1a2.. )
  36.  
  37.    '╤'  - ╨ατ≡σ°σφ√ δ■ß√σ ±Φ∞Γεδ√
  38.         Γετ∞εµφ√ ±δσΣ≤∙Φσ Γα≡Φαφ≥√ τα∩Φ±Φ:
  39.           a. ╤
  40.           ß. ╤[a1a2.. ] - Σε∩≤±≥Φ∞√ ≥εδⁿΩε ÷Φ⌠≡√[a1, a2, ...]
  41.           Γ. ╤(a1a2.. )
  42.  
  43.    '±'  - ╨ατ≡σ°σφ√ δ■ß√σ ±Φ∞Γεδ√
  44.         Γετ∞εµφ√ ±δσΣ≤∙Φσ Γα≡Φαφ≥√ τα∩Φ±Φ:
  45.           a. ±
  46.           ß. ±[a1a2.. ] - [a1, a2, ...]
  47.           Γ. ╤(a1a2.. )
  48.  
  49.    '0'  - ╓Φ⌠≡√, ═┼╬┴╒╬─╚╠█┼ φα ΣαφφεΘ ∩ετΦ÷ΦΦ
  50.         Γετ∞εµφ√ ±δσΣ≤∙Φσ Γα≡Φαφ≥√ τα∩Φ±Φ:
  51.           a. 0
  52.           ß. 0[a1a2.. ] - Σε∩≤±≥Φ∞√ ≥εδⁿΩε ÷Φ⌠≡√[a1, a2, ...]
  53.           Γ. 0(a1a2.. )
  54.  
  55.    '9'  - ╓Φ⌠≡√, ∩ετΦ÷Φ  Ωε≥ε≡α  φσ εß τα≥σδⁿφα 
  56.         Γετ∞εµφ√ ±δσΣ≤∙Φσ Γα≡Φαφ≥√ τα∩Φ±Φ:
  57.           a. 9
  58.           ß. 9[a1a2.. ]
  59.           Γ. 9(a1a2.. )
  60.  
  61.    '!'  - ╤∩σ÷╤Φ∞Γεδ (∩ε±δσ φσπε ΦΣσ≥ ±Φ∞Γεδ, Ωε≥ε≡√Θ ∩εΣ±≥αΓδ σ≥±  αΓ≥ε∞α≥Φ≈σ±ΩΦ)
  62.         Γετ∞εµφ√ ±δσΣ≤∙Φσ Γα≡Φαφ≥√ τα∩Φ±Φ:
  63.           a. !c1          - σΣΦφΦ≈φ√Θ ±Φ∞Γεδ
  64.           ß. ![c1c2.. ]   - ∩ε±δσΣεΓα≥σδⁿφε±≥ⁿ ±Φ∞ΓεδεΓ
  65.           Γ. !(±1±2.. )r1 - Σε∩≤±≥Φ∞√ ±1,c2 - εφΦ τα∞σ∙α■≥±  φα r1
  66.  
  67.    '<u>', '</u>'  - ┬±σ ΓΓεΣΦ∞√σ ±Φ∞Γεδ√ ß≤Σ≤≥ ∩≡σεß≡ατεΓ√Γα≥ⁿ±  Γ Γσ≡⌡φΦΘ ≡σπΦ±≥≡
  68.    '<l>', '</l>'  - ┬±σ ΓΓεΣΦ∞√σ ±Φ∞Γεδ√ ß≤Σ≤≥ ∩≡σεß≡ατεΓ√Γα≥ⁿ±  Γ φΦµφΦΘ ≡σπΦ±≥≡
  69.  
  70.    '{<≈Φ±δε ∩εΓ≥ε≡σφΦΘ>}' - ╧ε±δσ Γ±σ⌡ ⌠ε≡∞α≥εΓ Σε∩≤±≥ΦΓε ταΣαφΦσ ΩεδδΦ≈σ±≥Γα ∩εΓ≥ε≡σφΦΘ
  71.        ex:
  72.           a. 9{18}!.9{2}
  73.           ß. 9{18}!(.,).9{2}
  74.           Γ. a[IVXLMC]{10}
  75.  
  76.    P.S. Γφ≤≥≡Φ ±ΩεßεΩ [], () Σε∩≤±≥Φ∞ τφαΩ '#' - ∩εΩατ√Γασ≥, ≈≥ε ±δσΣε∞ τα φΦ∞ ΦΣσ≥ ±Φ∞Γεδ
  77.         ∩ε±δσΣεΓα≥σδⁿφε±≥Φ, α φσ ±∩σ÷±Φ∞Γεδ (αΩ≥≤αδⁿφε Σδ  ±Φ∞ΓεδεΓ ']' Φ ')')
  78. *)
  79.  
  80. interface
  81.  
  82. type
  83.   TMaskCharSet = set of Char;
  84.   TMaskOption  = (moUpperCase, moLowerCase, moRequired);
  85.   TMaskOptions = set of TMaskOption;
  86.   TMaskType    = (mtMask, mtSymbol);
  87.  
  88.   TMaskItem = packed record
  89.     case MaskType: TMaskType of
  90.       mtMask:
  91.         (MChars: set of Char;
  92.          Options: TMaskOptions;
  93.          Exclude: boolean);
  94.       mtSymbol:
  95.         (SChars: set of Char;
  96.          Symbol: Char;
  97.          Replace: boolean);
  98.   end;
  99.  
  100.   PEditMasks_tag = ^TEditMasks;
  101.   TEditMasks = packed array [0..0] of TMaskItem;
  102.  
  103.   TEditMask = packed record
  104.     Capacity: smallint;
  105.     Count: smallint;
  106.     Masks: PEditMasks_tag;
  107.   end;
  108.  
  109. procedure EMSetCapacity(var EditMask: TEditMask; Capacity: smallint);
  110. procedure EMAddItem(var EditMask: TEditMask; MaskItem: TMaskItem);
  111. procedure EMClear(var EditMask: TEditMask);
  112. procedure EMInitStruct(Value: string; var EditMask: TEditMask);
  113.  
  114. function EMMatches(var Value: string; EditMask: TEditMask; SkipSymbols: boolean;
  115.   var SymbolsCount: integer; FullMask: boolean; var MaskEnd: integer): integer;
  116.  
  117. function EMDeleteChar(var Value: string; EditMask: TEditMask;
  118.   SelStart, SelEnd: integer): integer;
  119.  
  120. procedure EMInsertChar(var Value: string; InsertStr: string; EditMask: TEditMask;
  121.   var SelStart, SelEnd: integer);
  122.  
  123. procedure EMCompeteChar(var Value: string; EditMask: TEditMask; MaskEnd: integer;
  124.   var SelStart, SelEnd: integer);
  125.  
  126. procedure EMClearSymbols(var Value: string; EditMask: TEditMask; MaskEnd: integer;
  127.   var SelStart: integer);
  128.  
  129. implementation
  130.  
  131. uses SysUtils, Windows;
  132.  
  133. procedure EMSetCapacity(var EditMask: TEditMask; Capacity: smallint);
  134. begin
  135.   ReallocMem(EditMask.Masks, Capacity*SizeOf(TMaskItem));
  136.   EditMask.Capacity := Capacity;
  137. end;
  138.  
  139. procedure EMClear(var EditMask: TEditMask);
  140. begin
  141.   ReallocMem(EditMask.Masks, 0);
  142.   EditMask.Capacity := 0;
  143.   EditMask.Count    := 0;
  144. end;
  145.  
  146. procedure EMAddItem(var EditMask: TEditMask; MaskItem: TMaskItem);
  147. begin
  148.   with EditMask do
  149.   begin
  150.     if Count = Capacity then EMSetCapacity(EditMask, Capacity + 4);
  151.     Masks[Count] := MaskItem;
  152.     Inc(Count);
  153.   end;
  154. end;
  155.  
  156. procedure EMInitStruct(Value: string; var EditMask: TEditMask);
  157.  const
  158.    Numbers: TMaskCharSet = ['0'..'9'];
  159.    Letters: TMaskCharSet = ['A'..'Z', 'a'..'z', Chr($C0)..Chr($FF), Chr($A8), Chr($B8)];
  160.  
  161.  var
  162.   P: PChar;
  163.   MaskState: TMaskOptions;
  164.   SCount: integer;
  165.  
  166.   procedure ScanTag(AddTag: boolean);
  167.   begin
  168.     Inc(P);
  169.     while not(P^ in [#0, '>']) do
  170.     begin
  171.       case P^ of
  172.         'u':
  173.           if AddTag then
  174.             MaskState := MaskState + [moUpperCase]
  175.           else
  176.             MaskState := MaskState - [moUpperCase];
  177.         'l':
  178.           if AddTag then
  179.             MaskState := MaskState + [moLowerCase]
  180.           else
  181.             MaskState := MaskState - [moLowerCase];
  182.         '/':
  183.           if AddTag then
  184.           begin
  185.             ScanTag(False);
  186.             Exit;
  187.           end;
  188.       end;
  189.       Inc(P);
  190.     end;
  191.     if P^ = '>' then Inc(P);
  192.   end;
  193.  
  194.   procedure ScanSymbol(Sequence: boolean);
  195.    var
  196.     ScanChars: TMaskCharSet;
  197.  
  198.     procedure AddSymbol(Symbol: Char; AReplace: boolean = False);
  199.       var
  200.        MaskItem: TMaskItem;
  201.     begin
  202.       MaskItem.MaskType := mtSymbol;
  203.       MaskItem.Symbol   := Symbol;
  204.       MaskItem.SChars   := ScanChars;
  205.       MaskItem.Replace  := AReplace;
  206.       EMAddItem(EditMask, MaskItem);
  207.     end;
  208.  
  209.   begin
  210.     if not Sequence then SCount := 0;
  211.     Inc(P);
  212.     if not Sequence and (P^ = '(') then
  213.     begin
  214.       inc(P);
  215.       ScanChars := [];
  216.       while not(P^ in [')', #0]) do
  217.       begin
  218.         if P^ = '#' then Inc(P);
  219.         ScanChars := ScanChars + [P^];
  220.         inc(P);
  221.       end;
  222.       if (P^ = ')') and ((P+1)^ <> #0) then
  223.       begin
  224.         inc(P);
  225.         AddSymbol(P^, True);
  226.         inc(P);
  227.       end;
  228.       Exit;
  229.     end;
  230.  
  231.     while not(P^ in [#0, ']']) do
  232.     begin
  233.       case P^ of
  234.         '[':
  235.           begin
  236.             if not Sequence then
  237.             begin
  238.               ScanSymbol(True);
  239.               Exit;
  240.             end
  241.             else AddSymbol(P^);
  242.           end;
  243.         '#':
  244.           begin
  245.             if (P+1)^ <> #0 then
  246.             begin
  247.               Inc(P);
  248.               AddSymbol(P^);
  249.               if not Sequence then
  250.               begin
  251.                 Inc(P);
  252.                 Break;
  253.               end;
  254.             end;
  255.           end;
  256.         else begin
  257.           AddSymbol(P^);
  258.           if not Sequence then
  259.           begin
  260.             Inc(P);
  261.             Break;
  262.           end;
  263.         end;
  264.       end;
  265.       Inc(P);
  266.     end;
  267.     if P^ = ']' then
  268.     begin
  269.       if not Sequence then AddSymbol(P^);
  270.       Inc(P);
  271.     end;
  272.   end;
  273.  
  274.   procedure ScanMaskChar(Chars: TMaskCharSet);
  275.    var
  276.     MaskItem: TMaskItem;
  277.     ScanChars: TMaskCharSet;
  278.  
  279.     procedure AddMaskItem;
  280.      var
  281.       sValue: string;
  282.       i: integer;
  283.     begin
  284.       if P^ = '{' then
  285.       begin
  286.         Inc(P);
  287.         sValue := '';
  288.         while P^ <> #0 do
  289.         begin
  290.           if P^ = '}' then
  291.           begin
  292.             for i := 1 to StrToIntDef(sValue, 0) do
  293.             EMAddItem(EditMask, MaskItem);
  294.             Break;
  295.           end;
  296.           sValue := sValue + P^;
  297.           Inc(P);
  298.         end;
  299.       end
  300.       else
  301.          EMAddItem(EditMask, MaskItem);
  302.     end;
  303.  
  304.   begin
  305.     ScanChars := [];
  306.     MaskItem.Options := MaskState;
  307.     MaskItem.MaskType := mtMask;
  308.     MaskItem.Exclude := False;
  309.  
  310.     Inc(P);
  311.     if P^ in ['[', '('] then
  312.     begin
  313.       if P^ = '[' then MaskItem.Exclude := False else MaskItem.Exclude := True;
  314.       Inc(P);
  315.       while P^ <> #0 do
  316.       begin
  317.         case P^ of
  318.           '#':
  319.             begin
  320.               if (P+1)^ <> #0 then
  321.               begin
  322.                 Inc(P);
  323.                 ScanChars := ScanChars + [P^];
  324.               end;
  325.             end;
  326.           ']':
  327.             if not MaskItem.Exclude then
  328.             begin
  329.               Inc(P); Break;
  330.             end
  331.             else
  332.               ScanChars := ScanChars + [P^];
  333.           ')':
  334.             if MaskItem.Exclude then
  335.             begin
  336.               Inc(P); Break;
  337.             end
  338.             else
  339.               ScanChars := ScanChars + [P^];
  340.           else
  341.             ScanChars := ScanChars + [P^];
  342.         end;
  343.         Inc(P);
  344.       end;
  345.       if Chars <> [] then
  346.       begin
  347.         MaskItem.Exclude  := False;
  348.         if MaskItem.Exclude then
  349.           ScanChars := Chars - ScanChars
  350.         else
  351.           ScanChars := Chars + ScanChars
  352.       end;
  353.  
  354.       MaskItem.MChars := ScanChars;
  355.       AddMaskItem;
  356.     end
  357.     else begin
  358.       MaskItem.MChars := Chars;
  359.       AddMaskItem;
  360.     end;
  361.   end;
  362.  
  363. begin
  364.   P := PChar(Value);
  365.   EMClear(EditMask);
  366.   MaskState := [];
  367.  
  368.   while P^ <> #0 do
  369.   begin
  370.     case P^ of
  371.       'L', 'l':
  372.         begin
  373.           if P^ = 'L' then
  374.             MaskState := MaskState + [moRequired]
  375.           else
  376.             MaskState := MaskState - [moRequired];
  377.           ScanMaskChar(Letters);
  378.         end;
  379.       'A', 'a':
  380.         begin
  381.           if P^ = 'A' then
  382.             MaskState := MaskState + [moRequired]
  383.           else
  384.             MaskState := MaskState - [moRequired];
  385.           ScanMaskChar(Letters + Numbers);
  386.         end;
  387.       'C', 'c':
  388.         begin
  389.           if P^ = 'C' then
  390.             MaskState := MaskState + [moRequired]
  391.           else
  392.             MaskState := MaskState - [moRequired];
  393.           ScanMaskChar([]);
  394.         end;
  395.       '0', '9':
  396.         begin
  397.           if P^ = '0' then
  398.             MaskState := MaskState + [moRequired]
  399.           else
  400.             MaskState := MaskState - [moRequired];
  401.           ScanMaskChar(Numbers);
  402.         end;
  403.       '!': ScanSymbol(False);
  404.       '<': ScanTag(True);
  405.       else
  406.         Inc(P);
  407.     end;
  408.   end;
  409. end;
  410.  
  411. function EMMatches(var Value: string; EditMask: TEditMask; SkipSymbols: boolean;
  412.   var SymbolsCount: integer; FullMask: boolean; var MaskEnd: integer): integer;
  413.  var
  414.   StartPos: integer;
  415.   Text: string;
  416.  
  417.   function MatchesEditMask(var StartPos: integer): boolean;
  418.    var
  419.     P: PChar;
  420.     i : integer;
  421.  
  422.     function GetMaskChar(Index: integer; C: Char): Char;
  423.     begin
  424.       with EditMask.Masks[Index] do
  425.       begin
  426.         if (MaskType = mtSymbol) and Replace then C := Symbol;
  427.         if moLowerCase in Options then C := AnsiLowerCase(String(C))[1];
  428.         if moUpperCase in Options then C := AnsiUpperCase(String(C))[1];
  429.       end;
  430.       Result := C;
  431.     end;
  432.  
  433.     function ValidChar(C: Char; MaskItem: TMaskItem): boolean;
  434.     begin
  435.       case MaskItem.MaskType of
  436.         mtSymbol:
  437.           begin
  438.             if MaskItem.Replace then
  439.               Result := C in MaskItem.SChars
  440.             else
  441.               Result := (C = MaskItem.Symbol);
  442.           end;
  443.         mtMask:
  444.           begin
  445.             if MaskItem.Exclude then
  446.               Result := not(C in MaskItem.MChars)
  447.             else
  448.               Result := ((MaskItem.MChars = []) or (C in MaskItem.MChars));
  449.           end;
  450.         else
  451.           Result := False;
  452.       end;
  453.     end;
  454.  
  455.     function RequiredChar(i: integer): boolean;
  456.     begin
  457.       with EditMask do
  458.         Result := (Masks[i].MaskType = mtMask) and (moRequired in Masks[i].Options) or
  459.                   (Masks[i].MaskType = mtSymbol);
  460.     end;
  461.  
  462.   begin
  463.     SymbolsCount := 0;
  464.     Result := False;
  465.     Text   := '';
  466.     P := PChar(Value);
  467.     i := StartPos;
  468.     with EditMask do while not Result and (P^ <> #0) and (i < Count) do
  469.     begin
  470.       if SkipSymbols then
  471.       begin
  472.         while (Masks[i].MaskType = mtSymbol) and (i < Count) do
  473.         begin
  474.           Inc(i);
  475.           Inc(SymbolsCount);
  476.         end;
  477.       end;
  478.  
  479.       if i < Count then
  480.       begin
  481.         if ValidChar(P^, Masks[i]) then
  482.         begin
  483.           Text := Text + GetMaskChar(i, P^);
  484.           Inc(P); Inc(i);
  485.         end
  486.         else begin
  487.           if not RequiredChar(i) then
  488.           begin
  489.             if (StartPos = 0) and not RequiredChar(StartPos) then Inc(StartPos);
  490.             Inc(i)
  491.           end
  492.           else begin
  493.             if not RequiredChar(StartPos) then
  494.             begin
  495.               StartPos := StartPos + 1;
  496.               Result   := MatchesEditMask(StartPos);
  497.               Exit;
  498.             end
  499.             else Break;
  500.           end;
  501.         end;
  502.       end;
  503.     end;
  504.     MaskEnd := i;
  505.     if not Result and (P^ = #0) then with EditMask do
  506.     begin
  507.       if (i <> Count) and FullMask then
  508.       begin
  509.         while not((Masks[i].MaskType = mtMask) and (moRequired in Masks[i].Options)) and
  510.               (i < Count) do Inc(i);
  511.         if i <> Count then
  512.         begin
  513.           if (Masks[StartPos].MaskType = mtMask) and not(moRequired in Masks[StartPos].Options) then
  514.           begin
  515.             StartPos := StartPos + 1;
  516.             Result   := MatchesEditMask(StartPos);
  517.           end;
  518.         end
  519.         else
  520.           Result := True;
  521.       end
  522.       else
  523.         Result := True;
  524.     end;
  525.   end;
  526.  
  527. begin
  528.   StartPos := 0;
  529.   MaskEnd  := 0;
  530.   if MatchesEditMask(StartPos) then
  531.   begin
  532.     Result := StartPos;
  533.     Value  := Text;
  534.   end
  535.   else
  536.     Result := -1;
  537. end;
  538.  
  539.  
  540. function EMDeleteChar(var Value: string; EditMask: TEditMask; SelStart, SelEnd: integer): integer;
  541.  var
  542.   Text: string;
  543.   MaskStart, SymbolsCount, MaskEnd: integer;
  544. begin
  545.   Text := Value;
  546.   if SelEnd - SelStart = 0 then
  547.     Delete(Text, SelStart + 1, 1)
  548.   else
  549.     Delete(Text, SelStart + 1, SelEnd - SelStart);
  550.  
  551.   MaskStart := EMMatches(Text, EditMask, False, SymbolsCount, False, MaskEnd);
  552.   while (MaskStart = -1) and (Length(Text) > 0) do
  553.   begin
  554.     if Length(Text) > (SelStart + 1) then
  555.       Delete(Text, SelStart + 1, 1)
  556.     else
  557.       Delete(Text, Length(Text), 1);
  558.     MaskStart := EMMatches(Text, EditMask, False, SymbolsCount, False, MaskEnd);
  559.   end;
  560.   Value  := Text;
  561.   if MaskStart > -1 then
  562.     Result := MaskEnd
  563.   else
  564.     Result := 0;
  565. end;
  566.  
  567. procedure EMCompeteChar(var Value: string; EditMask: TEditMask; MaskEnd: integer;
  568.   var SelStart, SelEnd: integer);
  569. begin
  570.   if MaskEnd < EditMask.Count then
  571.   with EditMask do begin
  572.     while (MaskEnd < Count) and (Masks[MaskEnd].MaskType = mtSymbol) do
  573.     begin
  574.       Value := Value + Masks[MaskEnd].Symbol;
  575.       Inc(SelStart);
  576.       Inc(SelEnd);
  577.       Inc(MaskEnd);
  578.     end;
  579.   end;
  580. end;
  581.  
  582. procedure EMInsertChar(var Value: string; InsertStr: string; EditMask: TEditMask;
  583.   var SelStart, SelEnd: integer);
  584.  var
  585.   Text: string;
  586.   MaskStart, SymbolsCount, MaskEnd, Offset: integer;
  587.  
  588.   function GetSource(Source, S: string; Index, Offset: integer): string;
  589.   begin
  590.     if Offset > 0 then S := Copy(S, 1, Length(S) -Offset);
  591.     Result := Source;
  592.     Insert(S, Result, Index);
  593.   end;
  594.  
  595. begin
  596.   if SelStart < SelEnd then
  597.   begin
  598.     Delete(Value, SelStart + 1, SelEnd - SelStart);
  599.     SelEnd := SelStart;
  600.   end;
  601.  
  602.   Text := GetSource(Value, InsertStr, SelStart+1, 0);
  603.   MaskStart := EMMatches(Text, EditMask, False, SymbolsCount, False, MaskEnd);
  604.  
  605.   if MaskStart = -1 then
  606.   begin
  607.     Offset := 1;
  608.     while (MaskStart = -1) and (Length(InsertStr) > Offset)do
  609.     begin
  610.       Text := GetSource(Value, InsertStr, SelStart+1, Offset);
  611.       MaskStart := EMMatches(Text, EditMask, False, SymbolsCount, False, MaskEnd);
  612.       Inc(Offset);
  613.     end;
  614.   end
  615.   else begin
  616.     Value := Text;
  617.     SelStart := SelStart+Length(InsertStr);
  618.   end;
  619.   if MaskStart > -1 then EMCompeteChar(Value, EditMask, MaskEnd, SelStart, SelEnd);
  620. end;
  621.  
  622. procedure EMClearSymbols(var Value: string; EditMask: TEditMask; MaskEnd: integer;
  623.   var SelStart: integer);
  624.  var
  625.   i: integer;
  626. begin
  627.   i := MaskEnd;
  628.   with EditMask do
  629.   begin
  630.     while (i >= 0) and (Masks[i].MaskType = mtSymbol) do Dec(i);
  631.     if (i >= 0) and (i <> MaskEnd) then Delete(Value, Length(Value) - MaskEnd + i, MaskEnd - i + 1);
  632.   end;
  633. end;
  634.  
  635. end.
  636.  
  637.