⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fl_text_display.cxx

📁 SRI international 发布的OAA框架软件
💻 CXX
📖 第 1 页 / 共 5 页
字号:
*/
void Fl_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip,
                                 int leftCharIndex, int rightCharIndex) {
  Fl_Text_Buffer * buf = mBuffer;
  int i, X, Y, startX, charIndex, lineStartPos, lineLen, fontHeight;
  int stdCharWidth, charWidth, startIndex, charStyle, style;
  int charLen, outStartIndex, outIndex;
  int dispIndexOffset;
  char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ], outStr[ MAX_DISP_LINE_LEN ];
  char *outPtr;
  const char *lineStr;

//  printf("draw_vline(visLineNum=%d, leftClip=%d, rightClip=%d, leftCharIndex=%d, rightCharIndex=%d)\n",
//         visLineNum, leftClip, rightClip, leftCharIndex, rightCharIndex);
//  printf("nNVisibleLines=%d\n", mNVisibleLines);

  /* If line is not displayed, skip it */
  if ( visLineNum < 0 || visLineNum >= mNVisibleLines )
    return;

  /* Calculate Y coordinate of the string to draw */
  fontHeight = mMaxsize;
  Y = text_area.y + visLineNum * fontHeight;

  /* Get the text, length, and  buffer position of the line to display */
  lineStartPos = mLineStarts[ visLineNum ];
//  printf("lineStartPos=%d\n", lineStartPos);
  if ( lineStartPos == -1 ) {
    lineLen = 0;
    lineStr = NULL;
  } else {
    lineLen = vline_length( visLineNum );
    lineStr = buf->text_range( lineStartPos, lineStartPos + lineLen );
  }

  /* Space beyond the end of the line is still counted in units of characters
     of a standardized character width (this is done mostly because style
     changes based on character position can still occur in this region due
	  to rectangular Fl_Text_Selections).  stdCharWidth must be non-zero to
     prevent a potential infinite loop if X does not advance */
  stdCharWidth = TMPFONTWIDTH;   //mFontStruct->max_bounds.width;
  if ( stdCharWidth <= 0 ) {
    Fl::error("Fl_Text_Display::draw_vline(): bad font measurement");
    free((void *)lineStr);
    return;
  }

  /* Shrink the clipping range to the active display area */
  leftClip = max( text_area.x, leftClip );
  rightClip = min( rightClip, text_area.x + text_area.w );

  /* Rectangular Fl_Text_Selections are based on "real" line starts (after
	  a newline or start of buffer).  Calculate the difference between the
	  last newline position and the line start we're using.  Since scanning
	  back to find a newline is expensive, only do so if there's actually a
	  rectangular Fl_Text_Selection which needs it */
    if (mContinuousWrap && (range_touches_selection(buf->primary_selection(),
    	    lineStartPos, lineStartPos + lineLen) || range_touches_selection(
    	    buf->secondary_selection(), lineStartPos, lineStartPos + lineLen) ||
    	    range_touches_selection(buf->highlight_selection(), lineStartPos,
    	    lineStartPos + lineLen))) {
    	dispIndexOffset = buf->count_displayed_characters(
    	    	buf->line_start(lineStartPos), lineStartPos);
    } else
    	dispIndexOffset = 0;

  /* Step through character positions from the beginning of the line (even if
     that's off the left edge of the displayed area) to find the first
     character position that's not clipped, and the X coordinate for drawing
     that character */
  X = text_area.x - mHorizOffset;
  outIndex = 0;
  for ( charIndex = 0; ; charIndex++ ) {
    charLen = charIndex >= lineLen ? 1 :
              Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex,
                                                expandedChar, buf->tab_distance(), buf->null_substitution_character() );
    style = position_style( lineStartPos, lineLen, charIndex,
                            outIndex + dispIndexOffset );
    charWidth = charIndex >= lineLen ? stdCharWidth :
                string_width( expandedChar, charLen, style );
    if ( X + charWidth >= leftClip && charIndex >= leftCharIndex ) {
      startIndex = charIndex;
      outStartIndex = outIndex;
      startX = X;
      break;
    }
    X += charWidth;
    outIndex += charLen;
  }

  /* Scan character positions from the beginning of the clipping range, and
     draw parts whenever the style changes (also note if the cursor is on
     this line, and where it should be drawn to take advantage of the x
     position which we've gone to so much trouble to calculate) */
  outPtr = outStr;
  outIndex = outStartIndex;
  X = startX;
  for ( charIndex = startIndex; charIndex < rightCharIndex; charIndex++ ) {
    charLen = charIndex >= lineLen ? 1 :
              Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar,
                                                buf->tab_distance(), buf->null_substitution_character() );
    charStyle = position_style( lineStartPos, lineLen, charIndex,
                                outIndex + dispIndexOffset );
    for ( i = 0; i < charLen; i++ ) {
      if ( i != 0 && charIndex < lineLen && lineStr[ charIndex ] == '\t' )
        charStyle = position_style( lineStartPos, lineLen,
                                    charIndex, outIndex + dispIndexOffset );
      if ( charStyle != style ) {
        draw_string( style, startX, Y, X, outStr, outPtr - outStr );
        outPtr = outStr;
        startX = X;
        style = charStyle;
      }
      if ( charIndex < lineLen ) {
        *outPtr = expandedChar[ i ];
        charWidth = string_width( &expandedChar[ i ], 1, charStyle );
      } else
        charWidth = stdCharWidth;
      outPtr++;
      X += charWidth;
      outIndex++;
    }
    if ( outPtr - outStr + FL_TEXT_MAX_EXP_CHAR_LEN >= MAX_DISP_LINE_LEN || X >= rightClip )
      break;
  }

  /* Draw the remaining style segment */
  draw_string( style, startX, Y, X, outStr, outPtr - outStr );

  /* Draw the cursor if part of it appeared on the redisplayed part of
     this line.  Also check for the cases which are not caught as the
     line is scanned above: when the cursor appears at the very end
     of the redisplayed section. */
  /*  CET - FIXME
    if ( mCursorOn )
    {
      if ( hasCursor )
        draw_cursor( cursorX, Y );
      else if ( charIndex < lineLen && ( lineStartPos + charIndex + 1 == cursorPos )
                && X == rightClip )
      {
        if ( cursorPos >= buf->length() )
          draw_cursor( X - 1, Y );
        else
        {
          draw_cursor( X - 1, Y );
        }
      }
    }
  */
  if ( lineStr != NULL )
    free((void *)lineStr);
}

/*
** Draw a string or blank area according to parameter "style", using the
** appropriate colors and drawing method for that style, with top left
** corner at X, y.  If style says to draw text, use "string" as source of
** characters, and draw "nChars", if style is FILL, erase
** rectangle where text would have drawn from X to toX and from Y to
** the maximum Y extent of the current font(s).
*/
void Fl_Text_Display::draw_string( int style, int X, int Y, int toX,
                                   const char *string, int nChars ) {
  const Style_Table_Entry * styleRec;

  /* Draw blank area rather than text, if that was the request */
  if ( style & FILL_MASK ) {
    clear_rect( style, X, Y, toX - X, mMaxsize );
    return;
  }

  /* Set font, color, and gc depending on style.  For normal text, GCs
     for normal drawing, or drawing within a Fl_Text_Selection or highlight are
     pre-allocated and pre-configured.  For syntax highlighting, GCs are
     configured here, on the fly. */

  Fl_Font font = textfont();
  int fsize = textsize();
  Fl_Color foreground;
  Fl_Color background;

  if ( style & STYLE_LOOKUP_MASK ) {
    int si = (style & STYLE_LOOKUP_MASK) - 'A';
    if (si < 0) si = 0;
    else if (si >= mNStyles) si = mNStyles - 1;

    styleRec = mStyleTable + si;
    font  = styleRec->font;
    fsize = styleRec->size;

    if ( style & (HIGHLIGHT_MASK | PRIMARY_MASK) ) {
      background = selection_color();
    } else background = color();

    foreground = fl_contrast(styleRec->color, background);
  } else if ( style & (HIGHLIGHT_MASK | PRIMARY_MASK) ) {
    background = selection_color();
    foreground = fl_contrast(textcolor(), background);
  } else {
    foreground = textcolor();
    background = color();
  }

  fl_color( background );
  fl_rectf( X, Y, toX - X, mMaxsize );
  fl_color( foreground );
  fl_font( font, fsize );
  fl_draw( string, nChars, X, Y + mMaxsize - fl_descent());

  // CET - FIXME
  /* If any space around the character remains unfilled (due to use of
     different sized fonts for highlighting), fill in above or below
     to erase previously drawn characters */
  /*
      if (fs->ascent < mAscent)
        clear_rect( style, X, Y, toX - X, mAscent - fs->ascent);
      if (fs->descent < mDescent)
        clear_rect( style, X, Y + mAscent + fs->descent, toX - x,
                mDescent - fs->descent);
  */
  /* Underline if style is secondary Fl_Text_Selection */

  /*
      if (style & SECONDARY_MASK)
        XDrawLine(XtDisplay(mW), XtWindow(mW), gc, x,
                y + mAscent, toX - 1, Y + fs->ascent);
  */
}

/*
** Clear a rectangle with the appropriate background color for "style"
*/
void Fl_Text_Display::clear_rect( int style, int X, int Y,
                                  int width, int height ) {
  /* A width of zero means "clear to end of window" to XClearArea */
  if ( width == 0 )
    return;

  if ( style & HIGHLIGHT_MASK ) {
    fl_color( fl_contrast(textcolor(), color()) );
    fl_rectf( X, Y, width, height );
  } else if ( style & PRIMARY_MASK ) {
    fl_color( FL_SELECTION_COLOR );
    fl_rectf( X, Y, width, height );
  } else {
    fl_color( color() );
    fl_rectf( X, Y, width, height );
  }
}



/*
** Draw a cursor with top center at X, y.
*/
void Fl_Text_Display::draw_cursor( int X, int Y ) {
  typedef struct {
    int x1, y1, x2, y2;
  }
  Segment;

  Segment segs[ 5 ];
  int left, right, cursorWidth, midY;
  //    int fontWidth = mFontStruct->min_bounds.width, nSegs = 0;
  int fontWidth = TMPFONTWIDTH; // CET - FIXME
  int nSegs = 0;
  int fontHeight = mMaxsize;
  int bot = Y + fontHeight - 1;

  if ( X < text_area.x - 1 || X > text_area.x + text_area.w )
    return;

  /* For cursors other than the block, make them around 2/3 of a character
     width, rounded to an even number of pixels so that X will draw an
     odd number centered on the stem at x. */
  cursorWidth = 4;   //(fontWidth/3) * 2;
  left = X - cursorWidth / 2;
  right = left + cursorWidth;

  /* Create segments and draw cursor */
  if ( mCursorStyle == CARET_CURSOR ) {
    midY = bot - fontHeight / 5;
    segs[ 0 ].x1 = left; segs[ 0 ].y1 = bot; segs[ 0 ].x2 = X; segs[ 0 ].y2 = midY;
    segs[ 1 ].x1 = X; segs[ 1 ].y1 = midY; segs[ 1 ].x2 = right; segs[ 1 ].y2 = bot;
    segs[ 2 ].x1 = left; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = midY - 1;
    segs[ 3 ].x1 = X; segs[ 3 ].y1 = midY - 1; segs[ 3 ].x2 = right; segs[ 3 ].y2 = bot;
    nSegs = 4;
  } else if ( mCursorStyle == NORMAL_CURSOR ) {
    segs[ 0 ].x1 = left; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = right; segs[ 0 ].y2 = Y;
    segs[ 1 ].x1 = X; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = X; segs[ 1 ].y2 = bot;
    segs[ 2 ].x1 = left; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = right; segs[ 2 ].y2 = bot;
    nSegs = 3;
  } else if ( mCursorStyle == HEAVY_CURSOR ) {
    segs[ 0 ].x1 = X - 1; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = X - 1; segs[ 0 ].y2 = bot;
    segs[ 1 ].x1 = X; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = X; segs[ 1 ].y2 = bot;
    segs[ 2 ].x1 = X + 1; segs[ 2 ].y1 = Y; segs[ 2 ].x2 = X + 1; segs[ 2 ].y2 = bot;
    segs[ 3 ].x1 = left; segs[ 3 ].y1 = Y; segs[ 3 ].x2 = right; segs[ 3 ].y2 = Y;
    segs[ 4 ].x1 = left; segs[ 4 ].y1 = bot; segs[ 4 ].x2 = right; segs[ 4 ].y2 = bot;
    nSegs = 5;
  } else if ( mCursorStyle == DIM_CURSOR ) {
    midY = Y + fontHeight / 2;
    segs[ 0 ].x1 = X; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = X; segs[ 0 ].y2 = Y;
    segs[ 1 ].x1 = X; segs[ 1 ].y1 = midY; segs[ 1 ].x2 = X; segs[ 1 ].y2 = midY;
    segs[ 2 ].x1 = X; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = bot;
    nSegs = 3;
  } else if ( mCursorStyle == BLOCK_CURSOR ) {
    right = X + fontWidth;
    segs[ 0 ].x1 = X; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = right; segs[ 0 ].y2 = Y;
    segs[ 1 ].x1 = right; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = right; segs[ 1 ].y2 = bot;
    segs[ 2 ].x1 = right; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = bot;
    segs[ 3 ].x1 = X; segs[ 3 ].y1 = bot; segs[ 3 ].x2 = X; segs[ 3 ].y2 = Y;
    nSegs = 4;
  }
  fl_color( mCursor_color );

  for ( int k = 0; k < nSegs; k++ ) {
    fl_line( segs[ k ].x1, segs[ k ].y1, segs[ k ].x2, segs[ k ].y2 );
  }
}

/*
** Determine the drawing method to use to draw a specific character from "buf".
** "lineStartPos" gives the character index where the line begins, "lineIndex",
** the number of characters past the beginning of the line, and "dispIndex",
** the number of displayed characters past the beginning of the line.  Passing
** lineStartPos of -1 returns the drawing style for "no text".
**
** Why not just: position_style(pos)?  Because style applies to blank areas
** of the window beyond the text boundaries, and because this routine must also
** decide whether a position is inside of a rectangular Fl_Text_Selection, and do
** so efficiently, without re-counting character positions from the start of the
** line.
**
** Note that style is a somewhat incorrect name, drawing method would
** be more appropriate.
*/
int Fl_Text_Display::position_style( int lineStartPos,
                                     int lineLen, int lineIndex, int dispIndex ) {
  Fl_Text_Buffer * buf = mBuffer;
  Fl_Text_Buffer *styleBuf = mStyleBuffer;
  int pos, style = 0;

  if ( lineS

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -