protected CompoundRegion[] getOutsideRegions(IStructuredDocument model, IRegion reg) {
   CompoundRegion[] ret = new CompoundRegion[2];
   RegionIterator it = new RegionIterator(model, reg.getOffset());
   it.prev();
   if (it.hasPrev()) {
     ITextRegion textRegion = it.prev();
     IStructuredDocumentRegion documentRegion = it.getStructuredDocumentRegion();
     ret[0] = new CompoundRegion(documentRegion, textRegion);
   } else {
     ret[0] = null;
   }
   it.reset(model, reg.getOffset() + reg.getLength());
   if (it.hasNext()) {
     ITextRegion textRegion = it.next();
     IStructuredDocumentRegion documentRegion = it.getStructuredDocumentRegion();
     ret[1] = new CompoundRegion(documentRegion, textRegion);
   } else {
     ret[1] = null;
   }
   return ret;
 }
  /**
   * @return int
   * @param node org.eclipse.wst.css.core.model.interfaces.ICSSNode
   * @param insertPos int
   */
  public int getLengthToReformatBefore(ICSSNode node, int insertPos) {
    if (node == null) return 0;
    IndexedRegion nnode = (IndexedRegion) node;
    if (insertPos <= 0 || !nnode.contains(insertPos - 1)) return 0;

    IStructuredDocumentRegion flatNode =
        node.getOwnerDocument()
            .getModel()
            .getStructuredDocument()
            .getRegionAtCharacterOffset(insertPos - 1);
    if (flatNode == null) return 0;
    ITextRegion region = flatNode.getRegionAtCharacterOffset(insertPos - 1);
    if (region == null) return 0;
    RegionIterator it = new RegionIterator(flatNode, region);
    boolean found = false;
    while (it.hasPrev()) {
      region = it.prev();
      // if (region.getType() != CSSRegionContexts.CSS_S &&
      // region.getType() != CSSRegionContexts.CSS_DELIMITER &&
      // region.getType() !=
      // CSSRegionContexts.CSS_DECLARATION_DELIMITER) {
      if (region.getType() != CSSRegionContexts.CSS_S) {
        found = true;
        break;
      }
    }
    int pos =
        insertPos
            - (found
                ? it.getStructuredDocumentRegion().getTextEndOffset(region)
                : it.getStructuredDocumentRegion().getStartOffset(region));
    // flatNode = it.getStructuredDocumentRegion();
    // if (found) {
    // if (region.getLength() != region.getTextLength()) {
    // pos = insertPos - flatNode.getTextEndOffset(region);
    // } else {
    // pos = insertPos - flatNode.getEndOffset(region);
    // }
    // } else {
    // pos = insertPos - flatNode.getStartOffset(region);
    // }
    return (pos >= 0) ? pos : 0;
  }
  protected void appendDelimBefore(ICSSNode node, CompoundRegion toAppend, StringBuffer source) {
    if (node == null || source == null) return;
    if (isCleanup() && !getCleanupStrategy(node).isFormatSource())
      return; // for not formatting case on cleanup action
    String delim = getLineDelimiter(node);

    boolean needIndent = !(node instanceof ICSSStyleSheet);
    if (toAppend == null) {
      source.append(delim);
      source.append(getIndent(node));
      if (needIndent) source.append(getIndentString());
    } else {
      String type = toAppend.getType();
      if (type == CSSRegionContexts.CSS_COMMENT) {
        RegionIterator it =
            new RegionIterator(toAppend.getDocumentRegion(), toAppend.getTextRegion());
        it.prev();
        ITextRegion prev = it.prev();
        int[] result = null;
        if (prev == null
            || (prev.getType() == CSSRegionContexts.CSS_S
                && (result =
                            TextUtilities.indexOf(
                                DefaultLineTracker.DELIMITERS,
                                it.getStructuredDocumentRegion().getText(prev),
                                0))
                        [0]
                    >= 0)) {
          // Collapse to one empty line if there's more than one.
          int offset = result[0] + DefaultLineTracker.DELIMITERS[result[1]].length();
          if (offset < it.getStructuredDocumentRegion().getText(prev).length()) {
            if (TextUtilities.indexOf(
                    DefaultLineTracker.DELIMITERS,
                    it.getStructuredDocumentRegion().getText(prev),
                    offset)[0]
                >= 0) {
              source.append(delim);
            }
          }
          source.append(delim);
          source.append(getIndent(node));
          if (needIndent) source.append(getIndentString());
        } else if (prev.getType() == CSSRegionContexts.CSS_COMMENT) {
          String fullText = toAppend.getDocumentRegion().getFullText(prev);
          String trimmedText = toAppend.getDocumentRegion().getText(prev);
          String whiteSpaces = ""; // $NON-NLS-1$
          if (fullText != null && trimmedText != null)
            whiteSpaces = fullText.substring(trimmedText.length());
          int[] delimiterFound =
              TextUtilities.indexOf(DefaultLineTracker.DELIMITERS, whiteSpaces, 0);
          if (delimiterFound[0] != -1) {
            source.append(delim);
          } else {
            appendSpaceBefore(node, toAppend.getText(), source);

            /*If two comments can't be adjusted in one line(combined length exceeds line width),
             * a tab is also appended along with next line delimiter , we need to remove that.
             */
            if (source.toString().endsWith(getIndentString())) {
              source.delete((source.length() - getIndentString().length()), source.length());
            }
          }
        } else {
          appendSpaceBefore(node, toAppend.getText(), source);
        }
      } else if (type == CSSRegionContexts.CSS_DELIMITER
          || type == CSSRegionContexts.CSS_DECLARATION_DELIMITER) {
        RegionIterator it =
            new RegionIterator(toAppend.getDocumentRegion(), toAppend.getTextRegion());
        it.prev();
        ITextRegion prev = it.prev();

        Preferences preferences = CSSCorePlugin.getDefault().getPluginPreferences();

        if (prev.getType() == CSSRegionContexts.CSS_S
            && TextUtilities.indexOf(
                    DefaultLineTracker.DELIMITERS,
                    it.getStructuredDocumentRegion().getText(prev),
                    0)[0]
                >= 0) {
          source.append(delim);
          source.append(getIndent(node));
          if (needIndent) source.append(getIndentString());
        } else if (preferences.getInt(CSSCorePreferenceNames.LINE_WIDTH) > 0
            && (!preferences.getBoolean(CSSCorePreferenceNames.WRAPPING_PROHIBIT_WRAP_ON_ATTR)
                || node.getOwnerDocument().getNodeType() != ICSSNode.STYLEDECLARATION_NODE)) {
          int length = getLastLineLength(node, source);
          int append = 1;
          if (length + append > preferences.getInt(CSSCorePreferenceNames.LINE_WIDTH)) {
            source.append(getLineDelimiter(node));
            source.append(getIndent(node));
            if (needIndent) source.append(getIndentString());
          }
        }
      } else if (type == CSSRegionContexts.CSS_RBRACE || type == CSSRegionContexts.CSS_LBRACE) {
        source.append(delim);
        source.append(getIndent(node));
      } else {
        source.append(delim);
        source.append(getIndent(node));
        if (needIndent) source.append(getIndentString());
      }
    }
  }
  protected void appendSpaceBefore(ICSSNode node, CompoundRegion toAppend, StringBuffer source) {
    if (node == null || toAppend == null || source == null) return;
    if (isCleanup() && !getCleanupStrategy(node).isFormatSource())
      return; // for not formatting case on cleanup action
    String type = toAppend.getType();

    Preferences preferences = CSSCorePlugin.getDefault().getPluginPreferences();

    boolean needIndent = !(node instanceof ICSSStyleSheet);
    if (type == CSSRegionContexts.CSS_COMMENT) {
      // check whether previous region is 'S' and has CR-LF
      String delim = getLineDelimiter(node);
      RegionIterator it =
          new RegionIterator(toAppend.getDocumentRegion(), toAppend.getTextRegion());
      it.prev();
      ITextRegion prev = it.prev();
      // bug390904
      if (prev.getType() == CSSRegionContexts.CSS_LBRACE
          && TextUtilities.indexOf(
                  DefaultLineTracker.DELIMITERS,
                  it.getStructuredDocumentRegion().getFullText(prev),
                  0)[0]
              > 0) {
        source.append(delim);
        source.append(getIndent(node));
        source.append(getIndentString());
      } else if (prev.getType() == CSSRegionContexts.CSS_S
          && TextUtilities.indexOf(
                  DefaultLineTracker.DELIMITERS, it.getStructuredDocumentRegion().getText(prev), 0)[
                  0]
              >= 0) {
        source.append(delim);
        source.append(getIndent(node));
        if (needIndent) source.append(getIndentString());
      } else {
        appendSpaceBefore(node, toAppend.getText(), source);
      }
    } else if (type == CSSRegionContexts.CSS_LBRACE
        && preferences.getBoolean(CSSCorePreferenceNames.WRAPPING_NEWLINE_ON_OPEN_BRACE)) {
      String delim = getLineDelimiter(node);
      source.append(delim);
      source.append(getIndent(node));
      // } else if (type == CSSRegionContexts.CSS_CURLY_BRACE_CLOSE) {
      // } else if (type == CSSRegionContexts.CSS_INCLUDES || type ==
      // CSSRegionContexts.CSS_DASHMATCH) {
    } else if (type == CSSRegionContexts.CSS_DECLARATION_SEPARATOR
        && node instanceof ICSSStyleDeclItem) {
      int n = preferences.getInt(CSSCorePreferenceNames.FORMAT_PROP_PRE_DELIM);
      // no delimiter case
      while (n-- > 0) source.append(" "); // $NON-NLS-1$
    } else if (type == CSSRegionContexts.CSS_DECLARATION_VALUE_OPERATOR
        || type == CSSRegionContexts.CSS_DECLARATION_VALUE_PARENTHESIS_CLOSE) {
      if (preferences.getInt(CSSCorePreferenceNames.LINE_WIDTH) > 0
          && (!preferences.getBoolean(CSSCorePreferenceNames.WRAPPING_PROHIBIT_WRAP_ON_ATTR)
              || node.getOwnerDocument().getNodeType() != ICSSNode.STYLEDECLARATION_NODE)) {
        int length = getLastLineLength(node, source);
        int append = 1;
        if (length + append > preferences.getInt(CSSCorePreferenceNames.LINE_WIDTH)) {
          source.append(getLineDelimiter(node));
          source.append(getIndent(node));
          if (needIndent) source.append(getIndentString());
        }
      }
    } else if (CSSRegionContexts.CSS_FOREIGN_ELEMENT == type
        || CSSRegionContexts.CSS_DECLARATION_DELIMITER == type) {
      return;
    } else appendSpaceBefore(node, toAppend.getText(), source);
  }