public boolean prepareTextRegion(
      ITextRegionCollection blockedRegion,
      int partitionStartOffset,
      int partitionLength,
      Collection<StyleRange> holdResults) {

    boolean handled = false;
    final int partitionEndOffset = partitionStartOffset + partitionLength - 1;
    ITextRegion region = null;
    ITextRegionList regions = blockedRegion.getRegions();
    int nRegions = regions.size();
    StyleRange styleRange = null;
    for (int i = 0; i < nRegions; i++) {
      region = regions.get(i);
      TextAttribute attr = null;
      //            TextAttribute previousAttr = null;
      final int startOffset = blockedRegion.getStartOffset(region);
      if (startOffset > partitionEndOffset) break;
      if (blockedRegion.getEndOffset(region) <= partitionStartOffset) continue;

      if (region instanceof ITextRegionCollection) {
        handled =
            prepareTextRegion(
                (ITextRegionCollection) region, partitionStartOffset, partitionLength, holdResults);
      } else {

        if (region.getType() == TwigRegionContext.TWIG_CONTENT
            || region.getType() == TwigRegionContext.TWIG_COMMENT) {
          handled =
              prepareTwigRegions(
                  holdResults,
                  (ITwigScriptRegion) region,
                  startOffset,
                  partitionStartOffset,
                  partitionLength);
        } else {

          attr = getAttributeFor(region);
          if (attr != null) {
            handled = true;
            styleRange =
                createStyleRange(
                    blockedRegion, region, attr, partitionStartOffset, partitionLength);
            holdResults.add(styleRange);
            // technically speaking, we don't need to update
            // previousAttr
            // in the other case, because the other case is when
            // it hasn't changed
            //                        previousAttr = attr;
          } else {
            //                        previousAttr = null;
          }
        }
      }
    }
    return handled;
  }
  /*
   * Search the RegionContainer's regions looking for JSP content. If valid
   * content is found, return the position >= 0 If no valid content is
   * found, return NO_VALID_CONTENT. If a region starts after the line's
   * endOffset, return END_OF_LINE.
   */
  private static int getValidRegionPosition(
      IStructuredModel model,
      ITextRegionCollection regionContainer,
      int startOffset,
      int endOffset) {

    ITextRegionList regions = regionContainer.getRegions();
    for (int i = 0; i < regions.size(); i++) {
      ITextRegion region = regions.get(i);
      if (region instanceof ITextRegionCollection) {
        int validPosition =
            getValidRegionPosition(model, (ITextRegionCollection) region, startOffset, endOffset);
        if (validPosition == END_OF_LINE || validPosition >= 0) return validPosition;
      } else {
        // region must be at least partially on selected line
        if (regionContainer.getEndOffset(region) > startOffset) {

          int regionStartOffset = regionContainer.getStartOffset(region);
          // if region starts after line's endOffset, we're done
          // searching
          if (regionStartOffset > endOffset) return END_OF_LINE;

          // If region is JSP content, make sure the language is
          // Java not Javascript by
          // checking the content assist adapter's type.
          if (region.getType().equals(DOMJSPRegionContexts.JSP_CONTENT)) {
            // DWM: this logic is not incorrect ... given changes
            // to adapters, etc.
            // but probably don't need anything here, since both
            // Java and JavaScript
            // are supported in V5.

            // nsd_TODO: verify this!!!

            // INodeNotifier notifier =
            // (INodeNotifier)model.getNode(region.getStartOffset());
            // IAdapterFactory factory =
            // model.getFactoryRegistry().getFactoryFor(ContentAssistAdapter.class);
            // if(factory instanceof
            // HTMLContentAssistAdapterFactory) {
            // INodeAdapter adapter =
            // ((HTMLContentAssistAdapterFactory)factory).createAdapter(notifier,
            // region);
            // if(adapter != null && adapter instanceof
            // JSPJavaContentAssistAdapter)

            if (regionStartOffset > startOffset) return regionStartOffset;
            else return startOffset;
            // }
          }
          // a custom tag, jsp:useBean, getproperty or setproperty
          // statement is also a valid breakpoint location
          else if (region.getType().equals(DOMRegionContext.XML_TAG_NAME)
              && (isCustomTagRegion(model.getIndexedRegion(regionStartOffset))
                  || regionContainer.getText(region).equals(JSP12Namespace.ElementName.USEBEAN)
                  || regionContainer.getText(region).equals(JSP12Namespace.ElementName.GETPROPERTY)
                  || regionContainer
                      .getText(region)
                      .equals(JSP12Namespace.ElementName.SETPROPERTY))) {

            if (regionStartOffset > startOffset) return regionStartOffset;
            else return startOffset;
          } else {
            // Defect #241090, the Text Nodes inside of JSP
            // scriptlets, expressions, and declarations are valid
            // breakpoint-able locations
            boolean isCodeNode = false;
            IndexedRegion node = model.getIndexedRegion(regionStartOffset);
            if (node != null && node instanceof Node) {
              Node domNode = (Node) node;
              Node root = domNode.getOwnerDocument().getDocumentElement();
              if (root != null
                  && root.getNodeName().equals(JSP12Namespace.ElementName.ROOT)
                  && domNode.getNodeType() == Node.TEXT_NODE
                  && domNode.getParentNode() != null) {
                String parentName = domNode.getParentNode().getNodeName();
                isCodeNode =
                    parentName.equals(JSP12Namespace.ElementName.SCRIPTLET)
                        || parentName.equals(JSP12Namespace.ElementName.EXPRESSION)
                        || parentName.equals(JSP12Namespace.ElementName.DECLARATION);
              }
            }
            if (isCodeNode) {
              if (regionStartOffset > startOffset) return regionStartOffset;
              else return startOffset;
            }
          }
        }
      }
    }
    return NO_VALID_CONTENT;
  }