PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/nil-ng/src/client/console/SdlConsole.cc

#
C++ | 283 lines | 225 code | 38 blank | 20 comment | 28 complexity | 058c2a2f1f0492cfd36e25f35aa5f03e MD5 | raw file
Possible License(s): AGPL-1.0, GPL-3.0
  1. /********************************************************************************
  2. * NiL isn't Liero
  3. * SdlConsole.cc - SDL-based console implementation
  4. *
  5. * Copyright (C) 2005,2006,2007 Alexander Kahl <e-user@gmx.net>
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. *****************************************************************************/
  21. #include <client/SdlConsole.h>
  22. #include <VFS.h>
  23. #include <string>
  24. #include <sstream>
  25. #include <cmath>
  26. #include <sys/types.h>
  27. #include <regex.h>
  28. #include <malloc.h>
  29. SdlConsole::SdlConsole(IConsole::Severity minimum, SdlConsole::Mode _mode)
  30. : IConsole(minimum), Interactive(), Movable(), mode(_mode)
  31. {
  32. this->initialize();
  33. *this->cmessage << "SDL console started!" << IConsole::endl;
  34. }
  35. SdlConsole::~SdlConsole()
  36. {
  37. *IConsole::primary()->cmessage << "Closing SDL console..." << IConsole::endl;
  38. delete this->nil_logo;
  39. for(std::vector<Font*>::iterator i = this->font_table.begin(); i < this->font_table.end(); i++)
  40. delete *i;
  41. }
  42. void
  43. SdlConsole::initialize()
  44. {
  45. Graphics& graphics = Graphics::instance();
  46. try
  47. {
  48. this->nil_logo = new GraphicItem("data/gfx/logos/nil_small.png");
  49. this->nil_logo->destination.x += graphics.width() - (this->nil_logo->destination.w + 1);
  50. }
  51. catch(NilException ex) // TODO: Replace with appropriate exception
  52. {
  53. *this->cerror << "Error loading NiL logo!" << IConsole::endl;
  54. this->nil_logo = NULL;
  55. }
  56. Font* font;
  57. font = new Font(this, "data/fonts/DejaVu LGC Sans Mono.ttf", 8, Graphics::create_color(0x3d, 0x45, 0xb3), Font::NORMAL);
  58. this->font_table.push_back(font);
  59. font = new Font(this, "data/fonts/DejaVu LGC Sans Mono.ttf", 8, Graphics::create_color(0xff, 0xff, 0xff), Font::NORMAL);
  60. this->font_table.push_back(font);
  61. font = new Font(this, "data/fonts/DejaVu LGC Sans Mono.ttf", 8, Graphics::create_color(0xf2, 0xff, 0x23), Font::NORMAL);
  62. this->font_table.push_back(font);
  63. font = new Font(this, "data/fonts/DejaVu LGC Sans Mono.ttf", 8, Graphics::create_color(0xd9, 0x2d, 0x2d), Font::NORMAL);
  64. this->font_table.push_back(font);
  65. font = new Font(this, "data/fonts/DejaVu LGC Sans Mono.ttf", 8, Graphics::create_color(0xbf, 0x2d, 0xd9), Font::NORMAL);
  66. this->font_table.push_back(font);
  67. switch (this->mode)
  68. {
  69. case SdlConsole::INACTIVE:
  70. this->height = 0;
  71. break;
  72. case SdlConsole::ACTIVE:
  73. this->height = graphics.height() / 4;
  74. break;
  75. case SdlConsole::FULLSCREEN:
  76. this->height = graphics.height();
  77. break;
  78. }
  79. }
  80. void
  81. SdlConsole::set_mode(SdlConsole::Mode _mode)
  82. {
  83. this->mode = _mode;
  84. switch(this->mode)
  85. {
  86. case SdlConsole::INACTIVE:
  87. case SdlConsole::FULLSCREEN:
  88. this->movement.second = -100;
  89. break;
  90. case SdlConsole::ACTIVE:
  91. this->movement.second = 100;
  92. break;
  93. default:
  94. break;
  95. }
  96. }
  97. void
  98. SdlConsole::put_output(std::string message)
  99. {
  100. this->buffer += message;
  101. this->history += message;
  102. }
  103. void
  104. SdlConsole::clear()
  105. {
  106. this->buffer.clear();
  107. }
  108. void
  109. SdlConsole::draw()
  110. {
  111. if(this->movement.second)
  112. this->move();
  113. Graphics::instance().blit(this->nil_logo->image, &this->nil_logo->destination);
  114. IConsole::Severity level = this->chattiness;
  115. Font *font = this->font_table.at(level);
  116. unsigned int x = 0;
  117. int y = this->height - 2 * font->advance_y();
  118. int index = (int)this->buffer.find_last_of("\n", this->buffer.size() - 2);
  119. int limit = 0 - (int)font->advance_y();
  120. while(index != -1 && y > limit)
  121. {
  122. if(index == (int)std::string::npos)
  123. index = -1;
  124. for(std::string::size_type i = index + 1; this->buffer.at(i) != '\n'; i++)
  125. {
  126. char c = this->buffer.at(i);
  127. if(c == '\033')
  128. i = this->format_output(this->buffer, i + 1, &level);
  129. else
  130. {
  131. font = this->font_table.at(level);
  132. SDL_Surface* glyph_surface = font->render_glyph(c);
  133. SDL_Rect destination_rect = glyph_surface->clip_rect;
  134. destination_rect.x = x + font->minimum_x(c) + 2;
  135. destination_rect.y = y + (font->advance_y() - font->maximum_y(c));
  136. Graphics::instance().blit(glyph_surface, &destination_rect);
  137. x += font->advance_x(c);
  138. }
  139. }
  140. index = this->buffer.find_last_of("\n", index - 1);
  141. x = 0;
  142. y -= font->advance_y();
  143. }
  144. }
  145. int
  146. SdlConsole::format_output(std::string& sequence,
  147. std::string::size_type pos,
  148. IConsole::Severity* level) const
  149. {
  150. std::stringstream reader;
  151. int code;
  152. struct re_pattern_buffer* pattern_buffer = (struct re_pattern_buffer*) malloc(sizeof(struct re_pattern_buffer));
  153. pattern_buffer->translate = 0;
  154. pattern_buffer->fastmap = 0;
  155. pattern_buffer->buffer = 0;
  156. pattern_buffer->allocated = 0;
  157. re_compile_pattern("^[[0-9;]+m", 10, pattern_buffer);
  158. int length = sequence.substr(pos).size();
  159. if(re_search(pattern_buffer, sequence.substr(pos).c_str(), length, 0, length, 0) != -1)
  160. {
  161. pos++;
  162. for(char c = ' '; c != 'm'; pos++)
  163. {
  164. c = sequence.at(pos);
  165. if(c != ';' && c != 'm')
  166. reader << c;
  167. else
  168. {
  169. reader >> code;
  170. switch(code)
  171. {
  172. case 34: // Blue
  173. *level = IConsole::DEBUG;
  174. break;
  175. case 39: // White
  176. *level = IConsole::MESSAGE;
  177. break;
  178. case 33: // Yellow
  179. *level = IConsole::WARNING;
  180. break;
  181. case 31: // Red
  182. *level = IConsole::ERROR;
  183. break;
  184. case 35: // Purple
  185. *level = IConsole::FATAL;
  186. break;
  187. }
  188. reader.clear();
  189. }
  190. }
  191. }
  192. regfree(pattern_buffer);
  193. return pos - 1;
  194. }
  195. void
  196. SdlConsole::move()
  197. {
  198. Graphics& graphics = Graphics::instance();
  199. switch(this->mode)
  200. {
  201. case SdlConsole::INACTIVE:
  202. if(this->height / abs((int)this->movement.second) > 0)
  203. this->height += (int)this->movement.second;
  204. else
  205. {
  206. this->height = 0;
  207. this->movement.second = 0;
  208. }
  209. break;
  210. case SdlConsole::ACTIVE:
  211. if(this->height + this->movement.second < graphics.height() / 4)
  212. this->height += (int)this->movement.second;
  213. else
  214. {
  215. this->height = graphics.height() / 4;
  216. this->movement.second = 0;
  217. }
  218. break;
  219. case SdlConsole::FULLSCREEN:
  220. if(this->height + this->movement.second < graphics.height())
  221. this->height += (int)this->movement.second;
  222. else
  223. {
  224. this->height = graphics.height();
  225. this->movement.second = 0;
  226. }
  227. default:
  228. break;
  229. }
  230. }
  231. void
  232. SdlConsole::_handle_keyboard_event(SDL_Event event)
  233. {
  234. if(event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_CARET)
  235. {
  236. if(this->mode == SdlConsole::INACTIVE)
  237. this->set_mode(SdlConsole::ACTIVE);
  238. else
  239. this->set_mode(SdlConsole::INACTIVE);
  240. }
  241. }
  242. void
  243. SdlConsole::_handle_mouse_event(SDL_Event event)
  244. {
  245. }