mod/maxgui.mod/fltkmaxgui.mod/src/Fl_Text_Display.cxx
int Fl_Text_Display::handle_vline(
                                  int mode, 
                                  int lineStartPos, int lineLen, int leftChar, int rightChar,
                                  int Y, int bottomClip,
                                  int leftClip, int rightClip) const
{
  IS_UTF8_ALIGNED2(buffer(), lineStartPos)

  // FIXME: we need to allow two modes for FIND_INDEX: one on the edge of the 
  // FIXME: character for selection, and one on the character center for cursors.
  int i, X, startX, startIndex, style, charStyle;
  char *lineStr;
  
  if ( lineStartPos == -1 ) {
    lineStr = NULL;
  } else {
    lineStr = mBuffer->text_range( lineStartPos, lineStartPos + lineLen );
  }
  
  if (mode==GET_WIDTH) {
    X = 0;
  } else if (mode==FIND_INDEX_FROM_ZERO) {
    X = 0; 
    mode = FIND_INDEX;
  } else {
    X = text_area.x - mHorizOffset;
  }
  
  startX = X;
  startIndex = 0;
  if (!lineStr) {
    // just clear the background
    if (mode==DRAW_LINE) {
      style = position_style(lineStartPos, lineLen, -1);
      draw_string( style|BG_ONLY_MASK, text_area.x, Y, text_area.x+text_area.w, lineStr, lineLen );
    }
    if (mode==FIND_INDEX) {
      IS_UTF8_ALIGNED2(buffer(), lineStartPos)
      return lineStartPos;
    }
    return 0;
  }
  
  char currChar = 0, prevChar = 0;
  // draw the line
  style = position_style(lineStartPos, lineLen, 0);
  for (i=0; i<lineLen; ) {
    currChar = lineStr[i]; // one byte is enough to handele tabs and other cases
    int len = fl_utf8len(currChar);
    if (len<=0) len = 1; // OUCH!
    charStyle = position_style(lineStartPos, lineLen, i);
    if (charStyle!=style || currChar=='\t' || prevChar=='\t') {
      // draw a segment whenever the style changes or a Tab is found
      int w = 0;
      if (prevChar=='\t') {
        // draw a single Tab space
        int tab = col_to_x(4);
        int xAbs = (mode==GET_WIDTH) ? startX : startX+mHorizOffset-text_area.x;
        w = (((xAbs/tab)+1)*tab) - xAbs;
        if (mode==DRAW_LINE)
          draw_string( style|BG_ONLY_MASK, startX, Y, startX+w, 0, 0 );
        if (mode==FIND_INDEX && startX+w>rightClip) {
          // find x pos inside block
          free(lineStr);
          return lineStartPos + startIndex;
        }
      } else {
        // draw a text segment
        w = int( string_width( lineStr+startIndex, i-startIndex, style ) );
        if (mode==DRAW_LINE)
          draw_string( style, startX, Y, startX+w, lineStr+startIndex, i-startIndex );
        if (mode==FIND_INDEX && startX+w>rightClip) {
          // find x pos inside block
          int di = find_x(lineStr+startIndex, i-startIndex, style, rightClip-startX);
          free(lineStr);
          IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di))
          return lineStartPos + startIndex + di;
        }
      }
      style = charStyle;
      startX += w;
      startIndex = i;
    }
    i += len;
    prevChar = currChar;
  }
  int w = 0;
  if (currChar=='\t') {
    // draw a single Tab space
    int tab = col_to_x(4);
    int xAbs = (mode==GET_WIDTH) ? startX : startX+mHorizOffset-text_area.x;
    w = (((xAbs/tab)+1)*tab) - xAbs;
    if (mode==DRAW_LINE)
      draw_string( style|BG_ONLY_MASK, startX, Y, startX+w, 0, 0 );
    if (mode==FIND_INDEX) {
      // find x pos inside block
      free(lineStr);
      return lineStartPos + startIndex + ( rightClip-startX>w ? 1 : 0 );
    }
  } else {
    w = int( string_width( lineStr+startIndex, i-startIndex, style ) );
    if (mode==DRAW_LINE)
      draw_string( style, startX, Y, startX+w, lineStr+startIndex, i-startIndex );
    if (mode==FIND_INDEX) {
      // find x pos inside block
      int di = find_x(lineStr+startIndex, i-startIndex, style, rightClip-startX);
      free(lineStr);
      IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di))
      return lineStartPos + startIndex + di;
    }
  }
  if (mode==GET_WIDTH) {
    free(lineStr);
    return startX+w;
  }
  
  // clear the rest of the line
  startX += w;
  style = position_style(lineStartPos, lineLen, i);
  if (mode==DRAW_LINE)
    draw_string( style|BG_ONLY_MASK, startX, Y, text_area.x+text_area.w, lineStr, lineLen );
  
  free(lineStr);
  IS_UTF8_ALIGNED2(buffer(), (lineStartPos+lineLen))
  return lineStartPos + lineLen;
}
/**
 Universal pixel machine.
 
 We use a single function that handles all line layout, measuring, and drawing
  * draw a text range
  * return the width of a text range in pixels
  * return the index of a char that is at a pixel position
  
 \param[in] mode DRAW_LINE, GET_WIDTH, FIND_INDEX
 \param[in] lineStartPos index of first character
 \param[in] lineLen size of string in bytes
 \param[in] leftChar, rightChar
 \param[in] Y drawing position
 \param[in] bottomClip, leftClip, rightClip stop work when we reach the clipped 
            area. rightClip is the X position that we serach in FIND_INDEX.
 \retval DRAW_LINE index of last drawn character
 \retval GET_WIDTH width in pixels of text segment if we would draw it
 \retval FIND_INDEX index of character at given x position in window coordinates
 \retval FIND_INDEX_FROM_ZERO index of character at given x position without scrolling and widget offsets
 \todo we need to handle hidden hyphens and tabs here!
 \todo we handle all styles and selections 
 \todo we must provide code to get pixel positions of the middle of a character as well
 */
Universal pixel machine.
We use a single function that handles all line layout, measuring, and drawing
draw a text range
return the width of a text range in pixels
return the index of a char that is at a pixel position


Universal pixel machine . We use a single function that handles all line layout measuring and drawing draw a text range return the width of a text range in pixels return the index of a char that is at a pixel position
int Fl_Text_Display::handle_vline(
                                  int mode, 
                                  int lineStartPos, int lineLen, int leftChar, int rightChar,
                                  int Y, int bottomClip,
                                  int leftClip, int rightClip) const
{
  IS_UTF8_ALIGNED2(buffer(), lineStartPos)
  int i, X, startX, startIndex, style, charStyle;
  char *lineStr;
  if ( lineStartPos == -1 ) {
    lineStr = NULL;
  } else {
    lineStr = mBuffer->text_range( lineStartPos, lineStartPos + lineLen );
  }
  if (mode==GET_WIDTH) {
    X = 0;
  } else if (mode==FIND_INDEX_FROM_ZERO) {
    X = 0; 
    mode = FIND_INDEX;
  } else {
    X = text_area.x - mHorizOffset;
  }
  startX = X;
  startIndex = 0;
  if (!lineStr) {
    if (mode==DRAW_LINE) {
      style = position_style(lineStartPos, lineLen, -1);
      draw_string( style|BG_ONLY_MASK, text_area.x, Y, text_area.x+text_area.w, lineStr, lineLen );
    }
    if (mode==FIND_INDEX) {
      IS_UTF8_ALIGNED2(buffer(), lineStartPos)
      return lineStartPos;
    }
    return 0;
  }
  char currChar = 0, prevChar = 0;
  style = position_style(lineStartPos, lineLen, 0);
  for (i=0; i<lineLen; ) {
    currChar = lineStr[i]; 
    int len = fl_utf8len(currChar);
    if (len<=0) len = 1; 
    charStyle = position_style(lineStartPos, lineLen, i);
    if (charStyle!=style || currChar=='\t' || prevChar=='\t') {
      int w = 0;
      if (prevChar=='\t') {
        int tab = col_to_x(4);
        int xAbs = (mode==GET_WIDTH) ? startX : startX+mHorizOffset-text_area.x;
        w = (((xAbs/tab)+1)*tab) - xAbs;
        if (mode==DRAW_LINE)
          draw_string( style|BG_ONLY_MASK, startX, Y, startX+w, 0, 0 );
        if (mode==FIND_INDEX && startX+w>rightClip) {
          free(lineStr);
          return lineStartPos + startIndex;
        }
      } else {
        w = int( string_width( lineStr+startIndex, i-startIndex, style ) );
        if (mode==DRAW_LINE)
          draw_string( style, startX, Y, startX+w, lineStr+startIndex, i-startIndex );
        if (mode==FIND_INDEX && startX+w>rightClip) {
          int di = find_x(lineStr+startIndex, i-startIndex, style, rightClip-startX);
          free(lineStr);
          IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di))
          return lineStartPos + startIndex + di;
        }
      }
      style = charStyle;
      startX += w;
      startIndex = i;
    }
    i += len;
    prevChar = currChar;
  }
  int w = 0;
  if (currChar=='\t') {
    int tab = col_to_x(4);
    int xAbs = (mode==GET_WIDTH) ? startX : startX+mHorizOffset-text_area.x;
    w = (((xAbs/tab)+1)*tab) - xAbs;
    if (mode==DRAW_LINE)
      draw_string( style|BG_ONLY_MASK, startX, Y, startX+w, 0, 0 );
    if (mode==FIND_INDEX) {
      free(lineStr);
      return lineStartPos + startIndex + ( rightClip-startX>w ? 1 : 0 );
    }
  } else {
    w = int( string_width( lineStr+startIndex, i-startIndex, style ) );
    if (mode==DRAW_LINE)
      draw_string( style, startX, Y, startX+w, lineStr+startIndex, i-startIndex );
    if (mode==FIND_INDEX) {
      int di = find_x(lineStr+startIndex, i-startIndex, style, rightClip-startX);
      free(lineStr);
      IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di))
      return lineStartPos + startIndex + di;
    }
  }
  if (mode==GET_WIDTH) {
    free(lineStr);
    return startX+w;
  }
  startX += w;
  style = position_style(lineStartPos, lineLen, i);
  if (mode==DRAW_LINE)
    draw_string( style|BG_ONLY_MASK, startX, Y, text_area.x+text_area.w, lineStr, lineLen );
  free(lineStr);
  IS_UTF8_ALIGNED2(buffer(), (lineStartPos+lineLen))
  return lineStartPos + lineLen;
}
int Fl_Text_Display :: handle_vline ( int mode , int lineStartPos , int lineLen , int leftChar , int rightChar , int Y , int bottomClip , int leftClip , int rightClip ) const { IS_UTF8_ALIGNED2 ( buffer ( ) , lineStartPos ) int i , X , startX , startIndex , style , charStyle ; char * lineStr ; if ( lineStartPos == -1 ) { lineStr = NULL ; } else { lineStr = mBuffer -> text_range ( lineStartPos , lineStartPos + lineLen ) ; } if ( mode == GET_WIDTH ) { X = 0 ; } else if ( mode == FIND_INDEX_FROM_ZERO ) { X = 0 ; mode = FIND_INDEX ; } else { X = text_area . x - mHorizOffset ; } startX = X ; startIndex = 0 ; if ( ! lineStr ) { if ( mode == DRAW_LINE ) { style = position_style ( lineStartPos , lineLen , -1 ) ; draw_string ( style | BG_ONLY_MASK , text_area . x , Y , text_area . x + text_area . w , lineStr , lineLen ) ; } if ( mode == FIND_INDEX ) { IS_UTF8_ALIGNED2 ( buffer ( ) , lineStartPos ) return lineStartPos ; } return 0 ; } char currChar = 0 , prevChar = 0 ; style = position_style ( lineStartPos , lineLen , 0 ) ; for ( i = 0 ; i < lineLen ; ) { currChar = lineStr [ i ] ; int len = fl_utf8len ( currChar ) ; if ( len <= 0 ) len = 1 ; charStyle = position_style ( lineStartPos , lineLen , i ) ; if ( charStyle != style || currChar == ' \t ' || prevChar == ' \t ' ) { int w = 0 ; if ( prevChar == ' \t ' ) { int tab = col_to_x ( 4 ) ; int xAbs = ( mode == GET_WIDTH ) ? startX : startX + mHorizOffset - text_area . x ; w = ( ( ( xAbs / tab ) + 1 ) * tab ) - xAbs ; if ( mode == DRAW_LINE ) draw_string ( style | BG_ONLY_MASK , startX , Y , startX + w , 0 , 0 ) ; if ( mode == FIND_INDEX && startX + w > rightClip ) { free ( lineStr ) ; return lineStartPos + startIndex ; } } else { w = int ( string_width ( lineStr + startIndex , i - startIndex , style ) ) ; if ( mode == DRAW_LINE ) draw_string ( style , startX , Y , startX + w , lineStr + startIndex , i - startIndex ) ; if ( mode == FIND_INDEX && startX + w > rightClip ) { int di = find_x ( lineStr + startIndex , i - startIndex , style , rightClip - startX ) ; free ( lineStr ) ; IS_UTF8_ALIGNED2 ( buffer ( ) , ( lineStartPos + startIndex + di ) ) return lineStartPos + startIndex + di ; } } style = charStyle ; startX += w ; startIndex = i ; } i += len ; prevChar = currChar ; } int w = 0 ; if ( currChar == ' \t ' ) { int tab = col_to_x ( 4 ) ; int xAbs = ( mode == GET_WIDTH ) ? startX : startX + mHorizOffset - text_area . x ; w = ( ( ( xAbs / tab ) + 1 ) * tab ) - xAbs ; if ( mode == DRAW_LINE ) draw_string ( style | BG_ONLY_MASK , startX , Y , startX + w , 0 , 0 ) ; if ( mode == FIND_INDEX ) { free ( lineStr ) ; return lineStartPos + startIndex + ( rightClip - startX > w ? 1 : 0 ) ; } } else { w = int ( string_width ( lineStr + startIndex , i - startIndex , style ) ) ; if ( mode == DRAW_LINE ) draw_string ( style , startX , Y , startX + w , lineStr + startIndex , i - startIndex ) ; if ( mode == FIND_INDEX ) { int di = find_x ( lineStr + startIndex , i - startIndex , style , rightClip - startX ) ; free ( lineStr ) ; IS_UTF8_ALIGNED2 ( buffer ( ) , ( lineStartPos + startIndex + di ) ) return lineStartPos + startIndex + di ; } } if ( mode == GET_WIDTH ) { free ( lineStr ) ; return startX + w ; } startX += w ; style = position_style ( lineStartPos , lineLen , i ) ; if ( mode == DRAW_LINE ) draw_string ( style | BG_ONLY_MASK , startX , Y , text_area . x + text_area . w , lineStr , lineLen ) ; free ( lineStr ) ; IS_UTF8_ALIGNED2 ( buffer ( ) , ( lineStartPos + lineLen ) ) return lineStartPos + lineLen ; }
Universal pixel machine.
Universal pixel machine .
// FIXME: we need to allow two modes for FIND_INDEX: one on the edge of the  // FIXME: character for selection, and one on the character center for cursors. // just clear the background // draw the line // one byte is enough to handele tabs and other cases // OUCH! // draw a segment whenever the style changes or a Tab is found // draw a single Tab space // find x pos inside block // draw a text segment // find x pos inside block // draw a single Tab space // find x pos inside block // find x pos inside block // clear the rest of the line