/// <summary> /// Invokes the Field Verification Routine if one is specified by fsdego() in the Fsdscb Struct /// </summary> /// <param name="session"></param> /// <param name="fieldStatus"></param> /// <returns></returns> private bool FieldVerificationRoutine(SessionBase session, FsdStatus fieldStatus) { //Get fsdscb Struct for this channel var fsdscbStruct = GetFsdscbStruct(session); //If null, then return that it looks A-OK if (fsdscbStruct.fldvfy == IntPtr16.Empty) { return(true); } //Save Current Answer -- if not already allocated, allocate 255 bytes if (!session.CurrentModule.Memory.TryGetVariablePointer($"FSD-CurrentAnswer-{session.Channel}", out var currentAnswerPointer)) { currentAnswerPointer = session.CurrentModule.Memory.AllocateVariable($"FSD-CurrentAnswer-{session.Channel}", 0xFF); } session.CurrentModule.Memory.SetZero(currentAnswerPointer, 0xFF); session.CurrentModule.Memory.SetArray(currentAnswerPointer, Encoding.ASCII.GetBytes(fieldStatus.SelectedField.Value)); session.CurrentModule.Memory.SetArray(fsdscbStruct.newans, _fsdUtility.BuildAnswerString(fieldStatus)); //Set fsdscb struct values and save it fsdscbStruct.ansbuf = Encoding.ASCII.GetBytes(fieldStatus.SelectedField.Value); fsdscbStruct.anslen = (byte)fieldStatus.SelectedField.FieldLength; fsdscbStruct.crsfld = (byte)fieldStatus.SelectedOrdinal; fsdscbStruct.xitkey = _userInput; SaveFsdscbStruct(session, fsdscbStruct); var result = session.CurrentModule.Execute(fsdscbStruct.fldvfy, session.Channel, true, false, new Queue <ushort>(new List <ushort> { currentAnswerPointer.Segment, currentAnswerPointer.Offset, (ushort)fieldStatus.SelectedOrdinal }), 0xF200); //2k from stack base of 0xFFFF, should be enough to not overlap with the existing program execution //Get Latest Struct fsdscbStruct = GetFsdscbStruct(session); switch (fsdscbStruct.state) { case (byte)EnumFsdStateCodes.FSDQIT: case (byte)EnumFsdStateCodes.FSDSAV: { session.SessionState = EnumSessionState.ExitingFullScreenDisplay; return(true); } } return(result.AX == (ushort)EnumFsdStateCodes.VFYCHK); }
private void EnteringFullScreenDisplay(SessionBase session) { var fieldSpec = session.CurrentModule.Memory.GetString($"FSD-FieldSpec-{session.Channel}", true); var fsdTemplate = session.CurrentModule.Memory.GetString($"FSD-TemplateBuffer-{session.Channel}"); var answerPointer = session.CurrentModule.Memory.GetVariablePointer($"FSD-Answers-{session.Channel}"); //Load Fields & Answers from Spec & Description var fields = _fsdUtility.ParseFieldSpecs(fieldSpec); var parsedAnswers = _fsdUtility.ParseAnswers(fields.Count, session.CurrentModule.Memory.GetArray(answerPointer, 0x800)); _fsdUtility.SetAnswers(parsedAnswers, fields); //Parse Template to know location, type, etc. of Fields var fsdStatus = new FsdStatus { Channel = session.Channel, SelectedOrdinal = 0, Fields = fields }; _fsdUtility.GetFieldPositions(fsdTemplate, fsdStatus); _fsdUtility.GetFieldAnsi(fsdTemplate, fsdStatus); session.SessionState = EnumSessionState.InFullScreenDisplay; //Always reset on re-entry if (_fsdFields.ContainsKey(session.Channel)) { _fsdFields.Remove(session.Channel); } _fsdFields.Add(session.Channel, fsdStatus); for (var i = 0; i < fields.Count; i++) { SetFieldInactive(session, fsdStatus.Fields[i]); } //Set Original Value & Highlight the First Field ClearErrorMessage(session, fsdStatus.ErrorField); SetFieldActive(session, fsdStatus.SelectedField); //Get fsdscb Struct for this channel var fsdscbStruct = GetFsdscbStruct(session); fsdscbStruct.numtpl = (ushort)fsdStatus.Fields.Count; fsdscbStruct.state = (byte)EnumFsdStateCodes.FSDAEN; fsdscbStruct.newans = answerPointer; //1k buffer for answer string _fsdUtility.SetFieldAttributes(session.CurrentModule.Memory.GetArray($"FSD-Fsdscb-{session.Channel}-flddat", FsdfldStruct.Size * 100), fields); SaveFsdscbStruct(session, fsdscbStruct); }
/// <summary> /// Verifies a specified field value passes the specified validation /// </summary> /// <param name="field"></param> private bool ValidateField(SessionBase session, FsdStatus fsdStatus) { var isValid = true; //If a field verification was passed in, we'll check it if (!FieldVerificationRoutine(session, fsdStatus)) { DisplayErrorMessage(session, fsdStatus.ErrorField, GetVerificationErrorMessage(session)); isValid = false; } switch (fsdStatus.SelectedField.FsdFieldType) { //Text Validations case EnumFsdFieldType.Text: case EnumFsdFieldType.Secret: { if (fsdStatus.SelectedField.Value.Length > fsdStatus.SelectedField.Maximum) { DisplayErrorMessage(session, fsdStatus.ErrorField, $"Enter at most {fsdStatus.SelectedField.Maximum} character(s)"); isValid = false; break; } if (fsdStatus.SelectedField.Value.Length < fsdStatus.SelectedField.Minimum) { DisplayErrorMessage(session, fsdStatus.ErrorField, $"Enter at least {fsdStatus.SelectedField.Minimum} character(s)"); isValid = false; break; } break; } //Numeric Validation case EnumFsdFieldType.Numeric when int.Parse(fsdStatus.SelectedField.Value) > fsdStatus.SelectedField.Maximum: DisplayErrorMessage(session, fsdStatus.ErrorField, $"Enter no higher than {fsdStatus.SelectedField.Maximum}"); isValid = false; break; case EnumFsdFieldType.Numeric when int.Parse(fsdStatus.SelectedField.Value) < fsdStatus.SelectedField.Minimum: DisplayErrorMessage(session, fsdStatus.ErrorField, $"Enter at least {fsdStatus.SelectedField.Maximum}"); isValid = false; break; //Multiple Choice Validation case EnumFsdFieldType.MultipleChoice when fsdStatus.SelectedField.Value == string.Empty: DisplayErrorMessage(session, fsdStatus.ErrorField, $"Choices: {string.Join(' ', fsdStatus.SelectedField.Values).ToUpper()}"); isValid = false; break; } //If Validation Failed, display error message if (!isValid) { //Reset the Field _fsdFields[session.Channel].SelectedField.Value = _fsdFields[session.Channel].SelectedField.OriginalValue; //Mark it Active SetFieldActive(session, _fsdFields[session.Channel].SelectedField); } return(isValid); }