/// <summary>
 /// Initializes a new instance of the <see cref="ScreenDefintion"/> class.
 /// </summary>
 /// <param name="fileName">
 /// The file name.
 /// </param>
 /// <param name="name">
 /// The name.
 /// </param>
 /// <param name="expression">
 /// The expression.
 /// </param>
 /// <param name="definition">
 /// The definition.
 /// </param>
 public ScreenDefintion(string fileName, string name, string expression, SBString definition)
     : base(fileName, name, SourceDefinition.Definition, expression)
 {
     this.FieldDescriptions = new ObservableCollection<FieldDefinition>();
     this.ParseScreenDefinition(definition);
     // I need to read the .GUI definition to get the processes associated with buttons that do not have a FK assignment.
     SBFile.ReadDictionaryItem(fileName, name + ".GUI", new object(), this.GuiItemReadCompleted);
 }
 /// <summary>
 /// The send response.
 /// </summary>
 /// <param name="response">
 /// The response.
 /// </param>
 public static void SendResponse(SBString response)
 {
     SBPlus.Current.SetInputState(SBInputState.Dormant, "Sending response to SB/XA server.");
     SBPlusClient.LogInformation(
         "Responded to message." + response.GetStandardString() + "(" + Convert.ToString(DateTime.Now.Millisecond) + ")");
     try
     {
         SBPlus.Current.SBPlusRuntime.RespondToLastMessage(response);
     }
     catch (SBApplicationException exception)
     {
         if (exception.ErrorCode.Equals("CS0049"))
         {
             SBDisplay.Display(SBDisplayTypes.Fatal, "An Encoding error occurred handing a message", exception);
             SBPlus.Current.SetInputState(SBInputState.WaitingForInput, "Encoding error.");
         }
     }
     catch (Exception exception2)
     {
         SBPlusClient.LogError("An error occurred handing a message.", exception2);
         SBPlus.Current.SetInputState(SBInputState.WaitingForInput, "An error occurred handing a message.");
     }
 }
        /// <summary>
        /// The upload.
        /// </summary>
        /// <param name="sourceFileName">
        /// The source file name.
        /// </param>
        /// <param name="targetFileName">
        /// The target file name.
        /// </param>
        /// <param name="itemId">
        /// The item id.
        /// </param>
        /// <param name="options">
        /// The options.
        /// </param>
        /// <param name="uploadCompleted">
        /// The upload completed.
        /// </param>
        public static void Upload(
            string sourceFileName,
            string targetFileName,
            string itemId,
            string options,
            SubroutineCallCompleted uploadCompleted)
        {
            // SUBROUTINE TU.UPLOAD(DOS.FILE.NAME, F.RXFILE, ITEMID, OPTIONS, DESCRIPTION, STATUS.REC)
            // MESSAGE = DOS.FILE.NAME : @AM : @AM : FILE.NAME : @AM : ITEMID
            // FT.OPTIONS = OPTIONS : "O"
            // DATA = ""
            // CALL SB.FT.MASTER(3, MESSAGE, DATA, FT.OPTIONS, STATUS.REC)
            if (!File.Exists(sourceFileName))
            {
                return;
            }
            var message = new SBString();
            message.SBInsert(1, sourceFileName);
            message.SBInsert(3, targetFileName);
            message.SBInsert(4, itemId);

            SbProcessHandler.CallSubroutine(
                uploadCompleted,
                "SB.FT.MASTER",
                new[] { new SBString("3"), message, new SBString(), new SBString(options + "O"), new SBString() },
                new object[] { sourceFileName, targetFileName, itemId, options });

            /*
            SbProcessHandler.CallSubroutine(
                "SB.FT.MASTER",
                5,
                new[] { new SBString("3"), message, new SBString(), new SBString(options + "O"), new SBString() },
                new object[] { sourceFileName, targetFileName, itemId, options },
                uploadCompleted);
            */
        }
        /// <summary>
        /// The gui item read completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private void GuiItemReadCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            try
            {
                if (parameters[5].Count != 1 || !parameters[5].Value.Equals("0") || parameters[3].IsNullOrEmpty()
                    || !parameters[3].Extract(1).Value.Equals("SCREEN.GUIDEFS"))
                {
                    // item not found.
                    return;
                }

                const int AttributeList = 10;
                const int ObjectIndex = 12; // off set by 15, 0 based

                // Loop through the objects and look for a button. I know it is a button because it has a pbclass in the third attribute of the object.
                var record = parameters[3];
                var attributeList = record.Extract(AttributeList).CopyToStringCollection();
                var indexOfPbClass = Convert.ToString(attributeList.IndexOf("pbclass") + 2);
                var indexOfUserData = Convert.ToString(attributeList.IndexOf("user_data") + 1);
                var indexOfString = Convert.ToString(attributeList.IndexOf("string") + 1);
                var noAttributes = record.Dcount();
                for (int aNo = 15; aNo < noAttributes - 4; aNo += 4)
                {
                    var attributes = record.Extract(aNo + 2).CopyToStringCollection();
                    if (attributes.Contains(indexOfPbClass))
                    {
                        this.ProcessButton(indexOfUserData, indexOfString, attributes, record.Extract(aNo + 3).CopyToStringCollection());
                    }
                }
            }
            catch (Exception exception)
            {
                CustomLogger.LogException(exception, "There was a problem processing the .GUI item for " + this.Name);
            }
        }
        /// <summary>
        /// The read control record completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private void ReadControlRecordCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            this.SetIsLoading(-1);

            if (parameters[5].Count != 1 || !parameters[5].Value.Equals("0"))
            {
                // Error
                this.LastProcessReadError = string.Format("Failed to read {0} from {1}.", parameters[1].Value, parameters[0].Value);
                return;
            }

            var record = parameters[3];
            this.globalProcessFile = record.Extract(6, 2).Value;
            this.globalMenuFile = record.Extract(6, 3).Value;
        }
        /// <summary>
        /// The read basic program completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private void ReadBasicProgramCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            this.SetIsLoading(-1);

            if (parameters[5].Count != 1 || !parameters[5].Value.Equals("0"))
            {
                // Error
                this.LastProcessReadError = string.Format("Failed to read {0} from {1}.", parameters[1].Value, parameters[0].Value);
                return;
            }

            var basicProgramDescription = ((object[])userState)[0] as BasicProgramDescription;
            if (basicProgramDescription == null || IsExcludeFile(basicProgramDescription.FileName))
            {
                return;
            }

            this.FindCallsInBasicProgram(parameters[3], basicProgramDescription);
        }
        /// <summary>
        /// This method will parse out the definition and figure out the type of definition.
        /// </summary>
        /// <param name="processFileName">
        /// The name of the file that contains the process.
        /// </param>
        /// <param name="pName">
        /// The name of the definition.
        /// </param>
        /// <param name="defn">
        /// The definition description.
        /// </param>
        /// <param name="processLoadState">
        /// The information about the definition definition passed from the calling routine.
        /// </param>
        /// <returns>
        /// The <see cref="DefinitionDescription"/>.
        /// </returns>
        private DefinitionDescription CreateProcessDescription(
            string processFileName,
            string pName,
            SBString defn,
            ProcessLoadState processLoadState)
        {
            DefinitionDescription processDescription;
            if (defn == null)
            {
                if (processLoadState.Source == SourceDefinition.Button)
                {
            /*
                    processDescription = new ButtonDefinitionDescription()
                                             {
                                                 Description = processLoadState.HookPoint,
                                                 pName,
                                                 Source
                                             };
            */
                    processDescription = new ButtonDefinitionDescription(
                        processFileName,
                        pName,
                        SourceDefinition.Process,
                        processLoadState.Expression);
                }
                else
                {
                    processDescription = new DefinitionDescription(
                                                processFileName,
                                                pName,
                                                SourceDefinition.Process,
                                                processLoadState.Expression)
                                                {
                                                    IsError = true
                                                };

                }
                return processDescription;
            }

            switch (defn.Extract(1).Value)
            {
                case "I":
                    processDescription = new InputDefinitionDescription(processFileName, pName, processLoadState.Expression, defn);
                    break;
                case "O":
                    processDescription = new OutputDefinitionDescription(processFileName, pName, processLoadState.Expression, defn);
                    break;
                case "P":
                    processDescription = this.CreateParagraphDescription(processFileName, pName, processLoadState.Expression, defn);
                    break;
                case "SCREEN":
                    processDescription = new ScreenDefintion(processFileName, pName, string.Empty, defn);
                    break;
                case "F":
                    processDescription = new FileUpdateDefinitionDescription(processFileName, pName, string.Empty, defn);
                    break;
                case "M":
                    processDescription = new MenuDefinitionDescription(processFileName, pName, string.Empty, defn);
                    break;
                case "S":
                    processDescription = new SelectionProcessDescription(processFileName, pName, SourceDefinition.Process, processLoadState.SysId, defn);
                    break;
                default:
                    processDescription = new DefinitionDescription(
                        processFileName,
                        pName,
                        SourceDefinition.Process,
                        processLoadState.Expression);
                    break;
            }

            return processDescription;
        }
        /// <summary>
        /// The add process to collection.
        /// </summary>
        /// <param name="processFileName">
        /// The process file name.
        /// </param>
        /// <param name="pName">
        /// The p name.
        /// </param>
        /// <param name="defn">
        /// The defn.
        /// </param>
        /// <param name="processLoadState">
        /// The process load state.
        /// </param>
        /// <param name="isError">
        /// The is error.
        /// </param>
        private void AddProcessToCollection(
            string processFileName,
            string pName,
            SBString defn,
            ProcessLoadState processLoadState = null,
            bool isError = false)
        {
            if (DebugWindowManager.DebugConsoleWindow == null || processLoadState == null)
            {
                return;
            }

            if (Thread.CurrentThread == DebugWindowManager.DebugConsoleWindow.Dispatcher.Thread)
            {
                this.DoAddProcessToCollection(processFileName, pName, defn, processLoadState, isError);
            }
            else
            {

            JobManager.RunInDispatcherThread(
                DebugWindowManager.DebugConsoleWindow.Dispatcher,
                DispatcherPriority.Normal,
                ()=> this.DoAddProcessToCollection(processFileName, pName, defn, processLoadState, isError));
            }
        }
Example #9
0
 /// <summary>
 /// Writes the record.
 /// </summary>
 /// <remarks>
 /// FILE.NAME = PARAM1&lt;1&gt;
 ///     ID = PARAM1&lt;2&gt;
 ///     ATTR = PARAM1&lt;3&gt;
 ///     MODE = PARAM1&lt;4&gt;
 ///     REC = PARAM2
 /// </remarks>
 /// <param name="writeCompleted">
 /// The write completed.
 /// </param>
 /// <param name="itemInfo">
 /// The item information.
 /// </param>
 /// <param name="record">
 /// The record.
 /// </param>
 internal static void WriteRecord(SubroutineCallCompleted writeCompleted, SBString itemInfo, SBString record)
 {
     SbProcessHandler.CallSubroutine(
         writeCompleted,
         "XUI.DEBUG",
         new[] { new SBString("7"), itemInfo, record, new SBString(), new SBString("0"), new SBString() },
         new object[0]);
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="MenuDefinitionDescription"/> class.
 /// </summary>
 /// <param name="fileName">
 /// The file name.
 /// </param>
 /// <param name="name">
 /// The name.
 /// </param>
 /// <param name="expression">
 /// The expression.
 /// </param>
 /// <param name="definition">
 /// The definition.
 /// </param>
 public MenuDefinitionDescription(string fileName, string name, string expression, SBString definition)
     : base(fileName, name, SourceDefinition.Definition, expression)
 {
     this.ParseDefinition(definition);
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="ScreenProcessDescription"/> class.
        /// </summary>
        /// <param name="fileName">
        /// The name of the file that contains the screen.
        /// </param>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <param name="expression">
        /// The expression.
        /// </param>
        /// <param name="definition">
        /// The definition.
        /// </param>
        public ScreenProcessDescription(string fileName, string name, string expression, SBString definition)
            : this(fileName, name, expression)
        {
            if (!string.IsNullOrWhiteSpace(definition.Extract(5, 1).Value))
            {
                this.Dictionary = definition.Extract(5, 1).Value;
                this.ProcessCollection.Add(
                    new ProcessCall { Description = "Dictionary", ProcessDescription = new DictionaryDescription(this.Dictionary) });
            }

            if (!string.IsNullOrWhiteSpace(definition.Extract(6).Value))
            {
                this.ScreenName = definition.Extract(6).Value;
                DebugViewModel.Instance.ProcessAnalysisViewModel.LoadScreen(this.ScreenName, this.Dictionary, this, "Screen");

                // Now check if there are linked screens. To do this see if the last character is numeric. If it is go back until you find the first non-numeric. Now
                // we have a starting point, loop adding 1 untill there is no hit.
                int startIndex = this.ScreenName.Length - 1;
                while (SBXA.Shared.Utilities.IsNumber(this.ScreenName.Substring(startIndex)))
                {
                    startIndex++;
                }

                startIndex--; // because it would have been incremented one beyond.
                if (!string.IsNullOrEmpty(this.ScreenName.Substring(startIndex))
                    && Utilities.IsNumber(this.ScreenName.Substring(startIndex)))
                {
                    var nextScreen = Convert.ToInt16(this.ScreenName.Substring(startIndex)) + 1;
                    var prefix = this.ScreenName.Substring(0, startIndex);
                    DebugViewModel.Instance.ProcessAnalysisViewModel.SetIsLoading(1);
                    // I have a starting point, now read the definition.
                    SBFile.ReadDictionaryItem(
                        this.Dictionary,
                        prefix + nextScreen,
                        new object[] { nextScreen, prefix, this.Dictionary },
                        this.ReadLinkedScreenCompleted);
                }
            }

            // load the list of processes
            if (!string.IsNullOrWhiteSpace(definition.Extract(8, 1).Value))
            {
                DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                    SourceDefinition.Screen,
                    SourceDefinition.Process,
                    definition.Extract(8, 1).Value,
                    this,
                    "Before");
            }

            if (!string.IsNullOrWhiteSpace(definition.Extract(8, 2).Value))
            {
                DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                    SourceDefinition.Screen,
                    SourceDefinition.Process,
                    definition.Extract(8, 2).Value,
                    this,
                    "After");
            }

            if (!string.IsNullOrWhiteSpace(definition.Extract(8, 7).Value))
            {
                DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                    SourceDefinition.Screen,
                    SourceDefinition.Process,
                    definition.Extract(8, 7).Value,
                    this,
                    "Before Display");
            }

            if (!string.IsNullOrWhiteSpace(definition.Extract(8, 8).Value))
            {
                DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                    SourceDefinition.Screen,
                    SourceDefinition.Process,
                    definition.Extract(8, 8).Value,
                    this,
                    "Before Action Bar Option");
            }

            if (!string.IsNullOrWhiteSpace(definition.Extract(8, 4).Value))
            {
                DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                    SourceDefinition.Screen,
                    SourceDefinition.Process,
                    definition.Extract(8, 4).Value,
                    this,
                    "After Action Bar Option");
            }
        }
        /// <summary>
        /// The read linked screen completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private void ReadLinkedScreenCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            DebugViewModel.Instance.ProcessAnalysisViewModel.SetIsLoading(-1);

            if (parameters[5].Count != 1 || !parameters[5].Value.Equals("0"))
            {
                // item not found end of reading linked screens.
                return;
            }

            var state = userState as object[];
            if (state == null)
            {
                return;
            }

            var nextScreen = (int)state[0];
            var prefix = state[1] as string;
            var dict = state[2] as string;

            DebugViewModel.Instance.ProcessAnalysisViewModel.LoadScreen(prefix + nextScreen, dict, this, "Screen");

            // increment the next screen and do it again.
            nextScreen++;
            DebugViewModel.Instance.ProcessAnalysisViewModel.SetIsLoading(1);
            SBFile.ReadDictionaryItem(
                this.Dictionary,
                prefix + nextScreen,
                new object[] { nextScreen, prefix, this.Dictionary },
                this.ReadLinkedScreenCompleted);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="OutputDefinitionDescription"/> class.
 /// </summary>
 /// <param name="fileName">
 /// The file name.
 /// </param>
 /// <param name="name">
 /// The name.
 /// </param>
 /// <param name="expression">
 /// The expression.
 /// </param>
 /// <param name="definition">
 /// The definition.
 /// </param>
 public OutputDefinitionDescription(string fileName, string name, string expression, SBString definition)
     : base(fileName, name, expression, definition)
 {
 }
        /// <summary>
        /// The parse screen definition.
        /// </summary>
        /// <param name="definition">
        /// The definition.
        /// </param>
        private void ParseScreenDefinition(SBString definition)
        {
            const int ButtonDesc = 11;
            const int Buttons = 12;
            const int Fields = 15;
            const int ProcessesBefore = 25;
            const int ProcessesAfter = 26;
            const int IntHelp = 27;
            const int FieldPos = 31;
            const int ConversionCode = 34;
            const int DefaultDerived = 35;
            const int Validation = 36;
            // So far I have not found where or what this is, in the BRANCH S1 screen it looks like a hangove from rev control. const int InputConversion   = 39;
            const int StyleName = 51;

            try
            {
                // fields
                var noFields = definition.Dcount(Fields);
                for (int fno = 1; fno <= noFields; fno++)
                {
                    var processBefore = (definition.Dcount() >= ProcessesBefore && definition.Extract(ProcessesBefore).Dcount() >= fno)
                                            ? definition.Extract(ProcessesBefore, fno).Value
                                            : string.Empty;
                    var processAfter = (definition.Dcount() >= ProcessesAfter && definition.Extract(ProcessesAfter).Dcount() >= fno)
                                           ? definition.Extract(ProcessesAfter, fno).Value
                                           : string.Empty;
                    var intuitiveHelp = (definition.Dcount() >= IntHelp && definition.Extract(IntHelp).Dcount() >= fno)
                                            ? definition.Extract(IntHelp, fno).Value
                                            : string.Empty;
                    var conversionCode = (definition.Dcount() >= ConversionCode && definition.Extract(ConversionCode).Dcount() >= fno)
                                             ? definition.Extract(ConversionCode, fno).Value
                                             : string.Empty;
                    var fieldDefault = string.Empty;
                    if (definition.Dcount() >= FieldPos && definition.Extract(FieldPos).Dcount() >= fno)
                    {
                        fieldDefault = (!string.IsNullOrEmpty(definition.Extract(FieldPos, fno).Value)
                                        && definition.Extract(FieldPos, fno).Value.Substring(0, 1).Equals("0"))
                                           ? string.Empty
                                           : definition.Extract(DefaultDerived, fno).Value;
                    }

                    var derived = string.Empty;
                    if (definition.Dcount() >= FieldPos && definition.Extract(FieldPos).Dcount() >= fno)
                    {
                        derived = (!string.IsNullOrEmpty(definition.Extract(FieldPos, fno).Value)
                                   && definition.Extract(FieldPos, fno).Value.Substring(0, 1).Equals("0"))
                                      ? string.Empty
                                      : definition.Extract(DefaultDerived, fno).Value;
                    }

                    var validation = (definition.Dcount() >= Validation && definition.Extract(Validation).Dcount() >= fno)
                                         ? definition.Extract(Validation, fno).Value
                                         : string.Empty;
                    var styleName = (definition.Dcount() >= StyleName && definition.Extract(StyleName).Dcount() >= fno)
                                        ? definition.Extract(StyleName, fno).Value
                                        : string.Empty;

                    this.FieldDescriptions.Add(
                        new ScreenFieldDefinition(this.FileName, definition.Extract(Fields, fno).Value)
                            {
                                ProcessBefore = processBefore,
                                ProcessAfter = processAfter,
                                IntuitiveHelp = intuitiveHelp,
                                ConversionCode = conversionCode,
                                FieldDefault = fieldDefault,
                                Derived = derived,
                                Validation = validation,
                                StyleName = styleName
                            });
                }

                // Buttons
                var noButtons = definition.Dcount(Buttons);
                for (int bNo = 1; bNo <= noButtons; bNo++)
                {
                    if (!definition.Extract(Buttons, bNo).IsNullOrEmpty())
                    {
                        DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                            SourceDefinition.Button,
                            SourceDefinition.Process,
                            definition.Extract(Buttons, bNo).Value,
                            this,
                            "Button " + definition.Extract(ButtonDesc, bNo).Value);
                    }
                }

                // load the list of processes
                if (!string.IsNullOrWhiteSpace(definition.Extract(7, 1).Value))
                {
                    DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                        SourceDefinition.Screen,
                        SourceDefinition.Process,
                        definition.Extract(7, 1).Value,
                        this,
                        "Before Screen Display");
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(7, 2).Value))
                {
                    DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                        SourceDefinition.Screen,
                        SourceDefinition.Process,
                        definition.Extract(7, 2).Value,
                        this,
                        "After Screen Display");
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(7, 3).Value))
                {
                    DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                        SourceDefinition.Screen,
                        SourceDefinition.Process,
                        definition.Extract(7, 3).Value,
                        this,
                        "After Read Record");
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(7, 4).Value))
                {
                    DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                        SourceDefinition.Screen,
                        SourceDefinition.Process,
                        definition.Extract(7, 4).Value,
                        this,
                        "After Accept");
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(7, 5).Value))
                {
                    DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                        SourceDefinition.Screen,
                        SourceDefinition.Process,
                        definition.Extract(7, 5).Value,
                        this,
                        "After Update");
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(7, 6).Value))
                {
                    DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                        SourceDefinition.Screen,
                        SourceDefinition.Process,
                        definition.Extract(7, 6).Value,
                        this,
                        "If Escape");
                }

                // Buttons
            }
            catch (Exception exception)
            {
                CustomLogger.LogException(exception, "Exception parsing screen definition");
                // MessageBox.Show("Exception parsing screen definition (" + exception.Message + ")");
            }
        }
        /// <summary>
        /// The read control record completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private static void ReadControlRecordCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            try
            {
                var status = parameters[5];
                if (status.Count != 1 || !status.Value.Equals("0"))
                {
                    return;
                }

                var controlRec = parameters[3];
                switch (controlRec.Extract(9).Value)
                {
                    case "UV":
                        Platform = Platform.UniVerse;
                        break;
                    case "UDATA":
                        Platform = Platform.UniData;
                        break;
                }
            }
            catch (Exception exception)
            {
                CustomLogger.LogException(exception, "There was a problem reading the control record.");
            }
        }
 /// <summary>
 /// The get common variable completed.
 /// </summary>
 /// <param name="subroutineName">
 /// The subroutine name.
 /// </param>
 /// <param name="parameters">
 /// The parameters.
 /// </param>
 /// <param name="userState">
 /// The user state.
 /// </param>
 private static void GetCommonVariableCompleted(string subroutineName, SBString[] parameters, object userState)
 {
     try
     {
         if (DebugWindowManager.DebugConsoleWindow != null)
         {
             JobManager.RunInDispatcherThread(
                 DebugWindowManager.DebugConsoleWindow.Dispatcher, 
                 DispatcherPriority.Normal, 
                 () => UpdateProperties(parameters));
         }
         else
         {
             UpdateProperties(parameters);
         }
     }
     catch (Exception exception)
     {
         SBPlusClient.LogError("Exception caught.", exception);
     }
 }
 /// <summary>
 /// The process menu options.
 /// </summary>
 /// <param name="definition">
 /// The definition.
 /// </param>
 private void ProcessMenuOptions(SBString definition)
 {
     try
     {
         var noOptions = definition.Extract(MenuOptionType).Dcount();
         for (int optNo = 1; optNo <= noOptions; optNo++)
         {
             var desc = definition.Extract(Options, optNo).Value;
             var type = definition.Extract(MenuOptionType, optNo).Value;
             var process = definition.Extract(ProcessName, optNo).Value;
             if (type.Equals("P") && !string.IsNullOrEmpty(process))
             {
                 DebugViewModel.Instance.ProcessAnalysisViewModel.LoadProcessFromExpression(
                     SourceDefinition.Menu,
                     SourceDefinition.Process,
                     process,
                     this,
                     desc);
             }
         }
     }
     catch (Exception exception)
     {
         this.IsError = true;
         CustomLogger.LogException(exception, "There was a problem process the menu '" + this.Name + "'");
     }
 }
        /// <summary>
        /// The set item data.
        /// </summary>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <param name="which">
        /// The which.
        /// </param>
        /// <param name="collection">
        /// The collection.
        /// </param>
        private static void SetItemData(SBString value, string which, NestedAttributeCollection collection)
        {
            if (collection.ContainsIndex(which))
            {
                var item = collection.GetItemWithIndex(which);
                if (item == null)
                {
                    collection.Add(new NestedAttribute(which, value, BuildTitle(collection.Variable, which)));
                }

                if (item != null)
                {
                    item.Source = value;
                }
            }
            else if (!string.IsNullOrEmpty(collection.Variable) && collection.Variable.Equals(which))
            {
                collection.Source = value;
            }
            else
            {
                collection.Add(new NestedAttribute(which, value, BuildTitle(collection.Variable, which)));
            }
        }
        /// <summary>
        /// The parse definition.
        /// </summary>
        /// <param name="definition">
        /// The definition.
        /// </param>
        private void ParseDefinition(SBString definition)
        {
            /*
            Type                                               2
            1: vertical box
            2: horiz boxtype.
            3: user painted
            4: as 3 + select no
            5: horiz box with linked sub-menus (for GUI)
             *
             * Option Description                                 6.M     C
             * Name                                               7.M     D
             * Type (M/P/T/>/H/C/X)                               8.M     D

             *
             * Process before menu display                       13.1
             * Process after display                             13.2
             * Process after select option                       13.3
             * Process after execution of option                 13.4
             * Process after escaping this menu                  13.5
             * Process before returning to SYSMENU or LOGIN      13.6
             * Process to determine box cords                    13.7
             * Subroutine to call at start                       13.8

            */
            switch (definition.Extract(MenuType).Value)
            {
                case "1":
                    this.ProcessMenuOptions(definition);
                    break;
                case "2":
                    this.ProcessMenuOptions(definition);
                    break;
                case "3":
                    break;
                case "4":
                    break;
                case "5":
                    break;
            }
        }
        /// <summary>
        /// The read for set xui debug completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private void ReadForSetXuiDebugCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            var status = parameters[5];
            if (status.Count != 1 || !status.Value.Equals("0"))
            {
                if (this.isDebugEnabled)
                {
                    this.IsDebugEnabled = false;
                }

                return;
            }

            JobManager.RunInUIThread(
                DispatcherPriority.Input, 
                () => XuiDebug.EnableDebug(this.SetIsDebugEnabledCompleted, this.IsDebugEnabled));
        }
        /// <summary>
        /// The read field definition completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private void ReadFieldDefinitionCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            const int DefaultExpression = 5;
            const int ValidationExpression = 6;
            const int ConversionExpression = 7;
            const int DerivedExpression = 8;
            const int IntuitiveHelpExpression = 13;
            const int RightClickMenu = 29; // .1;
            const int DoubleClickProcess = 29; //.2;
            const int HtmlProcess = 30;
            const int ComboPopulationProcess = 34;

            string fieldName = string.Empty;
            try
            {
                if (parameters[5].Count != 1 || !parameters[5].Value.Equals("0"))
                {
                    // item not found.
                    this.HasDictionary = false;
                    return;
                }

                this.HasDictionary = true;

                var state = userState as object[];
                if (state == null)
                {
                    return;
                }

                var fileName = state[0] as string;
                fieldName = state[1] as string;

                var definition = parameters[3];

                if (!string.IsNullOrWhiteSpace(definition.Extract(DefaultExpression).Value))
                {
                    this.DictionaryDefault = definition.Extract(DefaultExpression).Value;
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(ValidationExpression).Value))
                {
                    this.DictionaryValidation = definition.Extract(ValidationExpression).Value;
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(ConversionExpression).Value))
                {
                    this.DictionaryConversionCode = definition.Extract(ConversionExpression).Value;
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(DerivedExpression).Value))
                {
                    this.DictionaryDerived = definition.Extract(DerivedExpression).Value;
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(IntuitiveHelpExpression).Value))
                {
                    // Check to see if the tooltip is there as well.
                    var intHelp = definition.Extract(IntuitiveHelpExpression).Value;
                    if (intHelp.IndexOf("[") >= 0)
                    {
                        intHelp = intHelp.Split("[".ToCharArray())[1];
                        this.DictionaryIntuitiveHelp = intHelp;
                    }
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(RightClickMenu, 1).Value))
                {
                    this.DictionaryRightClickMenu = definition.Extract(RightClickMenu, 1).Value;
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(DoubleClickProcess, 2).Value))
                {
                    this.DictionaryDoubleClickProcess = definition.Extract(DoubleClickProcess, 2).Value;
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(HtmlProcess).Value))
                {
                    this.DictionaryHtmlProcess = definition.Extract(HtmlProcess).Value;
                }

                if (!string.IsNullOrWhiteSpace(definition.Extract(ComboPopulationProcess).Value))
                {
                    this.DictionaryComboPopulationProcess = definition.Extract(ComboPopulationProcess).Value;
                }
            }
            catch (Exception exception)
            {
                CustomLogger.LogException(exception, "A problem occurred parsing the field definition for " + fieldName);
            }
        }
        /// <summary>
        /// The read xui debug completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private void ReadXuiDebugCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            var status = parameters[5];
            if (status.Count != 1 || !status.Value.Equals("0"))
            {
                if (this.isDebugEnabled)
                {
                    this.IsDebugEnabled = false;
                }

                return;
            }

            XuiDebug.IsDebugEnabled(this.SetIsDebugEnabledCompleted);
        }
        /// <summary>
        /// The create paragraph description.
        /// </summary>
        /// <param name="processFileName">
        /// The process file name.
        /// </param>
        /// <param name="pName">
        /// The p name.
        /// </param>
        /// <param name="expression">
        /// The expression.
        /// </param>
        /// <param name="defn">
        /// The defn.
        /// </param>
        /// <returns>
        /// The <see cref="ParagraphDescription"/>.
        /// </returns>
        private ParagraphDescription CreateParagraphDescription(string processFileName, string pName, string expression, SBString defn)
        {
            var processDescription = new ParagraphDescription(processFileName, pName, expression, defn);

            // Now parse out the paragraph to find definition and basic program calls
            var paragraphExpression = defn.Extract(3).Value;

            var elements = paragraphExpression.Split(GenericConstants.CHAR_ARRAY_SEMI_COLON);
            // C0;AP4;P4;C1;=;I2;EP.BRANCH,INT.CALL;J5;P4;C2;=;I1;BBASIC.PROGRAM
            foreach (var element in elements)
            {
                if (string.IsNullOrEmpty(element.Trim()))
                {
                    continue;
                }

                switch (element.Substring(0, 1))
                {
                    case "E":
                        this.LoadProcessFromExpression(
                            SourceDefinition.Paragraph,
                            SourceDefinition.Process,
                            element.Substring(1),
                            processDescription,
                            "Execute");
                        break;
                    case "B":
                        this.LoadBasicProgramFromExpression(element.Substring(1), processDescription, "Call");
                        break;
                }
            }

            return processDescription;
        }
 /// <summary>
 /// The set is debug enabled completed.
 /// </summary>
 /// <param name="subroutineName">
 /// The subroutine name.
 /// </param>
 /// <param name="parameters">
 /// The parameters.
 /// </param>
 /// <param name="userState">
 /// The user state.
 /// </param>
 private void SetIsDebugEnabledCompleted(string subroutineName, SBString[] parameters, object userState)
 {
     try
     {
         if (parameters[1].Dcount() == 1 && !string.IsNullOrEmpty(parameters[1].Value))
         {
             this.isDebugEnabled = parameters[1].Value.Equals("1");
         }
     }
     catch (Exception exception)
     {
         SBPlusClient.LogError("Exception setting IsDebugEnabled.", exception);
     }
 }
        private void DoAddProcessToCollection(string processFileName, string pName, SBString defn, ProcessLoadState processLoadState, bool isError)
        {
            try
            {
                if (processLoadState == null)
                {
                    return;
                }

                // top of tree so just assign it.
                var processDescription = this.CreateProcessDescription(processFileName, pName, defn, processLoadState);
                processDescription.IsError = isError;

                // Add the definition to the total collection if it is not already there. It should never be there already as
                // we should have bypassed the load if it is.
                lock (this.processCollection)
                {
                    if (!this.processCollection.ContainsKey(processFileName, pName, processDescription.GetType()))
                    {
                        this.processCollection.Add(processDescription);
                    }
                }

                this.AddProcessToCollection(
                    processLoadState.HookPoint,
                    processLoadState.ParentDefinitionDescription,
                    processDescription,
                    processLoadState.Source);
            }
            catch (Exception ex)
            {
                CustomLogger.LogException(
                    ex,
                    string.Format("There was a problem when adding {0} {1} to the collection.", processFileName, pName));
            }
        }
        /// <summary>
        /// The update collection.
        /// </summary>
        /// <param name="which">
        /// The which.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        private void UpdateCollection(string which, SBString value)
        {
            try
            {
                var collection = this.GetCollection(which);
                if (collection != null)
                {
                    SetItemData(value, which, collection);
                }

                // Either did not find it and/or the it is already displayed in a sub window so have a look.
                var window = DebugWindowManager.GetWindow(which);
                if (window == null)
                {
                    // check to see if I have an specific attribute or value.
                    if (which.Contains("<"))
                    {
                        // extract the parent
                        var parent = which.Substring(0, which.IndexOf("<", StringComparison.Ordinal));
                        // look for a window first then a base colleciton
                        window = DebugWindowManager.GetWindow(parent);
                        if (window != null)
                        {
                            collection = window.DataContext as NestedAttributeCollection;
                        }
                        else
                        {
                            collection = this.GetCollection(parent);
                        }
                    }
                }
                else
                {
                    collection = window.DataContext as NestedAttributeCollection;
                }

                if (collection == null)
                {
                    return;
                }

                SetItemData(value, which, collection);
            }
            catch (Exception exception)
            {
                SBPlusClient.LogError("Problem getting common variable infor for " + which, exception);
            }
        }
        /// <summary>
        /// The read basic program voc pointer completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private void ReadBasicProgramVocPointerCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            try
            {
                this.SetIsLoading(-1);
                var processState = userState as ProcessLoadState;
                if (processState == null)
                {
                    return;
                }

                BasicProgramDescription basicProgramDescription = null;
                lock (this.processCollection)
                {
                    // it should be in the cache so retrieve it.
                    if (this.processCollection.ContainsKey(string.Empty, parameters[1].Value, typeof(BasicProgramDescription)))
                    {
                        basicProgramDescription = this.processCollection[parameters[1].Value] as BasicProgramDescription;
            /*
                        Debug.WriteLine(
                            "[ProcessAnalysisViewModel.ReadBasicProgramVocPointerCompleted(355)] Read " + parameters[1].Value
                            + " from cache.");
            */
                    }

                    if (basicProgramDescription == null)
                    {
                        basicProgramDescription = new BasicProgramDescription(string.Empty, parameters[1].Value);
                        this.processCollection.Add(basicProgramDescription);
            /*
                        Debug.WriteLine(
                            "[ProcessAnalysisViewModel.ReadBasicProgramVocPointerCompleted(363)] Added " + basicProgramDescription.Name
                            + " to cache.");
            */
                    }
                }

                if (parameters[5].Count != 1 || !parameters[5].Value.Equals("0"))
                {
                    // Error
                    this.LastProcessReadError = string.Format("Failed to read {0} from {1}.", parameters[1].Value, parameters[0].Value);
                    basicProgramDescription.IsError = true;
                    return;
                }

                this.AddBasicProgramToCollection(
                    basicProgramDescription,
                    new ProcessLoadState
                        {
                            Expression = processState.Expression,
                            HookPoint = processState.HookPoint,
                            ParentDefinitionDescription = processState.ParentDefinitionDescription
                        });

                /*
                 * UniVerse VOC pointer
                 *  V
                    C:\U2\SBXA3427\APPLICATIONSERVER\UNIVERSE\SBDEMO\CHPROGS.O/B.BRANCH
                    B
                    BNP

                    PICK.FORMAT
                    SýNýPýIýAýEýH
                    NO.WARNýNOPAGEýLPTRýKEEP.COMMONýýTRAPýHDR-SUPP
                    C:\U2\SBXA3427\APPLICATIONSERVER\UNIVERSE\SBDEMO\CHPROGS.O

                 * UniData VOC Pointer
                 * C
                 * E:\U2\SBXA\APPLICATIONSERVER\UNIDATA\SB.DEFN\DM\_SB.LOGIN
                 */
                if (!basicProgramDescription.Parsed && !basicProgramDescription.IsError)
                {
                    if (parameters[3].Extract(1).Value.Equals("V"))
                    {
                        // UniVerse
                        basicProgramDescription.ObjectFileLocation = parameters[3].Extract(9).Value;
                        basicProgramDescription.ObjectLocation = parameters[3].Extract(2).Value;
                        if (!string.IsNullOrEmpty(basicProgramDescription.ObjectFileLocation))
                        {
                            // figure out the name of the file
                            var fileName = Path.GetFileName(basicProgramDescription.ObjectFileLocation);
                            if (!string.IsNullOrEmpty(fileName))
                            {
                                if (fileName.EndsWith(".O"))
                                {
                                    basicProgramDescription.FileName = fileName.Substring(0, fileName.Length - 2);
                                }
                            }
                        }
                    }
                    else
                    {
                        // UniData, on windows.
                        var parts = parameters[3].Extract(2).Value.Split(@"\".ToCharArray());
                        basicProgramDescription.FileName = parts[parts.Length - 2];
                    }

                    if (!string.IsNullOrEmpty(basicProgramDescription.FileName))
                    {
                        // no need to go any further if I am excluding this file.
                        if (!IsExcludeFile(basicProgramDescription.FileName))
                        {
                            // if I have a file name try open it and see if I can read the code.
                            JobManager.RunInUIThread(
                                DispatcherPriority.Input,
                                delegate
                                    {
                                        this.SetIsLoading(1);
                                        SBFile.Read(
                                            basicProgramDescription.FileName,
                                            basicProgramDescription.Name,
                                            this.ReadBasicProgramCompleted,
                                            new object[] { basicProgramDescription });
                                    });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.LastProcessReadError = "Exception caught after reading definition definition. " + ex.Message;
            }
        }
        /// <summary>
        /// The update definition stack.
        /// </summary>
        /// <param name="add">
        /// The add.
        /// </param>
        /// <param name="processName">
        /// The definition name.
        /// </param>
        /// <param name="paramaters">
        /// The proc name.
        /// </param>
        public static void UpdateProcessStack(bool add, string processName, SBString paramaters)
        {
            var actionTime = DateTime.Now;
            try
            {
                int serverActionTime = 0;
                if (paramaters.Extract(1, 1).Dcount() > 1)
                {
                    int.TryParse(paramaters.Extract(1, 1, 1).Value, out serverActionTime);
                    CustomLogger.LogDebug(() => string.Format("Add {0} {1} at {2}.", add, processName, serverActionTime));
                }
                else
                {
                    CustomLogger.LogDebug(() => string.Format("Add {0} {1}.", add, processName));
                }

                if (DebugWindowManager.DebugConsoleWindow == null)
                {
                    // no debug windows.
                    return;
                }

                if (Thread.CurrentThread.ManagedThreadId != DebugWindowManager.DebugConsoleWindow.Dispatcher.Thread.ManagedThreadId)
                {
                    JobManager.RunInDispatcherThread(
                        DebugWindowManager.DebugConsoleWindow.Dispatcher, 
                        DispatcherPriority.Normal, 
                        () => DoUpdateProcessStack(add, processName, actionTime, serverActionTime));
                }
                else
                {
                    DoUpdateProcessStack(add, processName, actionTime, serverActionTime);
                }
            }
            catch (Exception exception)
            {
                SBPlusClient.LogError("Exception caught.", exception);
            }
        }
        /// <summary>
        /// The read process completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private void ReadProcessCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            try
            {
                this.SetIsLoading(-1);
                var processState = userState as ProcessLoadState;
                if (processState == null)
                {
                    return;
                }

                var processFileName = parameters[0].Value;
                var pName = parameters[1].Value;
                if (parameters[5].Count != 1 || !parameters[5].Value.Equals("0"))
                {
                    // Failed to read the process.
                    if (parameters[0].Value.EndsWith("MENUS"))
                    {
                        // Failed, but now I need to check if there is a global process file and if so try read it from there.
                        if (!string.IsNullOrEmpty(this.globalMenuFile) && !parameters[0].Value.Equals(this.globalMenuFile))
                        {
                            this.SetIsLoading(1);
                            SBFile.Read(this.globalMenuFile, pName, this.ReadProcessCompleted, processState);
                        }
                        else
                        {
                            // Error
                            this.LastProcessReadError = string.Format(
                                "Failed to read {0} from {1}.",
                                parameters[1].Value,
                                parameters[0].Value);
                            this.AddProcessToCollection(processFileName, pName, null, processState, true);
                        }
                    }
                    else
                    {
                        // Failed, but if the name is not all upper case try that first.
                        if (!pName.ToUpper().Equals(pName) && !parameters[0].Value.Equals(this.globalProcessFile))
                        {
                            this.SetIsLoading(1);
                            SBFile.Read(processFileName, pName.ToUpper(), this.ReadProcessCompleted, processState);
                            return;
                        }
                        // Failed, but now I need to check if there is a global process file and if so try read it from there.
                        if (!string.IsNullOrEmpty(this.globalProcessFile) && !parameters[0].Value.Equals(this.globalProcessFile))
                        {
                            this.SetIsLoading(1);
                            SBFile.Read(this.globalProcessFile, pName, this.ReadProcessCompleted, processState);
                            return;
                        }

                        if (!pName.ToUpper().Equals(pName) && parameters[0].Value.Equals(this.globalProcessFile))
                        {
                            this.SetIsLoading(1);
                            SBFile.Read(this.globalProcessFile, pName.ToUpper(), this.ReadProcessCompleted, processState);
                            return;
                        }

                        // Error
                        this.LastProcessReadError = string.Format(
                            "Failed to read {0} from {1}.",
                            parameters[1].Value,
                            parameters[0].Value);
                        this.AddProcessToCollection(processFileName, pName, null, processState, true);
                        // Now remove it from the MRU is it is there and display a message.
                        RemoveProcessFromMru(pName);
                        JobManager.RunInDispatcherThread(
                            DebugWindowManager.DebugConsoleWindow.Dispatcher,
                            DispatcherPriority.Normal,
                            () =>
                            {
                                if (processState.ParentDefinitionDescription == null)
                                {
                                    this.ErrorCollection.Add(
                                        new ErrorDescription()
                                    {
                                        ProcessName = pName,
                                        Description = string.Format("Failed to read process '{0}'.", pName)
                                    });
                                }
                                else
                                {
                                    this.ErrorCollection.Add(
                                        new ErrorDescription()
                                    {
                                        FileName =
                                            !string.IsNullOrEmpty(
                                                processState.ParentDefinitionDescription.FileName)
                                               ? processState.ParentDefinitionDescription.FileName
                                               : string.Empty,
                                        ProcessName = pName,
                                        FieldName =
                                            !string.IsNullOrEmpty(
                                                processState.ParentDefinitionDescription.Name)
                                                ? processState.ParentDefinitionDescription.Name
                                                : string.Empty,
                                        Description =
                                            string.Format(
                                                "Failed to read process '{0}', referenced by '{1}' in the file '{2}'.",
                                                pName,
                                                !string.IsNullOrEmpty(
                                                    processState.ParentDefinitionDescription.Name)
                                                ? processState.ParentDefinitionDescription.Name
                                                : string.Empty,
                                                !string.IsNullOrEmpty(
                                                    processState.ParentDefinitionDescription.FileName)
                                                    ? processState.ParentDefinitionDescription.FileName
                                                    : string.Empty)
                                    });
                                }
                            });
                    }

                    return;
                }

                this.AddProcessToCollection(processFileName, pName, parameters[3], processState);
            }
            catch (Exception ex)
            {
                this.LastProcessReadError = "Exception caught after reading definition definition. " + ex.Message;
            }
        }
        /// <summary>
        /// The read dict item completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private static void ReadDictItemCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            try
            {
                var state = userState as object[];
                if (state == null)
                {
                    return;
                }

                if (parameters[5].Count != 1 || !parameters[5].Value.Equals("0") || parameters[3].IsNullOrEmpty())
                {
                    // item not found.
                    return;
                }

                var revisionDefinitionItemCollection = state[2] as RevisionDefinitionItemCollection;
                if (revisionDefinitionItemCollection == null)
                {
                    return;
                }

                var fileName = state[0] as string;
                if (string.IsNullOrEmpty(fileName))
                {
                    return;
                }

                var itemName = state[1] as string;
                if (string.IsNullOrEmpty(itemName))
                {
                    return;
                }

                if (DebugWindowManager.DebugConsoleWindow != null)
                {
                    // Adding screen definition item from dictionary.
                    JobManager.RunInDispatcherThread(
                        DebugWindowManager.DebugConsoleWindow.Dispatcher,
                        DispatcherPriority.Normal,
                        () =>
                        RevisionDefinitionViewModel.AddItemToDefinition(
                            revisionDefinitionItemCollection,
                            new RevisionDefinitionItem
                                {
                                    Action = "IO",
                                    FileName = fileName.StartsWith("DICT ") ? fileName.Substring(5) : fileName,
                                    Item = itemName,
                                    Parameters = RevisionDefinitionViewModel.Dict
                                }));
                }
            }
            catch (Exception ex)
            {
                CustomLogger.LogException(ex, "There was a problem processing a dictionary item.");
            }
        }