console.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:7k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // console.cpp
  2. //
  3. // Copyright (C) 2003, Chris Laurel <claurel@shatters.net>
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. #include <cstring>
  10. #include <cstdarg>
  11. #include <cstdio>
  12. #include <cassert>
  13. #include <algorithm>
  14. #include "celutil/utf8.h"
  15. #include "gl.h"
  16. #include "vecgl.h"
  17. #include "console.h"
  18. using namespace std;
  19. static int pmod(int n, int m)
  20. {
  21.     return n >= 0 ? n % m : m - (-(n + 1) % m) - 1;
  22. }
  23. Console::Console(int _nRows, int _nColumns) :
  24.     ostream(&sbuf),
  25.     text(NULL),
  26.     nRows(_nRows),
  27.     nColumns(_nColumns),
  28.     row(0),
  29.     column(0),
  30.     windowRow(0),
  31.     windowHeight(10),
  32.     xscale(1),
  33.     yscale(1),
  34.     font(NULL),
  35.     autoScroll(true)
  36. {
  37.     sbuf.setConsole(this);
  38.     text = new wchar_t[(nColumns + 1) * nRows];
  39.     for (int i = 0; i < nRows; i++)
  40.         text[(nColumns + 1) * i] = '';
  41. }
  42. Console::~Console()
  43. {
  44.     if (text != NULL)
  45.         delete[] text;
  46. }
  47. /*! Resize the console log to use the specified number of rows.
  48.  *  Old long entries are preserved in the resize. setRowCount()
  49.  *  returns true if it was able to successfully allocate a new
  50.  *  buffer, and false if there was a problem (out of memory.)
  51.  */
  52. bool Console::setRowCount(int _nRows)
  53. {
  54.     wchar_t* newText = new wchar_t[(nColumns + 1) * _nRows];
  55.     if (newText == NULL)
  56.         return false;
  57.     for (int i = 0; i < _nRows; i++)
  58.     {
  59.         newText[(nColumns + 1) * i] = '';
  60.     }
  61.     std::copy(newText, newText + (nColumns + 1) * min(_nRows, nRows), text);
  62.     delete[] text;
  63.     text = newText;
  64.     nRows = _nRows;
  65.     return true;
  66. }
  67. void Console::begin()
  68. {
  69.     glMatrixMode(GL_PROJECTION);
  70.     glPushMatrix();
  71.     glLoadIdentity();
  72.     gluOrtho2D(0, xscale, 0, yscale);
  73.     glMatrixMode(GL_MODELVIEW);
  74.     glPushMatrix();
  75.     glLoadIdentity();
  76.     glTranslatef(0.125f, 0.125f, 0);
  77.     glDisable(GL_LIGHTING);
  78.     glDisable(GL_TEXTURE_2D);
  79.     glEnable(GL_BLEND);
  80.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  81. }
  82. void Console::end()
  83. {
  84.     glMatrixMode(GL_PROJECTION);
  85.     glPopMatrix();
  86.     glMatrixMode(GL_MODELVIEW);
  87.     glPopMatrix();
  88. }
  89. void Console::render(int rowHeight)
  90. {
  91.     if (font == NULL)
  92.         return;
  93.     glEnable(GL_TEXTURE_2D);
  94.     font->bind();
  95.     glPushMatrix();
  96.     for (int i = 0; i < rowHeight; i++)
  97.     {
  98.         //int r = (nRows - rowHeight + 1 + windowRow + i) % nRows;
  99.         int r = pmod(row + windowRow + i, nRows);
  100.         for (int j = 0; j < nColumns; j++)
  101.         {
  102.             wchar_t ch = text[r * (nColumns + 1) + j];
  103.             if (ch == '')
  104.                 break;
  105.             font->render(ch);
  106.         }
  107.         // advance to the next line
  108.         glPopMatrix();
  109.         glTranslatef(0.0f, -(1.0f + font->getHeight()), 0.0f);
  110.         glPushMatrix();
  111.     }
  112.     glPopMatrix();
  113. }
  114. void Console::setScale(int w, int h)
  115. {
  116.     xscale = w;
  117.     yscale = h;
  118. }
  119. void Console::setFont(TextureFont* f)
  120. {
  121.     if (f != font)
  122.     {
  123.         font = f;
  124.     }
  125. }
  126. void Console::newline()
  127. {
  128.     assert(column <= nColumns);
  129.     assert(row < nRows);
  130.     text[row * (nColumns + 1) + column] = '';
  131.     row = (row + 1) % nRows;
  132.     column = 0;
  133.     if (autoScroll)
  134.         windowRow = -windowHeight;
  135. }
  136. void Console::print(wchar_t c)
  137. {
  138.     switch (c)
  139.     {
  140.     case 'n':
  141.         newline();
  142.         break;
  143.     default:
  144.         if (column == nColumns)
  145.             newline();
  146.         text[row * (nColumns + 1) + column] = c;
  147.         column++;
  148.         break;
  149.     }
  150. }
  151. void Console::print(char* s)
  152. {
  153.     int length = strlen(s);
  154.     bool validChar = true;
  155.     int i = 0;
  156.     while (i < length && validChar)
  157.     {
  158.         wchar_t ch = 0;
  159.         validChar = UTF8Decode(s, i, length, ch);
  160.         i += UTF8EncodedSize(ch);
  161.         print(ch);
  162.     }
  163. }
  164. #if 0
  165. void Console::printf(const char* format, ...)
  166. {
  167.     va_list args;
  168.     va_start(args, format);
  169.     char buf[1024];
  170.     vsprintf(buf, format, args);
  171.     print(buf);
  172.     
  173.     va_end(args);
  174. }
  175. #endif
  176. int Console::getRow() const
  177. {
  178.     return row;
  179. }
  180. int Console::getColumn() const
  181. {
  182.     return column;
  183. }
  184. int Console::getWindowRow() const
  185. {
  186.     return windowRow;
  187. }
  188. void Console::setWindowRow(int _row)
  189. {
  190.     windowRow = _row;
  191. }
  192. void Console::setWindowHeight(int _height)
  193. {
  194.     windowHeight = _height;
  195. }
  196. int Console::getWidth() const
  197. {
  198.     return nColumns;
  199. }
  200. int Console::getHeight() const
  201. {
  202.     return nRows;
  203. }
  204. //
  205. // ConsoleStreamBuf implementation
  206. //
  207. void ConsoleStreamBuf::setConsole(Console* c)
  208. {
  209.     console = c;
  210. }
  211. int ConsoleStreamBuf::overflow(int c)
  212. {
  213.     if (console != NULL)
  214.     {
  215.         switch (decodeState)
  216.         {
  217.         case UTF8DecodeStart:
  218.             if (c < 0x80)
  219.             {
  220.                 // Just a normal 7-bit character
  221.                 console->print((char) c);
  222.             }
  223.             else
  224.             {
  225.                 unsigned int count;
  226.                 if ((c & 0xe0) == 0xc0)
  227.                     count = 2;
  228.                 else if ((c & 0xf0) == 0xe0)
  229.                     count = 3;
  230.                 else if ((c & 0xf8) == 0xf0)
  231.                     count = 4;
  232.                 else if ((c & 0xfc) == 0xf8)
  233.                     count = 5;
  234.                 else if ((c & 0xfe) == 0xfc)
  235.                     count = 6;
  236.                 else
  237.                     count = 1; // Invalid byte
  238.                 if (count > 1)
  239.                 {
  240.                     unsigned int mask = (1 << (7 - count)) - 1;
  241.                     decodeShift = (count - 1) * 6;
  242.                     decodedChar = (c & mask) << decodeShift;
  243.                     decodeState = UTF8DecodeMultibyte;
  244.                 }
  245.                 else
  246.                 {
  247.                     // If the character isn't valid multibyte sequence head,
  248.                     // silently skip it by leaving the decoder state alone.
  249.                 }
  250.             }
  251.             break;
  252.         case UTF8DecodeMultibyte:
  253.             if ((c & 0xc0) == 0x80)
  254.             {
  255.                 // We have a valid non-head byte in the sequence
  256.                 decodeShift -= 6;
  257.                 decodedChar |= (c & 0x3f) << decodeShift;
  258.                 if (decodeShift == 0)
  259.                 {
  260.                     console->print(decodedChar);
  261.                     decodeState = UTF8DecodeStart;
  262.                 }
  263.             }
  264.             else
  265.             {
  266.                 // Bad byte in UTF-8 encoded sequence; we'll silently ignore
  267.                 // it and reset the state of the UTF-8 decoder.
  268.                 decodeState = UTF8DecodeStart;
  269.             }
  270.             break;
  271.         }
  272.     }
  273.     return c;
  274. }