Exemple #1
0
        public bool Init(IEnumerable <String> extensionDirs)
        {
            if (_agentsCache == null)
            {
                _agentsCache = new AgentsCache();
                _agentsCache.EvtAgentAdded += _agentsCache_EvtAgentAdded;
                _agentsCache.Init(extensionDirs);

                _genericAppAgent = _agentsCache.GetAgent(GenericAppAgentName);
                if (_genericAppAgent == null)
                {
                    _agentsCache.AddAgentByType(typeof(UnsupportedAppAgent));
                    _genericAppAgent = _agentsCache.GetAgent(GenericAppAgentName);
                }

                _agentsCache.AddAgentByType(typeof(NullAgent));
                _nullAgent = _agentsCache.GetAgent(NullAgentName);

                _dialogAgent      = _agentsCache.GetAgent(DialogControlAgentName);
                _menuControlAgent = _agentsCache.GetAgent(MenuControlAgentName);

                _textControlAgent = _genericAppAgent.TextControlAgent;

                WindowActivityMonitor.EvtFocusChanged += WindowActivityMonitor_EvtFocusChanged;

                getKeyboardActuator();

                WindowActivityMonitor.GetActiveWindow();
            }

            return(true);
        }
Exemple #2
0
 /// <summary>
 /// Call this function to raise events to indicated that something changed
 /// in the text window either due to editing or due to cursor movement. Event
 /// raised is asynchronous
 /// </summary>
 /// <param name="textInterface">text agent</param>
 protected void triggerTextChangedAsync(ITextControlAgent textInterface)
 {
     if (EvtTextChanged != null)
     {
         EvtTextChanged.BeginInvoke(textInterface, new TextChangedEventArgs(textInterface), null, null);
     }
 }
Exemple #3
0
 /// <summary>
 /// Call this function to raise events to indicated that something changed
 /// in the text window either due to editing or due to cursor movement. Event
 /// raised is synchronous
 /// </summary>
 /// <param name="textInterface">text agent</param>
 protected void triggerTextChanged(ITextControlAgent textInterface)
 {
     if (EvtTextChanged != null)
     {
         EvtTextChanged(this, new TextChangedEventArgs(textInterface));
     }
 }
Exemple #4
0
        /// <summary>
        /// Dispose resources
        /// </summary>
        /// <param name="disposing">Disposed yet?</param>
        private void dispose(bool disposing)
        {
            if (!_disposed)
            {
                _textControlAgent = null;
            }

            _disposed = true;
        }
Exemple #5
0
        /// <summary>
        /// Activates a functional agent. The caller should to an 'await'
        /// on this to wait for it to complete.  This is because some
        /// functional agents return data and the caller has to wait
        /// for the functional agent to exit so it can get the data. Eg
        /// FileBrowser agent that returns a filename
        /// </summary>
        /// <param name="caller">The calling agent (can be null)</param>
        /// <param name="agent">Functional agent to activate</param>
        /// <returns>the task to wait on</returns>
        public async Task ActivateAgent(IApplicationAgent caller, IFunctionalAgent agent)
        {
            lock (_syncActivateAgent)
            {
                if (_currentAgent != null && _currentAgent != agent)
                {
                    if (caller == null && !_currentAgent.QueryAgentSwitch(agent))
                    {
                        return;
                    }

                    _currentAgent.OnFocusLost();
                }

                if (caller != null)
                {
                    agent.Parent = caller;
                    caller.OnPause();
                }

                _textControlAgent = agent.TextControlAgent;

                setAgent(agent);
            }

            Log.Debug("Calling activateAgent: " + agent.Name);
            await activateAgent(agent);

            CompletionCode exitCode = agent.ExitCode;

            Log.Debug("Returned from activateAgent: " + agent.Name);
            setAgent(null);

            if (agent.ExitCommand != null)
            {
                if (agent.ExitCommand.ContextSwitch)
                {
                    Context.AppPanelManager.CloseCurrentPanel();
                }

                RunCommandDispatcher.Dispatch(agent.ExitCommand.Command);
            }
            else if (exitCode == CompletionCode.ContextSwitch)
            {
                Context.AppPanelManager.CloseCurrentPanel();
                EnumWindows.RestoreFocusToTopWindow();
                WindowActivityMonitor.GetActiveWindow();
            }
            else
            {
                PausePanelChangeRequests();
                EnumWindows.RestoreFocusToTopWindow();
                ResumePanelChangeRequests(false);
            }
        }
Exemple #6
0
        /// <summary>
        /// Sets the text control agent to the specifed one, null agent
        /// if NULL
        /// </summary>
        /// <param name="textInterface">Text interface to set</param>
        protected void setTextInterface(TextControlAgentBase textInterface = null)
        {
            if (_textInterface != null)
            {
                Log.Debug("Disposing " + _textInterface.GetType().Name);
                _textInterface.Dispose();
            }

            Log.Debug("Setting textinterface to " + ((textInterface != null) ? textInterface.GetType().Name : "null"));

            _textInterface = textInterface ?? _nullTextInterface;
            AgentManager.Instance.TextControlAgent = _textInterface;
        }
Exemple #7
0
 /// <summary>
 /// Initializes a new instance of the class.
 /// </summary>
 /// <param name="textControlAgent">currently active text control agent object</param>
 internal AgentContext(ITextControlAgent textControlAgent)
 {
     _textControlAgent = textControlAgent;
 }
Exemple #8
0
 /// <summary>
 /// Initializes a new instance of the class.
 /// </summary>
 /// <param name="textAgent">The objet that triggered the event</param>
 public TextChangedEventArgs(ITextControlAgent textAgent)
 {
     TextInterface = textAgent;
 }
Exemple #9
0
 /// <summary>
 /// Call this function to raise events to indicated that something changed
 /// in the text window either due to editing or due to cursor movement. Event
 /// raised is asynchronous
 /// </summary>
 /// <param name="textInterface">text agent</param>
 protected void triggerTextChangedAsync(ITextControlAgent textInterface)
 {
     if (EvtTextChanged != null)
     {
         EvtTextChanged.BeginInvoke(this, new TextChangedEventArgs(textInterface), null, null);
     }
 }
Exemple #10
0
 /// <summary>
 /// Call this function to raise events to indicated that something changed
 /// in the text window either due to editing or due to cursor movement. Event
 /// raised is synchronous
 /// </summary>
 /// <param name="textInterface">text agent</param>
 protected void triggerTextChanged(ITextControlAgent textInterface)
 {
     if (EvtTextChanged != null)
     {
         EvtTextChanged(this, new TextChangedEventArgs(textInterface));
     }
 }
Exemple #11
0
        /// <summary>
        /// Sets the text control agent to the specifed one, null agent
        /// if NULL
        /// </summary>
        /// <param name="textInterface">Text interface to set</param>
        protected void setTextInterface(TextControlAgentBase textInterface = null)
        {
            if (_textInterface != null)
            {
                Log.Debug("Disposing " + _textInterface.GetType().Name);
                _textInterface.Dispose();
            }

            Log.Debug("Setting textinterface to " + ((textInterface != null) ? textInterface.GetType().Name : "null"));

            _textInterface = textInterface ?? _nullTextInterface;
            AgentManager.Instance.TextControlAgent = _textInterface;
        }
Exemple #12
0
 /// <summary>
 /// Sets the current agent to the specified one and raises
 /// a text changed event.
 /// </summary>
 /// <param name="agent">agent to set as the current agent</param>
 private void updateCurrentAgentAndNotify(IApplicationAgent agent)
 {
     _textControlAgent = agent.TextControlAgent;
     setAgent(agent);
     notifyTextChanged(_textControlAgent);
 }
Exemple #13
0
 /// <summary>
 /// Sets the current agent to the specified one and raises
 /// a text changed event.
 /// </summary>
 /// <param name="agent">agent to set as the current agent</param>
 private void updateCurrentAgentAndNotify(IApplicationAgent agent)
 {
     _textControlAgent = agent.TextControlAgent;
     setAgent(agent);
     notifyTextChanged(_textControlAgent);
 }
Exemple #14
0
        /// <summary>
        /// Notifies that something changed in the active text window -
        /// either the text changed or the caret moved. This is a tricky
        /// thing to handle The event can be raised while this function
        /// is still executing due to a previous event.  We must guard
        /// against. Subsequent calls must be blocked until the function
        /// has exited.
        /// </summary>
        /// <param name="textInterface">The source of the event</param>
        /// <returns>true if successful</returns>
        private bool notifyTextChanged(ITextControlAgent textInterface)
        {
            uint threadId = GetCurrentThreadId();

            Log.Debug("Entered notifyTextChanged: " + threadId);

            // Use the semaphore to see if this is blocked
            if (TextChangedNotifications.OnHold())
            {
                Log.Debug("NotificationsOnHold.  Exit ThreadID: " + threadId);
                return(false);
            }

            // try to acquire a lock
            if (!tryLock(_syncTextChangeNotifyObj))
            {
                Log.Debug("_lock is true. returning on thread : " + threadId);
                return(false);
            }

            try
            {
                // this is required as _syncTextChangeNotifyObj lock will
                // only work if different threads are trying to enter.
                // The following statement is required to block against
                // the same thread trying to re-enter the function
                if (_notifyTextChangedLock)
                {
                    Log.Debug("REENTRANCY DETECTED. RETURNING");
                    return(true);
                }

                if (textInterface != _textControlAgent)
                {
                    Log.Debug("event source is not the current agent. returning...");
                    return(false);
                }

                _notifyTextChangedLock = true;

                try
                {
                    if (EvtTextChanged != null)
                    {
                        Log.Debug("Calling EvtTextChanged");
                        EvtTextChanged(this, EventArgs.Empty);
                        Log.Debug("Returned from EvtTextChanged");
                    }
                    else
                    {
                        Log.Debug("EvtTextChanged is null");
                    }
                }
                catch (Exception ex)
                {
                    Log.Debug(ex.ToString());
                }

                _notifyTextChangedLock = false;

                Log.Debug("Exit End of function ThreadID: " + threadId);
            }
            catch (Exception ex)
            {
                Log.Debug(ex.ToString());
            }
            finally
            {
                release(_syncTextChangeNotifyObj);
            }

            Log.Debug("Returning");
            return(true);
        }
Exemple #15
0
 /// <summary>
 /// Initializes a new instance of the class.
 /// </summary>
 /// <param name="textAgent">The objet that triggered the event</param>
 public TextChangedEventArgs(ITextControlAgent textAgent)
 {
     TextInterface = textAgent;
 }
Exemple #16
0
        /// <summary>
        /// Activates an application agent depending on the context.
        /// The monitorInfo parameter has all the information to make
        /// this decision. Depending on the active foreground process,
        /// the appropriate agent is activated.  if there is no dedicated
        /// agent for the process, the generic agent is used.
        /// If a dialog the foreground window, the dialog agent is activated.
        /// If a menu has been activated, the menu agent is activated
        /// </summary>
        /// <param name="monitorInfo">Foreground window/process info</param>
        private void activateAppAgent(WindowActivityMonitorInfo monitorInfo)
        {
            if (_inActivateAppAgent)
            {
                Log.Debug("Already inside. returning");
                return;
            }

            Log.Debug("Before syncsetagent");
            lock (_syncActivateAgent)
            {
                _inActivateAppAgent = true;
                Log.Debug("After syncsetagent");
                try
                {
                    bool handled = false;

                    Log.Debug(monitorInfo.ToString());

                    // did a request for displaying the contextual
                    // menu come in?  If so handle it.

                    bool getContextMenu = _getContextMenu;

                    Log.Debug("getContextMenu: " + getContextMenu);

                    _getContextMenu = false;

                    String processName = monitorInfo.FgProcess.ProcessName;

                    // first check if there is an ad-hoc agent, if so,
                    // activate it
                    Log.Debug("Looking for adhoc agent for " + monitorInfo.FgHwnd);
                    IApplicationAgent agent = _agentsCache.GetAgent(monitorInfo.FgHwnd);
                    if (agent == null)
                    {
                        // check if a dialog or menu is active
                        Log.Debug("Adhoc agent not present for " + monitorInfo.FgHwnd);

                        if (EnableContextualMenusForDialogs &&
                            (String.Compare(processName, _currentProcessName, true) != 0) &&
                            isDialog(monitorInfo))
                        {
                            Log.Debug("Fg window is a dialog.  Setting agent to dialog agent");

                            agent = _dialogAgent;
                        }
                        else if (EnableContextualMenusForMenus && isMenu(monitorInfo))
                        {
                            Log.Debug("Fg window is a menu.  Setting agent to menu agent");
                            agent = _menuControlAgent;
                        }
                        else if (Windows.IsMinimized(monitorInfo.FgHwnd))
                        {
                            Log.Debug("Window is minimized. Use generic agent");
                            agent = _genericAppAgent;
                        }
                        else
                        {
                            // check if there is a dedicated agent for this process
                            Log.Debug("Getting agent for " + processName);
                            agent = _agentsCache.GetAgent(monitorInfo.FgProcess);
                        }
                    }
                    else
                    {
                        Log.Debug("Adhoc agent IS present for " + monitorInfo.FgHwnd);
                    }

                    Log.Debug("Current agent: " + ((_currentAgent != null) ?
                                                    _currentAgent.Name : "null") +
                                                    ", agent:  " + ((agent != null) ? agent.Name : "null"));

                    // if there is an agent switch, query the current agent
                    // if it is OK to switch. Some agents may not allow
                    // the switch
                    if (_currentAgent != null && _currentAgent != agent)
                    {
                        bool allowSwitch = _currentAgent.QueryAgentSwitch(agent);
                        Log.Debug("CurrentAgent is " + _currentAgent.Name + ", queryAgentSwitch: " + allowSwitch);
                        if (!allowSwitch)
                        {
                            _currentAgent.OnFocusChanged(monitorInfo, ref handled);
                            _textControlAgent = _currentAgent.TextControlAgent;
                            return;
                        }

                        _currentAgent.OnFocusLost();
                    }

                    // if there was a request to display
                    // contextual menu, do so
                    if (getContextMenu)
                    {
                        if (agent == null)
                        {
                            agent = _genericAppAgent;
                        }

                        Log.Debug("agent : " + agent.Name);
                        agent.OnContextMenuRequest(monitorInfo);
                        return;
                    }

                    // Inform the new agent about the current
                    // focused element so it can display the scanner that
                    // is appropriated for the context.
                    if (agent != null)
                    {
                        Log.Debug("Trying agent " + agent.Name);
                        agent.OnFocusChanged(monitorInfo, ref handled);
                        Log.Debug("Returned from agent.OnFOcus");
                    }

                    // If we have reached here, it means there was no
                    // agent. Just use the default generic agent. See
                    // if it will handle it
                    if (!handled)
                    {
                        Log.Debug("Did not find agent for " + processName + ". trying generic app agent");
                        Log.Debug("_genericAppAgent is " + ((_genericAppAgent != null) ? "not null" : "null"));
                        agent = _genericAppAgent;
                        try
                        {
                            agent.OnFocusChanged(monitorInfo, ref handled);
                        }
                        catch (Exception ex)
                        {
                            Log.Exception(ex);
                        }
                    }

                    // even the generic agent refused.  Use the null agent
                    // as the last resort
                    Log.Debug("handled " + handled);
                    if (!handled)
                    {
                        Log.Debug("generic app agent refused. Using null agent");
                        agent = _nullAgent;
                        agent.OnFocusChanged(monitorInfo, ref handled);
                    }

                    updateCurrentAgentAndNotify(agent);
                }
                catch (Exception ex)
                {
                    Log.Debug(ex.ToString());
                }
                finally
                {
                    _inActivateAppAgent = false;
                }
            }

            Log.Debug("Return");
        }
Exemple #17
0
        public bool Init(IEnumerable<String> extensionDirs)
        {
            if (_agentsCache == null)
            {
                _agentsCache = new AgentsCache();
                _agentsCache.EvtAgentAdded += _agentsCache_EvtAgentAdded;
                _agentsCache.Init(extensionDirs);

                _genericAppAgent = _agentsCache.GetAgent(GenericAppAgentName);
                if (_genericAppAgent == null)
                {
                    _agentsCache.AddAgentByType(typeof(UnsupportedAppAgent));
                    _genericAppAgent = _agentsCache.GetAgent(GenericAppAgentName);
                }

                _agentsCache.AddAgentByType(typeof(NullAgent));
                _nullAgent = _agentsCache.GetAgent(NullAgentName);

                _dialogAgent = _agentsCache.GetAgent(DialogControlAgentName);
                _menuControlAgent = _agentsCache.GetAgent(MenuControlAgentName);

                _textControlAgent = _genericAppAgent.TextControlAgent;

                WindowActivityMonitor.EvtFocusChanged += WindowActivityMonitor_EvtFocusChanged;

                //WindowActivityMonitor.GetActiveWindow();
            }

            return true;
        }
Exemple #18
0
        /// <summary>
        /// Activates a functional agent. The caller should to an 'await'
        /// on this to wait for it to complete.  This is because some
        /// functional agents return data and the caller has to wait
        /// for the functional agent to exit so it can get the data. Eg
        /// FileBrowser agent that returns a filename
        /// </summary>
        /// <param name="caller">The calling agent (can be null)</param>
        /// <param name="agent">Functional agent to activate</param>
        /// <returns>the task to wait on</returns>
        public async Task ActivateAgent(IApplicationAgent caller, IFunctionalAgent agent)
        {
            lock (_syncActivateAgent)
            {
                if (_currentAgent != null && _currentAgent != agent)
                {
                    if (caller == null && !_currentAgent.QueryAgentSwitch(agent))
                    {
                        return;
                    }

                    _currentAgent.OnFocusLost();
                }

                if (caller != null)
                {
                    agent.Parent = caller;
                    caller.OnPause();
                }

                _textControlAgent = agent.TextControlAgent;

                setAgent(agent);
            }

            Log.Debug("Calling activateAgent: " + agent.Name);
            await activateAgent(agent);

            CompletionCode exitCode = agent.ExitCode;

            Log.Debug("Returned from activateAgent: " + agent.Name);
            setAgent(null);

            if (agent.ExitCommand != null)
            {
                if (agent.ExitCommand.ContextSwitch)
                {
                    Context.AppPanelManager.CloseCurrentPanel();
                }

                RunCommandDispatcher.Dispatch(agent.ExitCommand.Command);
            }
            else if (exitCode == CompletionCode.ContextSwitch)
            {
                //Context.AppPanelManager.CloseCurrentPanel();
                Context.AppPanelManager.ClearStack();
                EnumWindows.RestoreFocusToTopWindow();
                WindowActivityMonitor.GetActiveWindow();
            }
            else
            {
                PausePanelChangeRequests();
                EnumWindows.RestoreFocusToTopWindow();
                ResumePanelChangeRequests(false);
            }
        }
Exemple #19
0
 /// <summary>
 /// Initializes a new instance of the class.
 /// </summary>
 /// <param name="textControlAgent">currently active text control agent object</param>
 internal AgentContext(ITextControlAgent textControlAgent)
 {
     _textControlAgent = textControlAgent;
 }
Exemple #20
0
        /// <summary>
        /// Activates an application agent depending on the context.
        /// The monitorInfo parameter has all the information to make
        /// this decision. Depending on the active foreground process,
        /// the appropriate agent is activated.  if there is no dedicated
        /// agent for the process, the generic agent is used.
        /// If a dialog the foreground window, the dialog agent is activated.
        /// If a menu has been activated, the menu agent is activated
        /// </summary>
        /// <param name="monitorInfo">Foreground window/process info</param>
        private void activateAppAgent(WindowActivityMonitorInfo monitorInfo)
        {
            if (_inActivateAppAgent)
            {
                Log.Debug("Already inside. returning");
                return;
            }

            Log.Debug("Before syncsetagent");
            lock (_syncActivateAgent)
            {
                _inActivateAppAgent = true;
                Log.Debug("After syncsetagent");
                try
                {
                    bool handled = false;

                    Log.Debug(monitorInfo.ToString());

                    // did a request for displaying the contextual
                    // menu come in?  If so handle it.

                    bool getContextMenu = _getContextMenu;

                    Log.Debug("getContextMenu: " + getContextMenu);

                    _getContextMenu = false;

                    String processName = monitorInfo.FgProcess.ProcessName;

                    // first check if there is an ad-hoc agent, if so,
                    // activate it
                    Log.Debug("Looking for adhoc agent for " + monitorInfo.FgHwnd);
                    IApplicationAgent agent = _agentsCache.GetAgent(monitorInfo.FgHwnd);
                    if (agent == null)
                    {
                        // check if a dialog or menu is active
                        Log.Debug("Adhoc agent not present for " + monitorInfo.FgHwnd);

                        if (EnableContextualMenusForDialogs &&
                            (String.Compare(processName, _currentProcessName, true) != 0) &&
                            isDialog(monitorInfo))
                        {
                            Log.Debug("Fg window is a dialog.  Setting agent to dialog agent");

                            agent = _dialogAgent;
                        }
                        else if (EnableContextualMenusForMenus && isMenu(monitorInfo))
                        {
                            Log.Debug("Fg window is a menu.  Setting agent to menu agent");
                            agent = _menuControlAgent;
                        }
                        else
                        {
                            // check if there is a dedicated agent for
                            // this process
                            Log.Debug("Getting agent for " + processName);
                            agent = _agentsCache.GetAgent(monitorInfo.FgProcess);
                        }
                    }
                    else
                    {
                        Log.Debug("Adhoc agent IS present for " + monitorInfo.FgHwnd);
                    }

                    Log.Debug("Current agent: " + ((_currentAgent != null) ?
                                                   _currentAgent.Name : "null") +
                              ", agent:  " + ((agent != null) ? agent.Name : "null"));

                    // if there is an agent switch, query the current agent
                    // if it is OK to switch. Some agents may not allow
                    // the switch
                    if (_currentAgent != null && _currentAgent != agent)
                    {
                        bool allowSwitch = _currentAgent.QueryAgentSwitch(agent);
                        Log.Debug("CurrentAgent is " + _currentAgent.Name + ", queryAgentSwitch: " + allowSwitch);
                        if (!allowSwitch)
                        {
                            _currentAgent.OnFocusChanged(monitorInfo, ref handled);
                            _textControlAgent = _currentAgent.TextControlAgent;
                            return;
                        }

                        _currentAgent.OnFocusLost();
                    }

                    // if there was a request to display
                    // contextual menu, do so
                    if (getContextMenu)
                    {
                        if (agent == null)
                        {
                            agent = _genericAppAgent;
                        }

                        Log.Debug("agent : " + agent.Name);
                        agent.OnContextMenuRequest(monitorInfo);
                        return;
                    }

                    // Inform the new agent about the current
                    // focused element so it can display the scanner that
                    // is appropriated for the context.
                    if (agent != null)
                    {
                        Log.Debug("Trying agent " + agent.Name);
                        agent.OnFocusChanged(monitorInfo, ref handled);
                        Log.Debug("Returned from agent.OnFOcus");
                    }

                    // If we have reached here, it means there was no
                    // agent. Just use the default generic agent. See
                    // if it will handle it
                    if (!handled)
                    {
                        Log.Debug("Did not find agent for " + processName + ". trying generic app agent");
                        Log.Debug("_genericAppAgent is " + ((_genericAppAgent != null) ? "not null" : "null"));
                        agent = _genericAppAgent;
                        try
                        {
                            agent.OnFocusChanged(monitorInfo, ref handled);
                        }
                        catch (Exception ex)
                        {
                            Log.Exception(ex);
                        }
                    }

                    // even the generic agent refused.  Use the null agent
                    // as the last resort
                    Log.Debug("handled " + handled);
                    if (!handled)
                    {
                        Log.Debug("generic app agent refused. Using null agent");
                        agent = _nullAgent;
                        agent.OnFocusChanged(monitorInfo, ref handled);
                    }

                    updateCurrentAgentAndNotify(agent);
                }
                catch (Exception ex)
                {
                    Log.Debug(ex.ToString());
                }
                finally
                {
                    _inActivateAppAgent = false;
                }
            }

            Log.Debug("Return");
        }
Exemple #21
0
        /// <summary>
        /// Dispose resources
        /// </summary>
        /// <param name="disposing">Disposed yet?</param>
        private void dispose(bool disposing)
        {
            if (!_disposed)
            {
                _textControlAgent = null;
            }

            _disposed = true;
        }
Exemple #22
0
        /// <summary>
        /// Notifies that something changed in the active text window -
        /// either the text changed or the caret moved. This is a tricky
        /// thing to handle The event can be raised while this function
        /// is still executing due to a previous event.  We must guard
        /// against. Subsequent calls must be blocked until the function
        /// has exited.
        /// </summary>
        /// <param name="textInterface">The source of the event</param>
        /// <returns>true if successful</returns>
        private bool notifyTextChanged(ITextControlAgent textInterface)
        {
            uint threadId = GetCurrentThreadId();
            Log.Debug("Entered notifyTextChanged: " + threadId);

            // Use the semaphore to see if this is blocked
            if (TextChangedNotifications.OnHold())
            {
                Log.Debug("NotificationsOnHold.  Exit ThreadID: " + threadId);
                return false;
            }

            // try to acquire a lock
            if (!tryLock(_syncTextChangeNotifyObj))
            {
                Log.Debug("_lock is true. returning on thread : " + threadId);
                return false;
            }

            try
            {
                // this is required as _syncTextChangeNotifyObj lock will
                // only work if different threads are trying to enter.
                // The following statement is required to block against
                // the same thread trying to re-enter the function
                if (_notifyTextChangedLock)
                {
                    Log.Debug("REENTRANCY DETECTED. RETURNING");
                    return true;
                }

                if (textInterface != _textControlAgent)
                {
                    Log.Debug("event source is not the current agent. returning...");
                    return false;
                }

                _notifyTextChangedLock = true;

                try
                {
                    if (EvtTextChanged != null)
                    {
                        Log.Debug("Calling EvtTextChanged");
                        EvtTextChanged(this, EventArgs.Empty);
                        Log.Debug("Returned from EvtTextChanged");
                    }
                    else
                    {
                        Log.Debug("EvtTextChanged is null");
                    }
                }
                catch (Exception ex)
                {
                    Log.Debug(ex.ToString());
                }

                _notifyTextChangedLock = false;

                Log.Debug("Exit End of function ThreadID: " + threadId);
            }
            catch (Exception ex)
            {
                Log.Debug(ex.ToString());
            }
            finally
            {
                release(_syncTextChangeNotifyObj);
            }

            Log.Debug("Returning");
            return true;
        }