--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sdlterm/src/sdlterm.cc Sat Jan 05 00:40:27 2013 +0100
@@ -0,0 +1,251 @@
+#include "sdlterm.h"
+
+#include <stdexcept>
+
+
+GlyphRenderer::GlyphRenderer()
+ : _font_regular(NULL), _font_bold(NULL)
+{
+ if (TTF_Init() == -1)
+ {
+ printf("TTF_Init: %s\n", TTF_GetError());
+ throw std::exception();
+ }
+}
+
+
+GlyphRenderer::~GlyphRenderer()
+{
+ close_font();
+ TTF_Quit();
+}
+
+
+void GlyphRenderer::open_font(const char *fname_regular, const char *fname_bold, int ptsize)
+{
+ close_font();
+
+ // open regular font
+ _font_regular = TTF_OpenFont(fname_regular, ptsize);
+ if (!_font_regular)
+ {
+ printf("TTF_OpenFont: %s\n", TTF_GetError());
+ throw std::exception();
+ }
+
+ // open bold font
+ _font_bold = TTF_OpenFont(fname_bold, ptsize);
+ if (!_font_bold)
+ {
+ printf("TTF_OpenFont: %s\n", TTF_GetError());
+ throw std::exception();
+ }
+
+ // update metrics for regular font
+ int advance;
+ if (TTF_GlyphMetrics(_font_regular, 'M', NULL, NULL, NULL, NULL, &advance) == -1)
+ {
+ printf("TTF_GlyphMetrics: %s\n", TTF_GetError());
+ }
+ _cell_width = advance;
+ _cell_height = TTF_FontHeight(_font_regular);
+
+ // read metrics for bold font
+ if (TTF_GlyphMetrics(_font_bold, 'M', NULL, NULL, NULL, NULL, &advance) == -1)
+ {
+ printf("TTF_GlyphMetrics: %s\n", TTF_GetError());
+ }
+ if (advance > _cell_width)
+ {
+ _cell_width = advance;
+ }
+ int height = TTF_FontHeight(_font_bold);
+ if (height > _cell_height)
+ {
+ _cell_height = height;
+ }
+}
+
+
+void GlyphRenderer::close_font()
+{
+ if (_font_regular)
+ {
+ TTF_CloseFont(_font_regular);
+ _font_regular = NULL;
+ }
+ if (_font_bold)
+ {
+ TTF_CloseFont(_font_bold);
+ _font_bold = NULL;
+ }
+}
+
+
+SDL_Surface *GlyphRenderer::render_glyph(Uint16 ch)
+{
+ TTF_Font *font = _font_regular;
+ SDL_Color color={0xff,0xff,0xff}, bgcolor={0,100,100};
+ if (ch != 'W')
+ {
+ bgcolor.g = 0;
+ bgcolor.b = 0;
+ }
+
+ // create surface for whole cell and fill it with bg color
+ SDL_Surface *cell_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ _cell_width, _cell_height, 32, 0, 0, 0, 0);
+ SDL_Rect dst_rect;
+ dst_rect.x = 0;
+ dst_rect.y = 0;
+ dst_rect.w = _cell_width;
+ dst_rect.h = _cell_height;
+ Uint32 bgcolor_mapped = SDL_MapRGB(cell_surface->format, bgcolor.r, bgcolor.g, bgcolor.b);
+ SDL_FillRect(cell_surface, &dst_rect, bgcolor_mapped);
+
+ // render glyph, blit it onto cell surface
+ SDL_Surface *glyph_surface = TTF_RenderGlyph_Shaded(font, ch, color, bgcolor);
+ int minx, maxy;
+ TTF_GlyphMetrics(font, ch, &minx, NULL, NULL, &maxy, NULL);
+ dst_rect.x = minx;
+ dst_rect.y = TTF_FontAscent(font) - maxy;
+ SDL_BlitSurface(glyph_surface, NULL, cell_surface, &dst_rect);
+ SDL_FreeSurface(glyph_surface);
+
+ return cell_surface;
+}
+
+
+TerminalScreen::~TerminalScreen()
+{
+ if (_cells)
+ {
+ delete[] _cells;
+ }
+}
+
+
+void TerminalScreen::select_font(const char *fname_regular, const char *fname_bold, int ptsize)
+{
+ _render.open_font(fname_regular, fname_bold, ptsize);
+ _reset_cells();
+}
+
+void TerminalScreen::resize(int pxwidth, int pxheight)
+{
+ _screen_surface = SDL_SetVideoMode(pxwidth, pxheight, 8, SDL_SWSURFACE|SDL_ANYFORMAT|SDL_RESIZABLE);
+
+ if (_screen_surface == NULL)
+ {
+ fprintf(stderr, "Unable to set video: %s\n", SDL_GetError());
+ throw std::exception();
+ }
+
+ SDL_WM_SetCaption("terminal", NULL);
+
+ _pixel_width = pxwidth;
+ _pixel_height = pxheight;
+
+ _reset_cells();
+}
+
+
+void TerminalScreen::erase()
+{
+ TerminalCell * cell = _cells;
+ for (int i = 0; i < _width * _height; i++)
+ {
+ cell->ch = ' ';
+ cell->attr = 0;
+ cell++;
+ }
+}
+
+
+void TerminalScreen::putch(int x, int y, Uint16 ch, Uint16 attr)
+{
+ TerminalCell &cell = _cells[y * _width + x];
+ cell.ch = ch;
+ cell.attr = attr;
+}
+
+
+void TerminalScreen::commit()
+{
+ TerminalCell * cell = _cells;
+ SDL_Surface *glyph_surface;
+ SDL_Rect dst_rect;
+ for (int y = 0; y < _height; y++)
+ {
+ for (int x = 0; x < _width; x++)
+ {
+ dst_rect.x = x * _cell_width;
+ dst_rect.y = y * _cell_height;
+ glyph_surface = _render.render_glyph(cell->ch);
+ SDL_BlitSurface(glyph_surface, NULL, _screen_surface, &dst_rect);
+ SDL_FreeSurface(glyph_surface);
+ cell++;
+ }
+ }
+
+ SDL_UpdateRect(_screen_surface, 0, 0, 0, 0);
+}
+
+
+void TerminalScreen::_reset_cells()
+{
+ if (_cells)
+ {
+ delete[] _cells;
+ _cells = NULL;
+ }
+
+ _cell_width = _render.get_cell_width();
+ _cell_height = _render.get_cell_height();
+ _width = _pixel_width / _cell_width;
+ _height = _pixel_height / _cell_height;
+
+ int num_cells = _width * _height;
+ _cells = new TerminalCell[num_cells];
+}
+
+
+Terminal::Terminal()
+ : _screen()
+{
+ if (SDL_Init(SDL_INIT_VIDEO) == -1)
+ {
+ fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
+ throw std::exception();
+ }
+}
+
+
+Terminal::~Terminal()
+{
+ SDL_Quit();
+}
+
+
+void Terminal::get_next_event(Event &event)
+{
+ SDL_Event sdl_event;
+
+ while (SDL_WaitEvent(&sdl_event))
+ {
+ switch (sdl_event.type)
+ {
+ case SDL_QUIT:
+ event.type = EventType::quit;
+ return;
+
+ case SDL_KEYDOWN:
+ //switch(event.key.keysym.sym)
+ event.type = EventType::keypress;
+ return;
+
+ default:
+ break; // continue loop
+ }
+ }
+}