public static ScreenItemInstance FindItem(
      this IScreenItem item, IScreenLoc Start, IScreenLoc FindZeroLoc, 
      ScreenContent Content)
    {
      ScreenItemInstance findItem = null;

      if (item.ItemType == ShowItemType.Section)
      {
        var sectionItem = item as IScreenSection;
        findItem = sectionItem.FindItem(Start, FindZeroLoc, Content);
      }

      else
      {
        // adjust screen loc of the item by start pos of the section it is contained in.
        var adjRow = Start.RowNum - 1;
        var adjCol = Start.ColNum - 1;
        var loc = new OneScreenLoc(
          item.ScreenLoc.RowNum + adjRow, item.ScreenLoc.ColNum + adjCol);
        var zeroLoc = loc.ToZeroRowCol();

        var itemAtomic = item as IScreenAtomic;
        var range = new ScreenLocRange(zeroLoc, itemAtomic.Length, Content.ScreenDim);
        if (range.Contains(FindZeroLoc) == true)
          findItem = new ScreenItemInstance(item, range.From);
      }

      return findItem;
    }
    public static Tuple<DataItem, DataItemReport> CaptureReport(
      this IScreenItem item, IScreenLoc Start, ScreenContent Content)
    {
      string captureText = null;
      DataItem dataItem = null;
      DataItemReport itemReport = null;
      ContentItemBase contentItem = null;

      // get the content item at the rowcol location.
      bool rc = true;
      IScreenAtomic atomicItem = null;

      // adjust screen loc of the item by start pos of the section it is contained in.
      var adjRow = Start.RowNum - 1;
      var adjCol = Start.ColNum - 1;
      var loc = new OneScreenLoc(
        item.ScreenLoc.RowNum + adjRow, item.ScreenLoc.ColNum + adjCol);
      var zeroLoc = loc.ToZeroRowCol();

      if (item.ItemType != ShowItemType.Section)
      {
        rc = Content.FieldDict.TryGetValue(zeroLoc, out contentItem);
        atomicItem = item as IScreenAtomic;
      }

      if (rc == false)
      {
      }

      else if (item.ItemType == ShowItemType.Section)
      {
        var sectionItem = item as IScreenSection;
        itemReport = sectionItem.CaptureReport(Content);
      }

      else if (item.ItemType == ShowItemType.Field)
      {
        if ((contentItem is ContentField) == true)
        {
          var contentField = contentItem as ContentField;
          dataItem = new DataItem(item.ItemName, contentField.GetShowText(Content));
          captureText = item.ItemName + "=" + contentField.GetShowText(Content);
        }
      }

      // match fixed literal
      else if (item.ItemType == ShowItemType.Literal)
      {
        if ((contentItem is ContentText) == true)
        {
          var contentText = contentItem as ContentText;
          var itemLit = item as IScreenLiteral;
          var ctValue = contentText.GetShowText(Content).TrimEndWhitespace();
        }
      }

      return new Tuple<DataItem, DataItemReport>(dataItem, itemReport);
    }
    public static bool Match(
      this IScreenItem item, IScreenLoc Start, ScreenContent Content, 
      string DebugInfo)
    {
      bool isMatch = true;
      ContentItemBase contentItem = null;

      // get the content item at the rowcol location.
      bool rc = true;
      IScreenAtomic atomicItem = null;

      // adjust screen loc of the item by start pos of the section it is contained in.
      var adjRow = Start.RowNum - 1;
      var adjCol = Start.ColNum - 1;
      var loc = new OneScreenLoc(
        item.ScreenLoc.RowNum + adjRow, item.ScreenLoc.ColNum + adjCol) ;
      var zeroLoc = loc.ToZeroRowCol();

      // item is not a section. Get the field or literal located at the item loc.
      if (item.ItemType != ShowItemType.Section)
      {
        atomicItem = item as IScreenAtomic;
      }

      if ((rc == false) && ( 1 == 2))
      {
        if ( item.IsOptional == false )
          isMatch = false;
      }

      else if ((isMatch == true) && (item.ItemType == ShowItemType.Section))
      {
        var sectionItem = item as IScreenSection;
        isMatch = sectionItem.Match(Content, DebugInfo);
      }

      else if ((isMatch == true) && (item.ItemType == ShowItemType.Field))
      {
        var fieldItem = item as IScreenField;
        rc = Content.FieldDict.TryGetValue(zeroLoc, out contentItem);
        if (rc == false)
          isMatch = false;
        
        // can match a screen field to a literal, but only if the field is output
        // only.
        else if ((contentItem is ContentText) 
          && (fieldItem.Usage != ShowUsage.Output))
          isMatch = false;

        else if ((contentItem is ContentField) == false)
          isMatch = false;
        else
        {
          var contentField = contentItem as ContentField;
          if (contentField.LL_Length != atomicItem.Length)
            isMatch = false;
        }
      }

      // match screen literal to actual content on the screen. The content can be
      // either a field or a literal. But the content has to match one of the 
      // values of the screen literal.
      else if ((isMatch == true) && (item.ItemType == ShowItemType.Literal))
      {
        // screen literal has a dsply attr. advance ....
        if ( atomicItem.DsplyAttr.IsNullOrEmpty( ) == false )
        {
          zeroLoc = zeroLoc.Advance(1) as ZeroRowCol;
        }

        var buf = Content.GetContentBytes_NonNull(zeroLoc, atomicItem.Length);
        var itemLit = item as IScreenLiteral;
        var contentText = buf.EbcdicBytesToString().TrimEndWhitespace();

        // match the screen defn item to the screen content.
        isMatch = itemLit.MatchValue(contentText);

        // failed the match. But if the item content is blank. And this screen
        // item is optional then that is ok.
        if ((isMatch == false) && (item.IsOptional == true) && (contentText.Length == 0))
          isMatch = true;
      }

      else if (isMatch == true)
      {
        throw new Exception("unrecognized screen item type");
      }

      return isMatch;
    }