diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Text_Display.cxx | 351 |
1 files changed, 213 insertions, 138 deletions
diff --git a/src/Fl_Text_Display.cxx b/src/Fl_Text_Display.cxx index 6612595bd..b26311767 100644 --- a/src/Fl_Text_Display.cxx +++ b/src/Fl_Text_Display.cxx @@ -2022,141 +2022,148 @@ int Fl_Text_Display::handle_vline( 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; + // In DRAW_LINE mode, the first iteration of the loop will draw all + // backgrounds. The second iteration will draw the text, so that text + // overlapping background color changes will not be clipped. + for (int loop=1; loop<=2; loop++) { + int mask = (loop==1) ? BG_ONLY_MASK : TEXT_ONLY_MASK; + startX = X; + startIndex = 0; + if (!lineStr) { + // just clear the background + if (mode==DRAW_LINE) { + style = position_style(lineStartPos, lineLen, -1); + if (loop==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; } - return 0; - } - char currChar = 0, prevChar = 0; - styleX = startX; startStyle = startIndex; - // 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_utf8len1(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 - double w = 0; - if (prevChar=='\t') { - // draw a single Tab space - double tab = col_to_x(mBuffer->tab_distance()); - double xAbs = (mode==GET_WIDTH) ? startX : startX+mHorizOffset-text_area.x; - w = ((int(xAbs/tab)+1)*tab) - xAbs; - styleX = startX+w; startStyle = i; - if (mode==DRAW_LINE) - draw_string( style|BG_ONLY_MASK, int(startX), Y, int(startX+w), 0, 0 ); - if (mode==FIND_INDEX && startX+w>rightClip) { - // find x pos inside block - free(lineStr); - if (cursor_pos && (startX+w/2<rightClip)) // STR #2788 - return lineStartPos + startIndex + len; // STR #2788 - return lineStartPos + startIndex; - } - } else { - // draw the text segment from the previous style change up to this point - if ( (style&0xff)==(charStyle&0xff)) { - w = string_width( lineStr+startStyle, i-startStyle, style ) - startX + styleX; + char currChar = 0, prevChar = 0; + styleX = startX; startStyle = startIndex; + // 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_utf8len1(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 + double w = 0; + if (prevChar=='\t') { + // draw a single Tab space + double tab = col_to_x(mBuffer->tab_distance()); + double xAbs = (mode==GET_WIDTH) ? startX : startX+mHorizOffset-text_area.x; + w = ((int(xAbs/tab)+1)*tab) - xAbs; + styleX = startX+w; startStyle = i; + if (mode==DRAW_LINE && loop==1) + draw_string( style|BG_ONLY_MASK, int(startX), Y, int(startX+w), 0, 0 ); + if (mode==FIND_INDEX && startX+w>rightClip) { + // find x pos inside block + free(lineStr); + if (cursor_pos && (startX+w/2<rightClip)) // STR #2788 + return lineStartPos + startIndex + len; // STR #2788 + return lineStartPos + startIndex; + } } else { - w = string_width( lineStr+startIndex, i-startIndex, style ); - } - if (mode==DRAW_LINE) { - if (startIndex!=startStyle) { - fl_push_clip(int(startX), Y, int(w)+1, mMaxsize); - draw_string( style, int(styleX), Y, int(startX+w), lineStr+startStyle, i-startStyle ); - fl_pop_clip(); + // draw the text segment from the previous style change up to this point + if ( (style&0xff)==(charStyle&0xff)) { + w = string_width( lineStr+startStyle, i-startStyle, style ) - startX + styleX; } else { - draw_string( style, int(startX), Y, int(startX+w), lineStr+startIndex, i-startIndex ); + w = string_width( lineStr+startIndex, i-startIndex, style ); } - } - if (mode==FIND_INDEX && startX+w>rightClip) { - // find x pos inside block - int di; - if (startIndex!=startStyle) { - di = find_x(lineStr+startStyle, i-startStyle, style, -int(rightClip-styleX)); // STR #2788 - di = lineStartPos + startStyle + di; - } else { - di = find_x(lineStr+startIndex, i-startIndex, style, -int(rightClip-startX)); // STR #2788 - di = lineStartPos + startIndex + di; + if (mode==DRAW_LINE) { + if (startIndex!=startStyle) { + fl_push_clip(int(startX), Y, int(w)+1, mMaxsize); + draw_string( style|mask, int(styleX), Y, int(startX+w), lineStr+startStyle, i-startStyle ); + fl_pop_clip(); + } else { + draw_string( style|mask, int(startX), Y, int(startX+w), lineStr+startIndex, i-startIndex ); + } + } + if (mode==FIND_INDEX && startX+w>rightClip) { + // find x pos inside block + int di; + if (startIndex!=startStyle) { + di = find_x(lineStr+startStyle, i-startStyle, style, -int(rightClip-styleX)); // STR #2788 + di = lineStartPos + startStyle + di; + } else { + di = find_x(lineStr+startIndex, i-startIndex, style, -int(rightClip-startX)); // STR #2788 + di = lineStartPos + startIndex + di; + } + free(lineStr); + IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di)) + return di; + } + if ( (style&0xff)!=(charStyle&0xff)) { + startStyle = i; + styleX = startX+w; } - free(lineStr); - IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di)) - return di; - } - if ( (style&0xff)!=(charStyle&0xff)) { - startStyle = i; - styleX = startX+w; } + style = charStyle; + startX += w; + startIndex = i; } - style = charStyle; - startX += w; - startIndex = i; + i += len; + prevChar = currChar; } - i += len; - prevChar = currChar; - } - double w = 0; - if (currChar=='\t') { - // draw a single Tab space - double tab = col_to_x(mBuffer->tab_distance()); - double xAbs = (mode==GET_WIDTH) ? startX : startX+mHorizOffset-text_area.x; - w = ((int(xAbs/tab)+1)*tab) - xAbs; - if (mode==DRAW_LINE) - draw_string( style|BG_ONLY_MASK, int(startX), Y, int(startX+w), 0, 0 ); - if (mode==FIND_INDEX) { - // find x pos inside block - free(lineStr); - if (cursor_pos) // STR #2788 - return lineStartPos + startIndex + ( rightClip-startX>w/2 ? 1 : 0 ); // STR #2788 - return lineStartPos + startIndex + ( rightClip-startX>w ? 1 : 0 ); - } - } else { - w = string_width( lineStr+startIndex, i-startIndex, style ); - if (mode==DRAW_LINE) { - // STR 2531 - if (startIndex!=startStyle) { - fl_push_clip(int(startX), Y, int(w)+1, mMaxsize); - draw_string( style, int(styleX), Y, int(startX+w), lineStr+startStyle, i-startStyle ); - fl_pop_clip(); - } else { - draw_string( style, int(startX), Y, int(startX+w), lineStr+startIndex, i-startIndex ); + double w = 0; + if (currChar=='\t') { + // draw a single Tab space + double tab = col_to_x(mBuffer->tab_distance()); + double xAbs = (mode==GET_WIDTH) ? startX : startX+mHorizOffset-text_area.x; + w = ((int(xAbs/tab)+1)*tab) - xAbs; + if (mode==DRAW_LINE && loop==1) + draw_string( style|BG_ONLY_MASK, int(startX), Y, int(startX+w), 0, 0 ); + if (mode==FIND_INDEX) { + // find x pos inside block + free(lineStr); + if (cursor_pos) // STR #2788 + return lineStartPos + startIndex + ( rightClip-startX>w/2 ? 1 : 0 ); // STR #2788 + return lineStartPos + startIndex + ( rightClip-startX>w ? 1 : 0 ); } - } - if (mode==FIND_INDEX) { - // find x pos inside block - int di; - if (startIndex!=startStyle) { - di = find_x(lineStr+startStyle, i-startStyle, style, -int(rightClip-styleX)); // STR #2788 - di = lineStartPos + startStyle + di; - } else { - di = find_x(lineStr+startIndex, i-startIndex, style, -int(rightClip-startX)); // STR #2788 - di = lineStartPos + startIndex + di; + } else { + w = string_width( lineStr+startIndex, i-startIndex, style ); + if (mode==DRAW_LINE) { + // STR 2531 + if (startIndex!=startStyle) { + fl_push_clip(int(startX), Y, int(w)+1, mMaxsize); + draw_string( style|mask, int(styleX), Y, int(startX+w), lineStr+startStyle, i-startStyle ); + fl_pop_clip(); + } else { + draw_string( style|mask, int(startX), Y, int(startX+w), lineStr+startIndex, i-startIndex ); + } } + if (mode==FIND_INDEX) { + // find x pos inside block + int di; + if (startIndex!=startStyle) { + di = find_x(lineStr+startStyle, i-startStyle, style, -int(rightClip-styleX)); // STR #2788 + di = lineStartPos + startStyle + di; + } else { + di = find_x(lineStr+startIndex, i-startIndex, style, -int(rightClip-startX)); // STR #2788 + di = lineStartPos + startIndex + di; + } + free(lineStr); + IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di)) + return di; + } + } + if (mode==GET_WIDTH) { free(lineStr); - IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di)) - return di; + return int(startX+w); } - } - if (mode==GET_WIDTH) { - free(lineStr); - return int(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, int(startX), Y, text_area.x+text_area.w, lineStr, lineLen ); + // clear the rest of the line + startX += w; + style = position_style(lineStartPos, lineLen, i); + if (mode==DRAW_LINE && loop==1) + draw_string( style|BG_ONLY_MASK, int(startX), Y, text_area.x+text_area.w, lineStr, lineLen ); + } free(lineStr); IS_UTF8_ALIGNED2(buffer(), (lineStartPos+lineLen)) @@ -2267,7 +2274,7 @@ void Fl_Text_Display::draw_string(int style, const char *string, int nChars) const { IS_UTF8_ALIGNED(string) - const Style_Table_Entry * styleRec; + const Style_Table_Entry *styleRec = NULL; /* Draw blank area rather than text, if that was the request */ if ( style & FILL_MASK ) { @@ -2284,6 +2291,7 @@ void Fl_Text_Display::draw_string(int style, int fsize = textsize(); Fl_Color foreground; Fl_Color background; + Fl_Color bgbasecolor; if ( style & STYLE_LOOKUP_MASK ) { int si = (style & STYLE_LOOKUP_MASK) - 'A'; @@ -2293,19 +2301,27 @@ void Fl_Text_Display::draw_string(int style, styleRec = mStyleTable + si; font = styleRec->font; fsize = styleRec->size; + bgbasecolor = (styleRec->attr&ATTR_BGCOLOR) ? styleRec->bgcolor : color(); if (style & PRIMARY_MASK) { if (Fl::focus() == (Fl_Widget*)this) { - if (Fl::screen_driver()->has_marked_text() && Fl::compose_state) - background = color();// Mac OS: underline marked text - else + if (Fl::screen_driver()->has_marked_text() && Fl::compose_state) { + background = bgbasecolor; // Mac OS: underline marked text + } else { background = selection_color(); } - else background = fl_color_average(color(), selection_color(), 0.4f); + } else { + background = fl_color_average(bgbasecolor, selection_color(), 0.4f); + } } else if (style & HIGHLIGHT_MASK) { - if (Fl::focus() == (Fl_Widget*)this) background = fl_color_average(color(), selection_color(), 0.5f); - else background = fl_color_average(color(), selection_color(), 0.6f); - } else background = color(); + if (Fl::focus() == (Fl_Widget*)this) { + background = fl_color_average(bgbasecolor, selection_color(), 0.5f); + } else { + background = fl_color_average(bgbasecolor, selection_color(), 0.6f); + } + } else { + background = bgbasecolor; + } foreground = (style & PRIMARY_MASK) ? fl_contrast(styleRec->color, background) : styleRec->color; } else if (style & PRIMARY_MASK) { if (Fl::focus() == (Fl_Widget*)this) background = selection_color(); @@ -2332,11 +2348,44 @@ void Fl_Text_Display::draw_string(int style, if (!(style & BG_ONLY_MASK)) { fl_color( foreground ); fl_font( font, fsize ); + int baseline = Y + mMaxsize - fl_descent(); // Make sure antialiased ÄÖÜ do not leak on line above: // on X11+Xft the antialiased part of characters such as ÄÖÜ leak on the bottom pixel of the line above static int can_leak = Fl::screen_driver()->text_display_can_leak(); - if (can_leak) fl_push_clip(X, Y, toX - X, mMaxsize); - fl_draw( string, nChars, X, Y + mMaxsize - fl_descent()); + // Clip top and bottom only. Add margin to avoid clipping horizontally + if (can_leak) fl_push_clip(x(), Y, w(), mMaxsize); + fl_draw( string, nChars, X, baseline); + if (styleRec) { + if (styleRec->attr & ATTR_LINES_MASK) { + int pitch = fsize/7; + int prevAA = fl_antialias(); + fl_antialias(1); + switch (styleRec->attr & ATTR_LINES_MASK) { + case ATTR_UNDERLINE: + fl_color(foreground); + fl_line_style(FL_SOLID, pitch); + goto DRAW_UNDERLINE; + break; + case ATTR_GRAMMAR: + fl_color(FL_BLUE); + goto DRAW_DOTTED_UNDERLINE; + case ATTR_SPELLING: + fl_color(FL_RED); + DRAW_DOTTED_UNDERLINE: + fl_line_style(FL_DOT, pitch); + DRAW_UNDERLINE: + fl_xyline(X, baseline + fl_descent()/2, toX); + break; + case ATTR_STRIKE_THROUGH: + fl_color(foreground); + fl_line_style(FL_SOLID, pitch); + fl_xyline(X, baseline - (fl_height()-fl_descent())/3, toX); + break; + } + fl_line_style(FL_SOLID, 1); + fl_antialias(prevAA); + } + } if (Fl::screen_driver()->has_marked_text() && Fl::compose_state && (style & PRIMARY_MASK)) { fl_color( fl_color_average(foreground, background, 0.6f) ); fl_line(X, Y + mMaxsize - 1, X + (int)fl_width(string, nChars), Y + mMaxsize - 1); @@ -2379,21 +2428,31 @@ void Fl_Text_Display::clear_rect(int style, if ( width == 0 ) return; + Fl_Color bgbasecolor = color(); + if ( style & STYLE_LOOKUP_MASK ) { + int si = (style & STYLE_LOOKUP_MASK) - 'A'; + if (si < 0) si = 0; + else if (si >= mNStyles) si = mNStyles - 1; + const Style_Table_Entry *styleRec = mStyleTable + si; + if (styleRec->attr&ATTR_BGCOLOR_EXT_) + bgbasecolor = styleRec->bgcolor; + } + Fl_Color c; if (style & PRIMARY_MASK) { if (Fl::focus()==(Fl_Widget*)this) { c = selection_color(); } else { - c = fl_color_average(color(), selection_color(), 0.4f); + c = fl_color_average(bgbasecolor, selection_color(), 0.4f); } } else if (style & HIGHLIGHT_MASK) { if (Fl::focus()==(Fl_Widget*)this) { - c = fl_color_average(color(), selection_color(), 0.5f); + c = fl_color_average(bgbasecolor, selection_color(), 0.5f); } else { - c = fl_color_average(color(), selection_color(), 0.6f); + c = fl_color_average(bgbasecolor, selection_color(), 0.6f); } } else { - c = color(); + c = bgbasecolor; } fl_color(active_r() ? c : fl_inactive(c)); fl_rectf( X, Y, width, height ); @@ -2502,6 +2561,10 @@ void Fl_Text_Display::draw_cursor( int X, int Y ) { Note that style is a somewhat incorrect name, drawing method would be more appropriate. + If lineIndex is pointing to the last character in a line, and the second + to last character has the ATTR_BGCOLOR_EXT set, the background color will + extend into the remaining line. + \param lineStartPos beginning of this line \param lineLen number of bytes in line \param lineIndex position of character within line @@ -2520,9 +2583,21 @@ int Fl_Text_Display::position_style( int lineStartPos, int lineLen, int lineInde pos = lineStartPos + min( lineIndex, lineLen ); - if ( lineIndex >= lineLen ) + if ( styleBuf && lineIndex==lineLen && lineLen>0) { + style = ( unsigned char ) styleBuf->byte_at( pos-1 ); + if (style == mUnfinishedStyle && mUnfinishedHighlightCB) { + (mUnfinishedHighlightCB)( pos, mHighlightCBArg); + style = (unsigned char) styleBuf->byte_at( pos); + } + int si = (style & STYLE_LOOKUP_MASK) - 'A'; + if (si < 0) si = 0; + else if (si >= mNStyles) si = mNStyles - 1; + const Style_Table_Entry *styleRec = mStyleTable + si; + if ((styleRec->attr&ATTR_BGCOLOR_EXT_)==0) + style = FILL_MASK; + } else if ( lineIndex >= lineLen ) { style = FILL_MASK; - else if ( styleBuf != NULL ) { + } else if ( styleBuf != NULL ) { style = ( unsigned char ) styleBuf->byte_at( pos ); if (style == mUnfinishedStyle && mUnfinishedHighlightCB) { /* encountered "unfinished" style, trigger parsing */ |
