174 { |
174 { |
175 // draw underline |
175 // draw underline |
176 SDL_LockSurface(cell_surface); |
176 SDL_LockSurface(cell_surface); |
177 int y = 1 + TTF_FontAscent(font); |
177 int y = 1 + TTF_FontAscent(font); |
178 Uint32 fgcolor_mapped = SDL_MapRGB(cell_surface->format, fgcolor.r, fgcolor.g, fgcolor.b); |
178 Uint32 fgcolor_mapped = SDL_MapRGB(cell_surface->format, fgcolor.r, fgcolor.g, fgcolor.b); |
179 Uint32 *p = (Uint32 *)(cell_surface->pixels + y * cell_surface->pitch); |
179 Uint32 *p = (Uint32 *)((Uint8 *)cell_surface->pixels + y * cell_surface->pitch); |
180 for (int x = 0; x < _cell_width; x++) |
180 for (int x = 0; x < _cell_width; x++) |
181 *p++ = fgcolor_mapped; |
181 *p++ = fgcolor_mapped; |
182 SDL_UnlockSurface(cell_surface); |
182 SDL_UnlockSurface(cell_surface); |
183 } |
183 } |
184 } |
184 } |
223 { |
223 { |
224 fprintf(stderr, "Unable to set video: %s\n", SDL_GetError()); |
224 fprintf(stderr, "Unable to set video: %s\n", SDL_GetError()); |
225 throw std::exception(); |
225 throw std::exception(); |
226 } |
226 } |
227 |
227 |
228 SDL_WM_SetCaption("terminal", NULL); |
|
229 |
|
230 _pixel_width = pxwidth; |
228 _pixel_width = pxwidth; |
231 _pixel_height = pxheight; |
229 _pixel_height = pxheight; |
232 |
230 |
233 _reset_cells(); |
231 _reset_cells(); |
234 } |
232 } |
243 void TerminalScreen::putch(int x, int y, Uint32 ch, Uint32 attr) |
241 void TerminalScreen::putch(int x, int y, Uint32 ch, Uint32 attr) |
244 { |
242 { |
245 TerminalCell &cell = _cells_front[y * _width + x]; |
243 TerminalCell &cell = _cells_front[y * _width + x]; |
246 cell.ch = ch; |
244 cell.ch = ch; |
247 cell.attr = attr; |
245 cell.attr = attr; |
|
246 } |
|
247 |
|
248 |
|
249 void TerminalScreen::toggle_cursor(int x, int y) |
|
250 { |
|
251 TerminalCell &cell = _cells_front[y * _width + x]; |
|
252 cell.attr ^= (Style::STANDOUT << 24); |
248 } |
253 } |
249 |
254 |
250 |
255 |
251 void TerminalScreen::commit() |
256 void TerminalScreen::commit() |
252 { |
257 { |
273 |
278 |
274 SDL_UpdateRect(_screen_surface, 0, 0, 0, 0); |
279 SDL_UpdateRect(_screen_surface, 0, 0, 0, 0); |
275 } |
280 } |
276 |
281 |
277 |
282 |
|
283 void TerminalScreen::redraw() |
|
284 { |
|
285 // clear back buffer, current screen is considered blank |
|
286 std::fill(_cells_back.begin(), _cells_back.end(), TerminalCell()); |
|
287 } |
|
288 |
|
289 |
278 void TerminalScreen::_reset_cells() |
290 void TerminalScreen::_reset_cells() |
279 { |
291 { |
280 _cell_width = _render.get_cell_width(); |
292 _cell_width = _render.get_cell_width(); |
281 _cell_height = _render.get_cell_height(); |
293 _cell_height = _render.get_cell_height(); |
282 if (!_cell_width || !_cell_height) |
294 if (!_cell_width || !_cell_height) |
287 if (!_width || !_height) |
299 if (!_width || !_height) |
288 return; |
300 return; |
289 |
301 |
290 int num_cells = _width * _height; |
302 int num_cells = _width * _height; |
291 _cells_front.resize(num_cells, TerminalCell()); |
303 _cells_front.resize(num_cells, TerminalCell()); |
292 _cells_back.resize(num_cells, TerminalCell()); |
304 _cells_back.resize(num_cells); |
|
305 redraw(); |
293 } |
306 } |
294 |
307 |
295 |
308 |
296 Terminal::Terminal() |
309 Terminal::Terminal() |
297 : _screen(), _attr(7), _mousemove_last_x(-1) |
310 : _screen(), _attr(7), _cursor_visible(false), _mousemove_last_x(-1) |
298 { |
311 { |
299 if (SDL_Init(SDL_INIT_VIDEO) == -1) |
312 if (SDL_Init(SDL_INIT_VIDEO) == -1) |
300 { |
313 { |
301 fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); |
314 fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); |
302 throw std::exception(); |
315 throw std::exception(); |
303 } |
316 } |
304 SDL_EnableUNICODE(1); |
317 SDL_EnableUNICODE(1); |
|
318 SDL_WM_SetCaption("terminal", NULL); |
305 } |
319 } |
306 |
320 |
307 |
321 |
308 Terminal::~Terminal() |
322 Terminal::~Terminal() |
309 { |
323 { |
310 SDL_Quit(); |
324 SDL_Quit(); |
311 } |
325 } |
312 |
326 |
|
327 |
|
328 void Terminal::commit() |
|
329 { |
|
330 if (_cursor_visible) |
|
331 { |
|
332 _screen.toggle_cursor(_cursor_x, _cursor_y); |
|
333 _screen.commit(); |
|
334 _screen.toggle_cursor(_cursor_x, _cursor_y); |
|
335 } |
|
336 else |
|
337 { |
|
338 _screen.commit(); |
|
339 } |
|
340 } |
313 |
341 |
314 void Terminal::get_next_event(Event &event) |
342 void Terminal::get_next_event(Event &event) |
315 { |
343 { |
316 static SDL_Event sdl_event; |
344 static SDL_Event sdl_event; |
317 |
345 |
320 switch (sdl_event.type) |
348 switch (sdl_event.type) |
321 { |
349 { |
322 case SDL_QUIT: |
350 case SDL_QUIT: |
323 event.type = Event::QUIT; |
351 event.type = Event::QUIT; |
324 return; |
352 return; |
|
353 |
|
354 case SDL_VIDEORESIZE: |
|
355 event.type = Event::RESIZE; |
|
356 _screen.resize(sdl_event.resize.w, sdl_event.resize.h); |
|
357 return; |
|
358 |
|
359 case SDL_VIDEOEXPOSE: |
|
360 _screen.redraw(); |
|
361 break; |
325 |
362 |
326 case SDL_KEYDOWN: |
363 case SDL_KEYDOWN: |
327 { |
364 { |
328 //switch(event.key.keysym.sym) |
365 //switch(event.key.keysym.sym) |
329 event.type = Event::KEYPRESS; |
366 event.type = Event::KEYPRESS; |
352 event.mouse.button = sdl_event.button.button; |
389 event.mouse.button = sdl_event.button.button; |
353 _mousemove_last_x = -1; |
390 _mousemove_last_x = -1; |
354 return; |
391 return; |
355 |
392 |
356 case SDL_MOUSEMOTION: |
393 case SDL_MOUSEMOTION: |
|
394 if (sdl_event.motion.state == 0) |
|
395 break; // continue loop, do not report move events when no button is pressed |
357 event.type = Event::MOUSEMOVE; |
396 event.type = Event::MOUSEMOVE; |
358 event.mouse.x = sdl_event.motion.x / _screen.get_cell_width(); |
397 event.mouse.x = sdl_event.motion.x / _screen.get_cell_width(); |
359 event.mouse.y = sdl_event.motion.y / _screen.get_cell_height(); |
398 event.mouse.y = sdl_event.motion.y / _screen.get_cell_height(); |
360 if (_mousemove_last_x != event.mouse.x || |
399 if (_mousemove_last_x != event.mouse.x || |
361 _mousemove_last_y != event.mouse.y) |
400 _mousemove_last_y != event.mouse.y) |