⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adsapiph.pas

📁 测试用例
💻 PAS
📖 第 1 页 / 共 5 页
字号:
                                         CurrentSection : TStringList;
                                         var CurrentWord : Integer;
                                         var MatchingKey : string) : Boolean;
var
  List : TStringList;
  i : Integer;
  j : Integer;
  Optional : Boolean;
  RCode : Boolean;
  OldCurrentWord : Integer;

begin
  OldCurrentWord := CurrentWord;
  Result := True;
  Optional := False;
  { Tokenize the rule that is being analyzed }
  List := TStringList.Create;
  try
    TokenizePhrase (CurrentRule, List);
    i := 0;
    while i < List.Count do begin
      { If the token is of the form <stuff> or (stuff), first check to see
        if there is a section of that name.  If there is then use RecurseRules
        to analyze it.  If there isn't a section with that name, then see
        if there is one or more rules with that name in the current section.
        If so, then analyze those rules. }
      if (IsAnglePhrase (List[i])) or (IsParenPhrase (List[i])) then begin
        if INIFile.SectionExists (List[i]) then begin
          RCode := RecurseRules (Tokens, INIFile, List[i], CurrentWord,
                                 MatchingKey);
          if (not RCode) and (not Optional) then begin
            Result := False;
            CurrentWord := OldCurrentWord;
            Exit;
          end;
        end else begin
          RCode := False;
          for j := 0 to CurrentSection.Count - 1 do
            if GetKey (CurrentSection[j]) = List[i] then begin
              if AnalyzeRule (Tokens, GetValue (CurrentSection[j]),
                              INIFile, CurrentSection, CurrentWord,
                              MatchingKey) then
                RCode := True;
            end;
          if (not RCode) and (not Optional) then begin
            Result := False;
            CurrentWord := OldCurrentWord;
            Exit;
          end;
        end;
        Optional := False;
      end else if List[i] = '[opt]' then begin
        Optional := True;
      end else if List[i] = '[1+]' then begin
      end else if List[i] = '[0+]' then begin
        Optional := True;
      end else if IsQuoted (List[i]) then begin
        case FStringHandler of
          gshIgnore :
            begin
              { do nothing }
            end;
          gshInsert :
            begin
              Tokens.Insert(CurrentWord, KillQuotes (List[i]));
              Inc (CurrentWord);
            end;
          gshAutoReplace :
            begin
              if (i = 0) then begin
                Tokens.Insert(0, KillQuotes (List[i]));
                Inc (CurrentWord);
              end else begin
                if (IsAnglePhrase (List[i - 1])) or
                   (IsParenPhrase (List[i - 1])) or
                   (CurrentWord = 0) then begin
                  Tokens.Insert(0, KillQuotes (List[i]));
                  Inc (CurrentWord);
                end else begin
                  if (i > 1) and (List[i - 2] = '[opt]') then begin
                    Tokens.Insert(0, KillQuotes (List[i]));
                    Inc (CurrentWord);
                  end else
                    Tokens[CurrentWord - 1] := KillQuotes (List[i]);
                end;
              end;
            end;
        end;
      end else begin
        if CurrentWord < Tokens.Count then begin
          if List[i] = Tokens[CurrentWord] then begin
            Inc (CurrentWord);
          end else if not Optional then
            Result := False;
        end else if CurrentWord >= Tokens.Count then begin
          Exit;
        end;
        Optional := False;
      end;
      Inc (i);
    end;
  finally
    List.Free;
  end;
end;

function TApdSapiAskForInfo.RecurseRules (Tokens : TStringList;
                                          INIFile : TApdSapiGrammarList;
                                          CurrentSection : string;
                                          var CurrentWord : Integer;
                                          var MatchingKey : string) : Boolean;
{ Recurse Rules loads a new section and then analyzes it }
var
  i : Integer;
  Value : string;
  List : TStringList;

begin
  Result := False;
  List := TStringList.Create;
  try
    { Does the section ask for exists as a section in the grammar }
    if INIFile.SectionExists (CurrentSection) then begin
      INIFile.ReadSectionValues (CurrentSection, List);
      for i := 0 to List.Count - 1 do begin
        Value := GetKey (List[i]);
        if (Value = '') or (Value = CurrentSection) or
           ((not IsAnglePhrase (Value)) and
            (not IsParenPhrase (Value))) then begin
          Value := GetValue (List[i]);
          { Analyze the rule }
          if AnalyzeRule (Tokens, Value, INIFile, List, CurrentWord,
                          MatchingKey) then begin
            { The rule matched.  Exit successfully }
            if (Value <> '') and
               ((MatchingKey = '') or (IsAnglePhrase (MatchingKey)) or
                (IsParenPhrase (MatchingKey))) then
              MatchingKey := GetKey (List[i]);
            Result := True;
            Exit;
          end;
        end;
      end;
    end;
  finally
    List.Free;
  end;
end;

function TApdSapiAskForInfo.LocateRule (Tokens : TStringList) : string;

  procedure PreparseGrammar (Grammar : TStringList);
  var
    i : Integer;
  begin
    for i := Grammar.Count - 1 downto 0 do begin
      Grammar[i] := Trim (Grammar[i]);
      if Grammar[i] = '' then
        Grammar.Delete(i)
      else if (Copy (Grammar[i], 1, 2) = '//') or
              (Copy (Grammar[i], 1, 1) = ';') then
        Grammar.Delete(i);
    end;
  end;

var
  INIFile : TApdSapiGrammarList;
  MatchingKey : string;
  FWorkingGrammar : TStringList;
  CurrentWord : Integer;

begin
  Result := '';
  CurrentWord := 0;
  MatchingKey := '';
  { Create an INI file that will be used to work with the grammar }
  INIFile := TApdSapiGrammarList.Create;
  try
    { Create a work grammar and merge all the grammars into it }
    FWorkingGrammar := TStringList.Create;
    try
      FWorkingGrammar.Text := FMainGrammar.Text + ^M^J + FAskForGrammar.Text;
      PreparseGrammar (FWorkingGrammar);
      INIFile.Assign (FWorkingGrammar); 
    finally
      FWorkingGrammar.Free;
    end;
    { Analyze the grammar - start with the <Start> rule }
    RecurseRules (Tokens, INIFile, '<Start>', CurrentWord, MatchingKey);
    Result := MatchingKey;
  finally
    INIFile.Free;
  end;
end;

function TApdSapiAskForInfo.FindGrammarRule (var Phrase : string) : string;

var
  Tokens : TStringList;
  i      : Integer;
  
begin
  Result := '';
  if Phrase = '' then
    Exit;
  Tokens := TStringList.Create;
  try
    { Break the phrase down into its tokens }
    TokenizePhrase (Phrase, Tokens);
    { Find the first rule that matches the phrase }
    Result := LocateRule (Tokens);
    Phrase := '';
    for i := 0 to Tokens.Count - 1 do 
      if i < Tokens.Count - 1 then
        Phrase := Phrase + Tokens[i] + ' '
      else
        Phrase := Phrase + Tokens[i];
  finally
    Tokens.Free;
  end;
end;

procedure TApdSapiAskForInfo.InitializeMainGrammar;
begin
  with FMainGrammar do begin
    Clear;
    Text := ApdDefaultPhoneGrammar;
  end;
end;

procedure TApdSapiAskForInfo.SapiPhraseFinishHook (Sender : TObject;
                                                   Phrase : string;
                                                   Results : Integer);
var
  PhraseType  : TApdPhraseType;
  PhraseRule  : string;
  StringData  : PChar;

begin
  PhraseType := DeterminePhraseTypeEx (Phrase, PhraseRule);
  case PhraseType of
    ptHelp        :
      FSapiEngine.Speak (Prompts.Help);
    ptBack        :
      begin
        if psCanGoBack in Options then begin
          FSapiEngine.DeRegisterPhraseFinishHook (SapiPhraseFinishHook);
          FSapiEngine.Speak (Prompts.GoingBack);
          if ReplyHandle <> 0 then
            PostMessage (ReplyHandle, apw_SapiInfoPhrase, ApdSapiAskBack, 0);
        end else 
          FSapiEngine.Speak (Prompts.CannotGoBack);
      end;
    ptOperator    :
      begin
        if psEnableOperator in Options then begin
          FSapiEngine.DeRegisterPhraseFinishHook (SapiPhraseFinishHook);
          FSapiEngine.Speak (Prompts.Operator);
          if ReplyHandle <> 0 then
            PostMessage (ReplyHandle, apw_SapiInfoPhrase, ApdSapiAskOperator, 0);
        end else 
          FSapiEngine.Speak (Prompts.NoOperator);
      end;
    ptHangup      :
      begin
        if psEnableAskHangup in Options then begin
          FSapiEngine.DeRegisterPhraseFinishHook (SapiPhraseFinishHook);
          FSapiEngine.Speak (Prompts.HangingUp);
          if ReplyHandle <> 0 then
            PostMessage (ReplyHandle, apw_SapiInfoPhrase, ApdSapiAskHangup, 0);
        end else 
          FSapiEngine.Speak (Prompts.CannotHangUp);
      end;
    ptWhere       :
      begin
        FSapiEngine.Speak (Prompts.Where);
        if ReplyHandle <> 0 then
          PostMessage (ReplyHandle, apw_SapiInfoPhrase, ApdSapiAskWhere, 0);
      end;
    ptRepeat      :
      begin
        FSapiEngine.Speak (Prompts.Main2);
        if ReplyHandle <> 0 then
          PostMessage (ReplyHandle, apw_SapiInfoPhrase, ApdSapiAskRepeat, 0);
      end;
    ptSpeakFaster :
      begin
        if psDisableSpeedChange in Options then begin
          FSapiEngine.Speak (Prompts.NoSpeedChange);
        end else begin
          if FSapiEngine.DirectSS.Speed < FSapiEngine.DirectSS.MaxSpeed -
                                          ApdSapiSpeedChange then begin
            FSapiEngine.DirectSS.Speed := FSapiEngine.DirectSS.Speed +
                                          ApdSapiSpeedChange;
            FSapiEngine.Speak (Prompts.SpeakingFaster);
            if ReplyHandle <> 0 then
              PostMessage (ReplyHandle, apw_SapiInfoPhrase,
                           ApdSapiAskSpeakFaster, 0);
          end else 
            FSapiEngine.Speak (Prompts.MaxSpeed);
        end;
      end;
    ptSpeakSlower :
      begin
        if psDisableSpeedChange in Options then begin
          FSapiEngine.Speak (Prompts.NoSpeedChange);
        end else begin
          if FSapiEngine.DirectSS.Speed > FSapiEngine.DirectSS.MinSpeed +
                                          ApdSapiSpeedChange then begin
            FSapiEngine.DirectSS.Speed := FSapiEngine.DirectSS.Speed -
                                          ApdSapiSpeedChange;
            FSapiEngine.Speak (Prompts.SpeakingSlower);
            if ReplyHandle <> 0 then
              PostMessage (ReplyHandle, apw_SapiInfoPhrase,
                           ApdSapiAskSpeakSlower, 0);
          end else 
            FSapiEngine.Speak (Prompts.MinSpeed);
        end;
      end;
    ptNone        :
      begin
      end;
    ptUnknown     :
      begin
        { Parse unrecognized grammar rules here }
        try
          if ReplyHandle <> 0 then begin
            StringData := StrAlloc (Length (Phrase) + 1);
            StrPCopy (StringData, Phrase);
            PostMessage (ReplyHandle, apw_SapiInfoPhrase,
                         StrToInt (PhraseRule), LongInt (StringData));
          end;
        except
          on EConvertError do
            FSapiEngine.Speak (Prompts.Unrecognized);
        end;
      end;
  end;
end;

procedure TApdSapiAskForInfo.SetAskForGrammar (v : TStringList);
begin
  FAskForGrammar.Assign (v);
end;

procedure TApdSapiAskForInfo.SetMainGrammar (v : TStringList);
begin
  FMainGrammar.Assign (v);
end;

procedure TApdSapiAskForInfo.SetOptions (v : TApdSapiPhoneSettings);
begin
  if v <> FOptions then
    FOptions := v;
end;

procedure TApdSapiAskForInfo.SetReplyHandle (v : THandle);
begin
  if v <> FReplyHandle then
    FReplyHandle := v;
end;

{ TApdCustomSapiPhone }

constructor TApdCustomSapiPhone.Create (AOwner : TComponent);
begin
  inherited Create (AOwner);
  FSpellingEchoBack := True;

  FInfo := TApdSapiAskForInfo.Create;
  FPrompts := TApdSapiPhonePrompts.Create;
  FList := TStringList.Create;

  FSapiEngine := SearchSapiEngine (Owner);
end;

destructor TApdCustomSapiPhone.Destroy;
begin
  AbortAskFor;
  CancelCall;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -