00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <cstdarg>
00011 #include <cstdio>
00012 #include <cassert>
00013 #include "celutil/utf8.h"
00014 #include "gl.h"
00015 #include "vecgl.h"
00016 #include "console.h"
00017
00018 using namespace std;
00019
00020
00021 static int pmod(int n, int m)
00022 {
00023 return n >= 0 ? n % m : m - (-(n + 1) % m) - 1;
00024 }
00025
00026
00027 Console::Console(int _nRows, int _nColumns) :
00028 ostream(&sbuf),
00029 text(NULL),
00030 nRows(_nRows),
00031 nColumns(_nColumns),
00032 row(0),
00033 column(0),
00034 windowRow(0),
00035 windowHeight(10),
00036 xscale(1),
00037 yscale(1),
00038 font(NULL),
00039 autoScroll(true)
00040 {
00041 sbuf.setConsole(this);
00042 text = new wchar_t[(nColumns + 1) * nRows];
00043 for (int i = 0; i < nRows; i++)
00044 text[(nColumns + 1) * i] = '\0';
00045 }
00046
00047
00048 Console::~Console()
00049 {
00050 if (text != NULL)
00051 delete[] text;
00052 }
00053
00054
00055 void Console::begin()
00056 {
00057 glMatrixMode(GL_PROJECTION);
00058 glPushMatrix();
00059 glLoadIdentity();
00060 gluOrtho2D(0, xscale, 0, yscale);
00061 glMatrixMode(GL_MODELVIEW);
00062 glPushMatrix();
00063 glLoadIdentity();
00064 glTranslatef(0.125f, 0.125f, 0);
00065
00066 glDisable(GL_LIGHTING);
00067 glDisable(GL_TEXTURE_2D);
00068 glEnable(GL_BLEND);
00069 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00070 }
00071
00072
00073 void Console::end()
00074 {
00075 glMatrixMode(GL_PROJECTION);
00076 glPopMatrix();
00077 glMatrixMode(GL_MODELVIEW);
00078 glPopMatrix();
00079 }
00080
00081
00082 void Console::render(int rowHeight)
00083 {
00084 if (font == NULL)
00085 return;
00086
00087 glEnable(GL_TEXTURE_2D);
00088 font->bind();
00089 glPushMatrix();
00090 for (int i = 0; i < rowHeight; i++)
00091 {
00092
00093 int r = pmod(row + windowRow + i, nRows);
00094 for (int j = 0; j < nColumns; j++)
00095 {
00096 wchar_t ch = text[r * (nColumns + 1) + j];
00097 if (ch == '\0')
00098 break;
00099 font->render(ch);
00100 }
00101
00102
00103 glPopMatrix();
00104 glTranslatef(0.0f, -(1.0f + font->getHeight()), 0.0f);
00105 glPushMatrix();
00106 }
00107 glPopMatrix();
00108 }
00109
00110
00111 void Console::setScale(int w, int h)
00112 {
00113 xscale = w;
00114 yscale = h;
00115 }
00116
00117
00118 void Console::setFont(TextureFont* f)
00119 {
00120 if (f != font)
00121 {
00122 font = f;
00123 }
00124 }
00125
00126
00127 void Console::newline()
00128 {
00129 assert(column <= nColumns);
00130 assert(row < nRows);
00131
00132 text[row * (nColumns + 1) + column] = '\0';
00133 row = (row + 1) % nRows;
00134 column = 0;
00135
00136 if (autoScroll)
00137 windowRow = -windowHeight;
00138 }
00139
00140 void Console::print(wchar_t c)
00141 {
00142 switch (c)
00143 {
00144 case '\n':
00145 newline();
00146 break;
00147 default:
00148 if (column == nColumns)
00149 newline();
00150 text[row * (nColumns + 1) + column] = c;
00151 column++;
00152 break;
00153 }
00154 }
00155
00156
00157 void Console::print(char* s)
00158 {
00159 int length = strlen(s);
00160 bool validChar = true;
00161 int i = 0;
00162
00163 while (i < length && validChar)
00164 {
00165 wchar_t ch = 0;
00166 validChar = UTF8Decode(s, i, length, ch);
00167 i += UTF8EncodedSize(ch);
00168 print(ch);
00169 }
00170 }
00171
00172
00173 #if 0
00174 void Console::printf(const char* format, ...)
00175 {
00176 va_list args;
00177 va_start(args, format);
00178
00179 char buf[1024];
00180 vsprintf(buf, format, args);
00181 print(buf);
00182
00183 va_end(args);
00184 }
00185 #endif
00186
00187
00188 int Console::getRow() const
00189 {
00190 return row;
00191 }
00192
00193
00194 int Console::getColumn() const
00195 {
00196 return column;
00197 }
00198
00199
00200 int Console::getWindowRow() const
00201 {
00202 return windowRow;
00203 }
00204
00205
00206 void Console::setWindowRow(int _row)
00207 {
00208 windowRow = _row;
00209 }
00210
00211
00212 void Console::setWindowHeight(int _height)
00213 {
00214 windowHeight = _height;
00215 }
00216
00217
00218 int Console::getWidth() const
00219 {
00220 return nColumns;
00221 }
00222
00223
00224 int Console::getHeight() const
00225 {
00226 return nRows;
00227 }
00228
00229
00230
00231
00232
00233 void ConsoleStreamBuf::setConsole(Console* c)
00234 {
00235 console = c;
00236 }
00237
00238 int ConsoleStreamBuf::overflow(int c)
00239 {
00240 if (console != NULL)
00241 {
00242 switch (decodeState)
00243 {
00244 case UTF8DecodeStart:
00245 if (c < 0x80)
00246 {
00247
00248 console->print((char) c);
00249 }
00250 else
00251 {
00252 unsigned int count;
00253
00254 if ((c & 0xe0) == 0xc0)
00255 count = 2;
00256 else if ((c & 0xf0) == 0xe0)
00257 count = 3;
00258 else if ((c & 0xf8) == 0xf0)
00259 count = 4;
00260 else if ((c & 0xfc) == 0xf8)
00261 count = 5;
00262 else if ((c & 0xfe) == 0xfc)
00263 count = 6;
00264 else
00265 count = 1;
00266
00267 if (count > 1)
00268 {
00269 unsigned int mask = (1 << (7 - count)) - 1;
00270 decodeShift = (count - 1) * 6;
00271 decodedChar = (c & mask) << decodeShift;
00272 decodeState = UTF8DecodeMultibyte;
00273 }
00274 else
00275 {
00276
00277
00278 }
00279 }
00280 break;
00281
00282 case UTF8DecodeMultibyte:
00283 if ((c & 0xc0) == 0x80)
00284 {
00285
00286 decodeShift -= 6;
00287 decodedChar |= (c & 0x3f) << decodeShift;
00288 if (decodeShift == 0)
00289 {
00290 console->print(decodedChar);
00291 decodeState = UTF8DecodeStart;
00292 }
00293 }
00294 else
00295 {
00296
00297
00298 decodeState = UTF8DecodeStart;
00299 }
00300 break;
00301 }
00302 }
00303
00304 return c;
00305 }