--- Fl_Browser.cxx.orig 2007-11-24 13:01:43.000000000 -0800 +++ Fl_Browser.cxx 2008-03-10 01:19:50.653670088 -0700 @@ -31,6 +31,8 @@ #include "flstring.h" #include #include +#include // isdigit +#include "AnsiMode.H" // Ansi class // I modified this from the original Forms data to use a linked list // so that the number of items in the browser and size of those items @@ -255,12 +257,40 @@ return hmax; // previous version returned hmax+2! } +// Return copy of 'in' with ansi codes removed. +// 'ansistart' is optional: first instance of ansi from 'in' (speeds up parsing). +// Caller must free() returned string. +// +char *ansistrip(const char *in, const char *ansistart=0) { + ansistart = (!ansistart) ? in : ansistart; + int offset = (int)(ansistart-in); // chr index for first ansi + // String contains ansi: make copy + char *copy = strdup(in); // make copy we return + char *a,*b; + for ( a=b=(copy+offset); *b; ) { + if ( *b == '\033' ) { + // NOTE: only "\033[##;##" style ansi strings supported + if (*(b+1) == '[') { + b += 2; // skip "\033[" + while(*b && strchr(";0123456789", *b)) // skip args + { b++; } + if (*b) b++; // skip trailing cmd char + continue; + } + } + *a++ = *b++; // copy non-ansi + } + *a = '\0'; + return(copy); +} + int Fl_Browser::item_width(void* v) const { char* str = ((FL_BLINE*)v)->txt; const int* i = column_widths(); int ww = 0; - while (*i) { // add up all tab-seperated fields + // add up all tab-seperated fields + while (*i) { char* e; e = strchr(str, column_char()); if (!e) break; // last one occupied by text @@ -268,6 +298,16 @@ ww += *i++; } + // Handle ansi sequences, if any. + // HACK: This does not take into account bold text (wider than normal) + // To do this correctly, need to identify bold text substrings, + // and calculate their fl_width()'s separately. + // + const char *ansistart = strchr(str,'\033'); + if (ansistart) { + str = ansistrip(str,ansistart); + } + // OK, we gotta parse the string and find the string width... int tsize = textsize(); Fl_Font font = textfont(); @@ -302,7 +342,9 @@ str ++; fl_font(font, tsize); - return ww + int(fl_width(str)) + 6; + int ret = ww + (int)fl_width(str) + 6; // length returned + if ( ansistart ) { free(str); str = 0; } // free local copy we made + return(ret); } int Fl_Browser::full_height() const { @@ -327,6 +369,7 @@ int tsize = textsize(); Fl_Font font = textfont(); Fl_Color lcol = textcolor(); + Fl_Color bgcol = color(); Fl_Align talign = FL_ALIGN_LEFT; // check for all the @-lines recognized by XForms: while (*str == format_char() && *++str && *str != format_char()) { @@ -340,10 +383,11 @@ case 'c': talign = FL_ALIGN_CENTER; break; case 'r': talign = FL_ALIGN_RIGHT; break; case 'B': + bgcol = (Fl_Color)strtol(str, &str, 10); if (!(((FL_BLINE*)v)->flags & SELECTED)) { - fl_color((Fl_Color)strtol(str, &str, 10)); + fl_color(bgcol); fl_rectf(X, Y, w1, H); - } else strtol(str, &str, 10); + } break; case 'C': lcol = (Fl_Color)strtol(str, &str, 10); @@ -375,12 +419,58 @@ } } BREAK: - fl_font(font, tsize); - if (((FL_BLINE*)v)->flags & SELECTED) - lcol = fl_contrast(lcol, selection_color()); - if (!active_r()) lcol = fl_inactive(lcol); - fl_color(lcol); - fl_draw(str, X+3, Y, w1-6, H, e ? Fl_Align(talign|FL_ALIGN_CLIP) : talign, 0, 0); + { + // ANSI + AnsiMode ansi(lcol, bgcol); + int XX = X; + int WW = W; + int ww1 = w1; + char *start = str; + char *ss = start; + int done = 0; + while ( ! done ) { + if ( *ss == 0 || *ss == 033 ) { + // Anything to print? + if ( start != ss ) { + // Print what we have so far + char ts = *ss; + *ss = 0; + fl_font(font|(ansi.Bold()?FL_BOLD:0),tsize); + WW = (int)fl_width(start); + if ( WW > ww1 ) WW = ww1; // field clipping + if ( WW > 0 ) { + if (((FL_BLINE*)v)->flags & SELECTED) { + ansi.Fg(fl_contrast(ansi.Fg(),selection_color())); + } else if ( (Fl_Color)ansi.Bg() != bgcol) { + fl_color(ansi.Bg()); + fl_rectf(XX,Y,WW,H); + } + if (!active_r()) ansi.Fg(fl_inactive(textcolor())); + fl_color(ansi.Fg()); + if ( i && (*(i-1)-5) < WW ) { // column width smaller than field? clip + fl_draw(start,XX,Y,(*(i-1)-5),H,e ? Fl_Align(talign|FL_ALIGN_CLIP) : talign, 0, 0); + } else { + fl_draw(start,XX,Y,WW,H, e ? Fl_Align(talign|FL_ALIGN_CLIP) : talign, 0, 0); + } + if ( ansi.Underscore() ) fl_line(XX,Y+H-1,XX+WW-1,Y+H-1); + } + XX += WW; + ww1 -= WW; + *ss = ts; // restore char + } + // Handle ANSI escape sequence + if ( *ss == 0 ) { done = 1; continue; } + ++ss; // skip ESC + if ( *ss != '[' ) { start = ss; continue; } + ++ss; // skip '[' + ss = ansi.ParseAnsi(ss); + if ( *ss == 0 ) { done = 1; continue; } + start = ss; + continue; + } + ++ss; + } + } if (!e) break; // no more fields... *e = column_char(); // put the seperator back X += w1;