00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00035 ResetTerm();
00036
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
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
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
00077 if (!fCurrentlyBold) {
00078 if (fSetBold) {
00079 WriteTerm(fSetBold);
00080 }
00081 fCurrentlyBold = true;
00082 }
00083 }
00084
00085
00086 void
00087 TTermManip::StopBold() {
00088
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
00106 int idx = -1;
00107
00108 if (fNumColors > 255) {
00109 static unsigned char rgb256[256][3] = {{0}};
00110 if (rgb256[0][0] == 0) {
00111
00112
00113 unsigned char rgbidx = 0;
00114
00115
00116
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
00127
00128
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
00149
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
00159
00160
00161
00162
00163
00164
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
00201 return SetColor(GetColorIndex(r, g, b));
00202 }
00203
00204 bool
00205 TTermManip::SetColor(int idx) {
00206
00207 if (fSetFg && idx != fCurrentColorIdx) {
00208 WriteTerm(fSetFg, idx);
00209 fCurrentColorIdx = idx;
00210 }
00211 return true;
00212 }
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;
00220 char* termstr = tigetstr(capid);
00221
00222 if (termstr == (char*) -1) {
00223
00224 return NULL;
00225 } else if (termstr == 0) {
00226
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;
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 }
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
00261
00262
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
00277
00278
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 }
00331
00332
00333 #endif