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

📄 fl_text_display.cxx

📁 SRI international 发布的OAA框架软件
💻 CXX
📖 第 1 页 / 共 5 页
字号:
  text_area.x = X+LEFT_MARGIN;
  text_area.y = Y+BOTTOM_MARGIN;
  text_area.w = W-LEFT_MARGIN-RIGHT_MARGIN;
  text_area.h = H-TOP_MARGIN-BOTTOM_MARGIN;
  int i;

  /* Find the new maximum font height for this text display */
  for (i = 0, mMaxsize = fl_height(textfont(), textsize()); i < mNStyles; i++)
    mMaxsize = max(mMaxsize, fl_height(mStyleTable[i].font, mStyleTable[i].size));

  // did we have scrollbars initially?
  int hscrollbarvisible = mHScrollBar->visible();
  int vscrollbarvisible = mVScrollBar->visible();

  // try without scrollbars first
  mVScrollBar->clear_visible();
  mHScrollBar->clear_visible();

  for (int again = 1; again;) {
     again = 0;
    /* In continuous wrap mode, a change in width affects the total number of
       lines in the buffer, and can leave the top line number incorrect, and
       the top character no longer pointing at a valid line start */
    if (mContinuousWrap && !mWrapMargin && W!=oldWidth) {
      int oldFirstChar = mFirstChar;
    	mNBufferLines = count_lines(0, buffer()->length(), true);
	   mFirstChar = line_start(mFirstChar);
	   mTopLineNum = count_lines(0, mFirstChar, true)+1;
		absolute_top_line_number(oldFirstChar);
    }
 
    /* reallocate and update the line starts array, which may have changed
       size and / or contents.  */
    int nvlines = (text_area.h + mMaxsize - 1) / mMaxsize;
    if (nvlines < 1) nvlines = 1;
    if (mNVisibleLines != nvlines) {
      mNVisibleLines = nvlines;
      if (mLineStarts) delete[] mLineStarts;
      mLineStarts = new int [mNVisibleLines];
      calc_line_starts(0, mNVisibleLines);
      calc_last_char();
    }

    // figure the scrollbars
    if (scrollbar_width()) {
      /* Decide if the vertical scroll bar needs to be visible */
      if (scrollbar_align() & (FL_ALIGN_LEFT|FL_ALIGN_RIGHT) &&
          mNBufferLines >= mNVisibleLines - 1)
      {
        mVScrollBar->set_visible();
        if (scrollbar_align() & FL_ALIGN_LEFT) {
          text_area.x = X+scrollbar_width()+LEFT_MARGIN;
          text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN;
          mVScrollBar->resize(X, text_area.y-TOP_MARGIN, scrollbar_width(),
                              text_area.h+TOP_MARGIN+BOTTOM_MARGIN);
        } else {
          text_area.x = X+LEFT_MARGIN;
          text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN;
          mVScrollBar->resize(X+W-scrollbar_width(), text_area.y-TOP_MARGIN,
                              scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN);
        }
      }

      /*
         Decide if the horizontal scroll bar needs to be visible.  If there
         is a vertical scrollbar, a horizontal is always created too.  This
         is because the alternatives are unatractive:
          * Dynamically creating a horizontal scrollbar based on the currently
            visible lines is what the original nedit does, but it always wastes
            space for the scrollbar even when it's not used.  Since the FLTK
            widget dynamically allocates the space for the scrollbar and
            rearranges the widget to make room for it, this would create a very
            visually displeasing "bounce" effect when the vertical scrollbar is
            dragged.  Trust me, I tried it and it looks really bad.
          * The other alternative would be to keep track of what the longest
            line in the entire buffer is and base the scrollbar on that.  I
            didn't do this because I didn't see any easy way to do that using
            the nedit code and this could involve a lengthy calculation for
            large buffers.  If an efficient and non-costly way of doing this
            can be found, this might be a way to go.
      */
      /* WAS: Suggestion: Try turning the horizontal scrollbar on when
	 you first see a line that is too wide in the window, but then
	 don't turn it off (ie mix both of your solutions). */
      if (scrollbar_align() & (FL_ALIGN_TOP|FL_ALIGN_BOTTOM) &&
          (mVScrollBar->visible() || longest_vline() > text_area.w))
      {
        if (!mHScrollBar->visible()) {
          mHScrollBar->set_visible();
          again = 1; // loop again to see if we now need vert. & recalc sizes
        }
        if (scrollbar_align() & FL_ALIGN_TOP) {
          text_area.y = Y + scrollbar_width()+TOP_MARGIN;
          text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN;
          mHScrollBar->resize(text_area.x-LEFT_MARGIN, Y,
                              text_area.w+LEFT_MARGIN+RIGHT_MARGIN, scrollbar_width());
        } else {
          text_area.y = Y+TOP_MARGIN;
          text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN;
          mHScrollBar->resize(text_area.x-LEFT_MARGIN, Y+H-scrollbar_width(),
                              text_area.w+LEFT_MARGIN+RIGHT_MARGIN, scrollbar_width());
        }
      }
    }
  }

  // user request to change viewport
  if (mTopLineNumHint != mTopLineNum || mHorizOffsetHint != mHorizOffset)
    scroll_(mTopLineNumHint, mHorizOffsetHint);

  // everything will fit in the viewport
  if (mNBufferLines < mNVisibleLines || mBuffer == NULL || mBuffer->length() == 0)
    scroll_(1, mHorizOffset);
  /* if empty lines become visible, there may be an opportunity to
     display more text by scrolling down */
  else while (mLineStarts[mNVisibleLines-2] == -1)
    scroll_(mTopLineNum-1, mHorizOffset);

  // user request to display insert position
  if (display_insert_position_hint)
    display_insert();

  // in case horizontal offset is now greater than longest line
  int maxhoffset = max(0, longest_vline()-text_area.w);
  if (mHorizOffset > maxhoffset)
    scroll_(mTopLineNumHint, maxhoffset);

  mTopLineNumHint = mTopLineNum;
  mHorizOffsetHint = mHorizOffset;
  display_insert_position_hint = 0;

  if (mContinuousWrap ||
		hscrollbarvisible != mHScrollBar->visible() ||
      vscrollbarvisible != mVScrollBar->visible())
    redraw();

  update_v_scrollbar();
  update_h_scrollbar();
}

/*
** Refresh a rectangle of the text display.  left and top are in coordinates of
** the text drawing window
*/
void Fl_Text_Display::draw_text( int left, int top, int width, int height ) {
  int fontHeight, firstLine, lastLine, line;

  /* find the line number range of the display */
  fontHeight = mMaxsize ? mMaxsize : textsize_;
  firstLine = ( top - text_area.y - fontHeight + 1 ) / fontHeight;
  lastLine = ( top + height - text_area.y ) / fontHeight + 1;

  fl_push_clip( left, top, width, height );

  /* draw the lines */
  for ( line = firstLine; line <= lastLine; line++ )
    draw_vline( line, left, left + width, 0, INT_MAX );

    /* draw the line numbers if exposed area includes them */
    if (mLineNumWidth != 0 && left <= mLineNumLeft + mLineNumWidth)
	draw_line_numbers(false);

  fl_pop_clip();
}

void Fl_Text_Display::redisplay_range(int startpos, int endpos) {
  if (damage_range1_start == -1 && damage_range1_end == -1) {
    damage_range1_start = startpos;
    damage_range1_end = endpos;
  } else if ((startpos >= damage_range1_start && startpos <= damage_range1_end) ||
             (endpos >= damage_range1_start && endpos <= damage_range1_end)) {
    damage_range1_start = min(damage_range1_start, startpos);
    damage_range1_end = max(damage_range1_end, endpos);
  } else if (damage_range2_start == -1 && damage_range2_end == -1) {
    damage_range2_start = startpos;
    damage_range2_end = endpos;
  } else {
    damage_range2_start = min(damage_range2_start, startpos);
    damage_range2_end = max(damage_range2_end, endpos);
  }
  damage(FL_DAMAGE_SCROLL);
}
/*
** Refresh all of the text between buffer positions "start" and "end"
** not including the character at the position "end".
** If end points beyond the end of the buffer, refresh the whole display
** after pos, including blank lines which are not technically part of
** any range of characters.
*/
void Fl_Text_Display::draw_range(int startpos, int endpos) {
  int i, startLine, lastLine, startIndex, endIndex;

  /* If the range is outside of the displayed text, just return */
  if ( endpos < mFirstChar || ( startpos > mLastChar &&
       !empty_vlines() ) ) return;

  /* Clean up the starting and ending values */
  if ( startpos < 0 ) startpos = 0;
  if ( startpos > mBuffer->length() ) startpos = mBuffer->length();
  if ( endpos < 0 ) endpos = 0;
  if ( endpos > mBuffer->length() ) endpos = mBuffer->length();

  /* Get the starting and ending lines */
  if ( startpos < mFirstChar )
    startpos = mFirstChar;
  if ( !position_to_line( startpos, &startLine ) )
    startLine = mNVisibleLines - 1;
  if ( endpos >= mLastChar ) {
    lastLine = mNVisibleLines - 1;
  } else {
    if ( !position_to_line( endpos, &lastLine ) ) {
      /* shouldn't happen */
      lastLine = mNVisibleLines - 1;
    }
  }

  /* Get the starting and ending positions within the lines */
  startIndex = mLineStarts[ startLine ] == -1 ? 0 :
               startpos - mLineStarts[ startLine ];
  if ( endpos >= mLastChar )
    endIndex = INT_MAX;
  else if ( mLineStarts[ lastLine ] == -1 )
    endIndex = 0;
  else
    endIndex = endpos - mLineStarts[ lastLine ];

  /* If the starting and ending lines are the same, redisplay the single
     line between "start" and "end" */
  if ( startLine == lastLine ) {
    draw_vline( startLine, 0, INT_MAX, startIndex, endIndex );
    return;
  }

  /* Redisplay the first line from "start" */
  draw_vline( startLine, 0, INT_MAX, startIndex, INT_MAX );

  /* Redisplay the lines in between at their full width */
  for ( i = startLine + 1; i < lastLine; i++ )
    draw_vline( i, 0, INT_MAX, 0, INT_MAX );

  /* Redisplay the last line to "end" */
  draw_vline( lastLine, 0, INT_MAX, 0, endIndex );
}

/*
** Set the position of the text insertion cursor for text display
*/
void Fl_Text_Display::insert_position( int newPos ) {
  /* make sure new position is ok, do nothing if it hasn't changed */
  if ( newPos == mCursorPos )
    return;
  if ( newPos < 0 ) newPos = 0;
  if ( newPos > mBuffer->length() ) newPos = mBuffer->length();

  /* cursor movement cancels vertical cursor motion column */
  mCursorPreferredCol = -1;

  /* erase the cursor at it's previous position */
  redisplay_range(mCursorPos - 1, mCursorPos + 1);

  mCursorPos = newPos;

  /* draw cursor at its new position */
  redisplay_range(mCursorPos - 1, mCursorPos + 1);
}

void Fl_Text_Display::show_cursor(int b) {
  mCursorOn = b;
  redisplay_range(mCursorPos - 1, mCursorPos + 1);
}

void Fl_Text_Display::cursor_style(int style) {
  mCursorStyle = style;
  if (mCursorOn) show_cursor();
}

void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) {
    mWrapMargin = wrapMargin;
    mContinuousWrap = wrap;
    
    /* wrapping can change change the total number of lines, re-count */
    mNBufferLines = count_lines(0, buffer()->length(), true);
    
    /* changing wrap margins wrap or changing from wrapped mode to non-wrapped
       can leave the character at the top no longer at a line start, and/or
       change the line number */
    mFirstChar = line_start(mFirstChar);
    mTopLineNum = count_lines(0, mFirstChar, true) + 1;
	 reset_absolute_top_line_number();
        
    /* update the line starts array */
    calc_line_starts(0, mNVisibleLines);
    calc_last_char();
    
#if 0
	 //	FIXME!
    /* Update the scroll bar page increment size (as well as other scroll
       bar parameters) */
    updateVScrollBarRange(textD);
    updateHScrollBarRange(textD);
    
    /* Decide if the horizontal scroll bar needs to be visible */
    hideOrShowHScrollBar(textD);

    /* Do a full redraw */
    TextDRedisplayRect(textD, 0, textD->top, textD->width + textD->left,
	    textD->height);
#else
	 resize(x(), y(), w(), h());
#endif
}

/*
** Insert "text" at the current cursor location.  This has the same
** effect as inserting the text into the buffer using BufInsert and
** then moving the insert position after the newly inserted text, except
** that it's optimized to do less redrawing.
*/
void Fl_Text_Display::insert(const char* text) {
  int pos = mCursorPos;

  mCursorToHint = pos + strlen( text );
  mBuffer->insert( pos, text );
  mCursorToHint = NO_HINT;
}

/*
** Insert "text" (which must not contain newlines), overstriking the current
** cursor location.
*/
void Fl_Text_Display::overstrike(const char* text) {
  int startPos = mCursorPos;
  Fl_Text_Buffer *buf = mBuffer;
  int lineStart = buf->line_start( startPos );
  int textLen = strlen( text );
  int i, p, endPos, indent, startIndent, endIndent;
  const char *c;
  char ch, *paddedText = NULL;

  /* determine how many displayed character positions are covered */
  startIndent = mBuffer->count_displayed_characters( lineStart, startPos );
  indent = startIndent;
  for ( c = text; *c != '\0'; c++ )
    indent += Fl_Text_Buffer::character_width( *c, indent, buf->tab_distance(), buf->null_substitution_character() );
  endIndent = indent;

  /* find which characters to remove, and if necessary generate additional

⌨️ 快捷键说明

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