/**
  * Draw characters of content range.
  *
  * @param gc the GC
  * @param startOffset inclusive start index
  * @param endOffset exclusive end index
  */
 private void drawCharRange(GC gc, int startOffset, int endOffset) {
   StyledTextContent content = fTextWidget.getContent();
   int length = endOffset - startOffset;
   String text = content.getTextRange(startOffset, length);
   StyleRange styleRange = null;
   Color fg = null;
   Point selection = fTextWidget.getSelection();
   StringBuffer visibleChar = new StringBuffer(10);
   for (int textOffset = 0; textOffset <= length; ++textOffset) {
     int delta = 0;
     boolean eol = false;
     if (textOffset < length) {
       delta = 1;
       char c = text.charAt(textOffset);
       switch (c) {
         case ' ':
           visibleChar.append(SPACE_SIGN);
           // 'continue' would improve performance but may produce
           // drawing errors
           // for long runs of space if width of space and dot differ
           break;
         case '\u3000': // ideographic whitespace
           visibleChar.append(IDEOGRAPHIC_SPACE_SIGN);
           // 'continue' would improve performance but may produce
           // drawing errors
           // for long runs of space if width of space and dot differ
           break;
         case '\t':
           visibleChar.append(TAB_SIGN);
           break;
         case '\r':
           visibleChar.append(CARRIAGE_RETURN_SIGN);
           if (textOffset >= length - 1 || text.charAt(textOffset + 1) != '\n') {
             eol = true;
             break;
           }
           continue;
         case '\n':
           visibleChar.append(LINE_FEED_SIGN);
           eol = true;
           break;
         default:
           delta = 0;
           break;
       }
     }
     if (visibleChar.length() > 0) {
       int widgetOffset = startOffset + textOffset - visibleChar.length() + delta;
       if (!eol || !isFoldedLine(content.getLineAtOffset(widgetOffset))) {
         if (widgetOffset >= selection.x && widgetOffset < selection.y) {
           fg = fTextWidget.getSelectionForeground();
         } else if (styleRange == null || styleRange.start + styleRange.length <= widgetOffset) {
           styleRange = fTextWidget.getStyleRangeAtOffset(widgetOffset);
           if (styleRange == null || styleRange.foreground == null) {
             fg = fTextWidget.getForeground();
           } else {
             fg = styleRange.foreground;
           }
         }
         draw(gc, widgetOffset, visibleChar.toString(), fg);
       }
       visibleChar.delete(0, visibleChar.length());
     }
   }
 }