diff -r 729fcdfe6b57 -r fccca2a60492 sdlterm/src/sdlterm.cc --- a/sdlterm/src/sdlterm.cc Tue Jan 08 23:59:55 2013 +0100 +++ b/sdlterm/src/sdlterm.cc Wed Jan 09 22:32:15 2013 +0100 @@ -115,12 +115,18 @@ } -SDL_Surface *GlyphRenderer::render_cell(Uint32 ch, Uint32 attr) +SDL_Surface *GlyphRenderer::render_cell(Uint32 ch, Uint32 attr, bool blink_state) { SDL_Surface *cell_surface; TTF_Font *font; SDL_Color fgcolor, bgcolor; + // blink affects cache lookup, must be processed first + if ((attr & Style::BLINK) && !blink_state) + { + ch = ' '; + } + // try cache Uint64 id = (Uint64)ch | (Uint64)attr << 32; cell_surface = _cache.lookup_glyph(id); @@ -132,9 +138,8 @@ // load attributes _colormap.index_to_rgb((attr & 0x000000FF), fgcolor); _colormap.index_to_rgb((attr & 0x0000FF00) >> 8, bgcolor); - int style = (attr & 0xFF000000) >> 24; - font = (style & Style::BOLD) ? _font_bold : _font_regular; - if (style & Style::STANDOUT) + font = (attr & Style::BOLD) ? _font_bold : _font_regular; + if (attr & Style::STANDOUT) { std::swap(fgcolor, bgcolor); } @@ -154,7 +159,7 @@ if (ch) { // when glyph is not provided by BOLD font but is provided by REGULAR font, use that (better than nothing) - if ((style & Style::BOLD) && !TTF_GlyphIsProvided(font, ch) && TTF_GlyphIsProvided(_font_regular, ch)) + if ((attr & Style::BOLD) && !TTF_GlyphIsProvided(font, ch) && TTF_GlyphIsProvided(_font_regular, ch)) { // use bold style of regular font instead of bold font TTF_SetFontStyle(_font_regular, TTF_STYLE_BOLD); @@ -166,7 +171,7 @@ // normal case _render_glyph(cell_surface, font, ch, fgcolor, bgcolor); } - if (style & Style::UNDERLINE) + if (attr & Style::UNDERLINE) { // draw underline SDL_LockSurface(cell_surface); @@ -244,7 +249,7 @@ void TerminalScreen::toggle_cursor(int x, int y) { TerminalCell &cell = _cells_front[y * _width + x]; - cell.attr ^= (Style::STANDOUT << 24); + cell.attr ^= Style::STANDOUT; } @@ -262,7 +267,7 @@ { dst_rect.x = x * _cell_width; dst_rect.y = y * _cell_height; - cell_surface = _render.render_cell(front_iter->ch, front_iter->attr); + cell_surface = _render.render_cell(front_iter->ch, front_iter->attr, _blink_state); SDL_BlitSurface(cell_surface, NULL, _screen_surface, &dst_rect); *back_iter = *front_iter; } @@ -301,6 +306,33 @@ } +void TerminalScreen::_draw_blink() +{ + // Use back buffer which contains commited changes. + // This is called from timer while application may draw into front_buffer. + auto back_iter = _cells_back.begin(); + SDL_Surface *cell_surface; + SDL_Rect dst_rect; + for (int y = 0; y < _height; y++) + { + for (int x = 0; x < _width; x++) + { + // draw only blinking characters + if (back_iter->attr & Style::BLINK) + { + dst_rect.x = x * _cell_width; + dst_rect.y = y * _cell_height; + cell_surface = _render.render_cell(back_iter->ch, back_iter->attr, _blink_state); + SDL_BlitSurface(cell_surface, NULL, _screen_surface, &dst_rect); + } + back_iter++; + } + } + + SDL_UpdateRect(_screen_surface, 0, 0, 0, 0); +} + + Terminal::Terminal() : _screen(), _attr(7), _cursor_x(0), _cursor_y(0), _cursor_visible(false), _mousemove_last_x(-1), _mousemove_last_y(-1) @@ -312,6 +344,7 @@ SDL_EnableUNICODE(1); SDL_EnableKeyRepeat(250, SDL_DEFAULT_REPEAT_INTERVAL); SDL_WM_SetCaption("terminal", NULL); + SDL_AddTimer(500, _blink_toggle_callback, NULL); } @@ -362,6 +395,13 @@ } switch (sdl_event.type) { + case SDL_USEREVENT: + // toggle blink + if (sdl_event.user.code == 2) + { + _screen.toggle_blink(); + } + break; // continue loop case SDL_QUIT: event.type = Event::QUIT; return true; @@ -482,3 +522,13 @@ return 0; } + +Uint32 Terminal::_blink_toggle_callback(Uint32 interval, void *param) +{ + SDL_Event event; + event.type = SDL_USEREVENT; + event.user.code = 2; + SDL_PushEvent(&event); + return interval; +} +