TTermManip.cxx

Go to the documentation of this file.
00001 // @(#)root/editline:$Id: TTermManip.cxx 36302 2010-10-11 15:07:25Z axel $
00002 // Author: Axel Naumann, 2009
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TTermManip.h"
00013 #include <strings.h>
00014 
00015 #ifndef _MSC_VER
00016 # include "rlcurses.h"
00017 #else
00018 # include "win32vt100.h"
00019 #endif
00020 
00021 TTermManip::TTermManip():
00022    fNumColors(-1),
00023    fAnsiColors(true),
00024    fSetFg(0),
00025    fSetBold(0),
00026    fSetDefault(0),
00027    fStartUnderline(0),
00028    fStopUnderline(0),
00029    fPutc((PutcFunc_t)DefaultPutchar),
00030    fCurrentColorIdx(-1),
00031    fCurrentlyBold(false),
00032    fCurrentlyUnderlined(false)
00033 {
00034    // Initialize color management
00035    ResetTerm();
00036    // Use colors where possible
00037    fNumColors = GetTermNum("colors");
00038    if (fNumColors > 1) {
00039       fSetFg = GetTermStr("setaf");
00040       fAnsiColors = true;
00041 
00042       if (!fSetFg) {
00043          fSetFg = GetTermStr("setf");
00044          fAnsiColors = false;
00045       }
00046    }
00047 
00048    fSetBold = GetTermStr("bold");
00049    // "sgr0" doesn't reset window size
00050    fSetDefault = GetTermStr("sgr0");
00051 
00052    if (!fSetDefault) {
00053       fSetDefault = GetTermStr("rs2");
00054    }
00055    fStartUnderline = GetTermStr("smul");
00056    fStopUnderline = GetTermStr("rmul");
00057 }
00058 
00059 
00060 void
00061 TTermManip::SetDefaultColor() {
00062    // Set terminal to the default color.
00063    if (fCurrentlyBold || fCurrentColorIdx != -1) {
00064       WriteTerm(fSetDefault);
00065       fCurrentlyBold = false;
00066       fCurrentColorIdx = -1;
00067    }
00068    if (fCurrentlyUnderlined) {
00069       WriteTerm(fStopUnderline);
00070       fCurrentlyUnderlined = false;      
00071    }
00072 }
00073 
00074 void
00075 TTermManip::StartBold() {
00076    // want bold
00077    if (!fCurrentlyBold) {
00078       if (fSetBold) {
00079          WriteTerm(fSetBold);
00080       }
00081       fCurrentlyBold = true;
00082    }
00083 }
00084 
00085 
00086 void
00087 TTermManip::StopBold() {
00088    // turn bold off
00089    if (fCurrentlyBold) {
00090       if (fSetDefault && fCurrentlyBold) {
00091          WriteTerm(fSetDefault);
00092       }
00093       fCurrentlyBold = false;
00094       if (fCurrentColorIdx != -1) {
00095          int ci = fCurrentColorIdx;
00096          fCurrentColorIdx = -1;
00097          SetColor(ci);
00098       }
00099    }
00100 }
00101 
00102 
00103 int
00104 TTermManip::GetColorIndex(unsigned char r, unsigned char g, unsigned char b) {
00105    // Determine the color index givenan RGB triplet, each within [0..255].
00106    int idx = -1;
00107 
00108    if (fNumColors > 255) {
00109       static unsigned char rgb256[256][3] = {{0}};
00110       if (rgb256[0][0] == 0) {
00111          // initialize the array with the expected standard colors:
00112          // (from http://frexx.de/xterm-256-notes)
00113          unsigned char rgbidx = 0;
00114          // this is not what I see, though it's supposedly the default:
00115          //   rgb[0][0] =   0; rgb[0][1] =   0; rgb[0][1] =   0;
00116          // use this instead, just to be on the safe side:
00117          rgb256[0][0] =  46; rgb256[0][1] =  52; rgb256[0][1] =  64;
00118          rgb256[1][0] = 205; rgb256[1][1] =   0; rgb256[1][1] =   0;
00119          rgb256[2][0] =   0; rgb256[2][1] = 205; rgb256[2][1] =   0;
00120          rgb256[3][0] = 205; rgb256[3][1] = 205; rgb256[3][1] =   0;
00121          rgb256[4][0] =   0; rgb256[4][1] =   0; rgb256[4][1] = 238;
00122          rgb256[5][0] = 205; rgb256[5][1] =   0; rgb256[5][1] = 205;
00123          rgb256[6][0] =   0; rgb256[6][1] = 205; rgb256[6][1] = 205;
00124          rgb256[7][0] = 229; rgb256[7][1] = 229; rgb256[7][1] = 229;
00125 
00126          // this is not what I see, though it's supposedly the default:
00127          //   rgb256[ 8][0] = 127; rgb256[ 8][1] = 127; rgb256[ 8][1] = 127;
00128          // use this instead, just to be on the safe side:
00129          rgb256[ 8][0] =   0; rgb256[ 8][1] =   0; rgb256[ 8][1] =   0;
00130          rgb256[ 9][0] = 255; rgb256[ 9][1] =   0; rgb256[ 9][1] =   0;
00131          rgb256[10][0] =   0; rgb256[10][1] = 255; rgb256[10][1] =   0;
00132          rgb256[11][0] = 255; rgb256[11][1] = 255; rgb256[11][1] =   0;
00133          rgb256[12][0] =  92; rgb256[12][1] =  92; rgb256[12][1] = 255;
00134          rgb256[13][0] = 255; rgb256[13][1] =   0; rgb256[13][1] = 255;
00135          rgb256[14][0] =   0; rgb256[14][1] = 255; rgb256[14][1] = 255;
00136          rgb256[15][0] = 255; rgb256[15][1] = 255; rgb256[15][1] = 255;
00137 
00138          for (unsigned char red = 0; red < 6; ++red) {
00139             for (unsigned char green = 0; green < 6; ++green) {
00140                for (unsigned char blue = 0; blue < 6; ++blue) {
00141                   rgbidx = 16 + (red * 36) + (green * 6) + blue;
00142                   rgb256[rgbidx][0] = red ? (red * 40 + 55) : 0;
00143                   rgb256[rgbidx][1] = green ? (green * 40 + 55) : 0;
00144                   rgb256[rgbidx][2] = blue ? (blue * 40 + 55) : 0;
00145                }
00146             }
00147          }
00148          // colors 232-255 are a grayscale ramp, intentionally leaving out
00149          // black and white
00150          for (unsigned char gray = 0; gray < 24; ++gray) {
00151             unsigned char level = (gray * 10) + 8;
00152             rgb256[232 + gray][0] = level;
00153             rgb256[232 + gray][1] = level;
00154             rgb256[232 + gray][2] = level;
00155          }
00156       }
00157 
00158       // Find the closest index.
00159       // A: the closest color match (square of geometric distance in RGB)
00160       // B: the closest brightness match
00161       // Treat them equally, which suppresses differences
00162       // in color due to squared distance.
00163 
00164       // start with black:
00165       idx = 0;
00166       int graylvl = (r + g + b)/3;
00167       long mindelta = (r*r + g*g + b*b) + graylvl;
00168       if (mindelta) {
00169          for (unsigned int i = 1; i < 256; ++i) {
00170             long delta = (rgb256[i][0] + rgb256[i][1] + rgb256[i][2])/3 - graylvl;
00171             if (delta < 0) delta = -delta;
00172             delta += (r-rgb256[i][0])*(r-rgb256[i][0]) +
00173                      (g-rgb256[i][1])*(g-rgb256[i][1]) +
00174                      (b-rgb256[i][2])*(b-rgb256[i][2]);
00175             
00176             if (delta < mindelta) {
00177                mindelta = delta;
00178                idx = i;
00179                if (mindelta == 0) break;
00180             }
00181          }
00182       }
00183    } else if (fNumColors > 1) {
00184       int sum = r + g + b;
00185       r = r > sum / 4;
00186       g = g > sum / 4;
00187       b = b > sum / 4;
00188 
00189       if (fAnsiColors) {
00190          idx = r + (g * 2) + (b * 4);
00191       } else {
00192          idx = (r * 4) + (g * 2) + b;
00193       }
00194    }
00195    return idx;
00196 }
00197 
00198 bool
00199 TTermManip::SetColor(unsigned char r, unsigned char g, unsigned char b) {
00200    // RGB colors range from 0 to 255
00201    return SetColor(GetColorIndex(r, g, b));
00202 }
00203 
00204 bool
00205 TTermManip::SetColor(int idx) {
00206    // Set color to a certain index as returned by GetColorIdx.
00207    if (fSetFg && idx != fCurrentColorIdx) {
00208       WriteTerm(fSetFg, idx);
00209       fCurrentColorIdx = idx;
00210    }
00211    return true;
00212 } // SetColor
00213 
00214 
00215 char*
00216 TTermManip::GetTermStr(const char* cap) {
00217    char capid[10];
00218    strncpy(capid, cap, sizeof(capid) - 1);
00219    capid[sizeof(capid) - 1] = 0; // force 0 termination
00220    char* termstr = tigetstr(capid);
00221 
00222    if (termstr == (char*) -1) {
00223       //printf("ERROR unknown capability %s\n", cap);
00224       return NULL;
00225    } else if (termstr == 0) {
00226       // printf("ERROR capability %s not supported\n", cap);
00227       return NULL;
00228    }
00229    return termstr;
00230 }
00231 
00232 int
00233 TTermManip::GetTermNum(const char* cap) {
00234    char capid[10];
00235    strncpy(capid, cap, sizeof(capid) - 1);
00236    capid[sizeof(capid) - 1] = 0; // force 0 termination
00237    return tigetnum(capid);
00238 }
00239 
00240 
00241 bool
00242 TTermManip::ResetTerm() {
00243    WriteTerm(fSetDefault);
00244    WriteTerm(fStopUnderline);
00245 
00246    fCurrentColorIdx = -1;
00247    fCurrentlyBold = false;
00248    fCurrentlyUnderlined = false;
00249    return true;
00250 } // ResetTerm
00251 
00252 
00253 bool
00254 TTermManip::WriteTerm(char* termstr) {
00255    if (!termstr) {
00256       return false;
00257    }
00258    tputs(tparm(termstr, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1, fPutc);
00259 
00260    /*if (tputs(tparm(termstr, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1, fPutc) == ERR) {
00261       printf("ERROR writing %s\n", termstr);
00262       return false;
00263       }*/
00264    fflush(stdout);
00265    return true;
00266 }
00267 
00268 
00269 bool
00270 TTermManip::WriteTerm(char* termstr, int i) {
00271    if (!termstr) {
00272       return false;
00273    }
00274    tputs(tparm(termstr, i, 0, 0, 0, 0, 0, 0, 0, 0), 1, fPutc);
00275 
00276    /*if (tputs(tparm(termstr, i, 0, 0, 0, 0, 0, 0, 0, 0), 1, fPutc) == ERR) {
00277       printf("ERROR writing %s %d\n", termstr, i);
00278       return false;
00279       }*/
00280    fflush(stdout);
00281    return true;
00282 }
00283 
00284 
00285 #ifdef TEST_TERMMANIP
00286 void
00287 testcolor(TTermManip& tm, int r, int g, int b) {
00288    tm.SetColor(r, g, b);
00289 
00290    if (r % 2) {
00291       tm.StartUnderline();
00292    }
00293    printf("HELLO %d %d %d\n", r, g, b);
00294 
00295    if (r % 2) {
00296       tm.StopUnderline();
00297    }
00298 }
00299 
00300 
00301 void
00302 testall(TTermManip& tm, int h) {
00303    testcolor(tm, h, 0, 0);
00304    testcolor(tm, 0, h, 0);
00305    testcolor(tm, 0, 0, h);
00306    testcolor(tm, h, h, 0);
00307    testcolor(tm, h, 0, h);
00308    testcolor(tm, 0, h, h);
00309    testcolor(tm, h, h, h);
00310 }
00311 
00312 
00313 int
00314 main(int, char*[]) {
00315    int errcode;
00316 
00317    if (ERR == setupterm(0, 1, &errcode)) {
00318       printf("ERROR in setupterm: %d\n", errcode);
00319       return 1;
00320    }
00321    TTermManip tm;
00322    testall(tm, 31);
00323    testall(tm, 127);
00324    testall(tm, 128);
00325    testall(tm, 255);
00326 
00327    testcolor(tm, 0, 0, 0);
00328 
00329    return 0;
00330 } // main
00331 
00332 
00333 #endif

Generated on Tue Jul 5 14:11:39 2011 for ROOT_528-00b_version by  doxygen 1.5.1