(mathml: Element<'m>, nav_command: &'static str,
rules: &Ref<SpeechRules>, rules_with_context: &mut SpeechRulesWithContext<'c, '_, 'm>, nav_state: &mut RefMut<NavigationState>,
| 394 | |
| 395 | |
| 396 | fn apply_navigation_rules<'c, 'm:'c>(mathml: Element<'m>, nav_command: &'static str, |
| 397 | rules: &Ref<SpeechRules>, rules_with_context: &mut SpeechRulesWithContext<'c, '_, 'm>, nav_state: &mut RefMut<NavigationState>, |
| 398 | loop_count: usize) -> Result<(String, bool)> { |
| 399 | let context = rules_with_context.get_context(); |
| 400 | context.set_variable("MatchCounter", loop_count as f64); |
| 401 | |
| 402 | let start_node = get_start_node(mathml, nav_state)?; |
| 403 | // debug!("start_node\n{}", mml_to_string(&start_node)); |
| 404 | |
| 405 | let raw_speech_string = rules_with_context.match_pattern::<String>(start_node) |
| 406 | .chain_err(|| "Pattern match/replacement failure during math navigation!")?; |
| 407 | let speech = rules.pref_manager.borrow().get_tts() |
| 408 | .merge_pauses(crate::speech::remove_optional_indicators( |
| 409 | &raw_speech_string.replace(CONCAT_STRING, "") |
| 410 | .replace(CONCAT_INDICATOR, "") |
| 411 | ) |
| 412 | .trim()); |
| 413 | // debug!("Nav Speech: {}", speech); |
| 414 | |
| 415 | // FIX: add things that need to do a speech replacement based on some marker for "where am i" and others that loop ([Speak: id])??? |
| 416 | // what else needs to be done/set??? |
| 417 | |
| 418 | // transfer some values that might have been set into the prefs |
| 419 | let context = rules_with_context.get_context(); // need to recompute or we have a multiple borrow problem |
| 420 | nav_state.mode = context_get_variable(context, "NavMode", mathml)?.0.unwrap(); |
| 421 | rules.pref_manager.as_ref().borrow_mut().set_user_prefs("NavMode", &nav_state.mode); |
| 422 | |
| 423 | let nav_position = match context_get_variable(context, "NavNode", mathml)?.0 { |
| 424 | None => NavigationPosition::default(), |
| 425 | Some(node) => NavigationPosition { |
| 426 | current_node: node, |
| 427 | current_node_offset: context_get_variable(context, "NavNodeOffset", mathml)?.1.unwrap() as usize |
| 428 | } |
| 429 | }; |
| 430 | |
| 431 | // after a command, we either read or describe the new location (part of state) |
| 432 | // also some commands are DescribeXXX/ReadXXX, so we need to look at the commands also |
| 433 | let use_read_rules = if nav_command.starts_with("Read") { |
| 434 | true |
| 435 | } else if nav_command.starts_with("Describe") { |
| 436 | false |
| 437 | } else { |
| 438 | let overview = context_get_variable(context, "Overview", mathml)?.0.unwrap(); |
| 439 | overview == "false" |
| 440 | }; |
| 441 | |
| 442 | if (nav_command.starts_with("Move") || nav_command.starts_with("Zoom")) && nav_command != "MoveLastLocation" { |
| 443 | // push the new location on the stack |
| 444 | if nav_position != NavigationPosition::default() { |
| 445 | // debug!("nav_state: pushing on {}", &nav_position); |
| 446 | let current_node = nav_position.current_node.as_str(); |
| 447 | if current_node != nav_state.top().unwrap().0.current_node && current_node != ILLEGAL_NODE_ID { |
| 448 | nav_state.push(nav_position.clone(), nav_command); |
| 449 | } |
| 450 | } |
| 451 | } |
| 452 | |
| 453 | if nav_command.starts_with("SetPlacemarker") { |
no test coverage detected