dxx-rebirth/similar/main/console.cpp

327 lines
7.6 KiB
C++
Raw Normal View History

2014-06-01 17:55:23 +00:00
/*
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
* It is copyright by its individual contributors, as recorded in the
* project's Git history. See COPYING.txt at the top level for license
* terms and a link to the Git history.
*/
2006-03-20 17:12:09 +00:00
/*
*
* Game console
2006-03-20 17:12:09 +00:00
*
*/
#include <algorithm>
2006-03-20 17:12:09 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
2013-06-30 02:22:56 +00:00
#include <SDL.h>
#include "window.h"
#include "event.h"
2006-03-20 17:12:09 +00:00
#include "console.h"
#include "args.h"
2006-03-20 17:12:09 +00:00
#include "gr.h"
#include "physfsx.h"
2006-03-20 17:12:09 +00:00
#include "gamefont.h"
2012-11-11 00:14:30 +00:00
#include "game.h"
#include "key.h"
#include "vers_id.h"
#include "timer.h"
#include "cli.h"
2015-06-07 16:20:46 +00:00
#include "cvar.h"
2006-03-20 17:12:09 +00:00
2014-07-05 03:32:07 +00:00
#include "dxxsconf.h"
#include "compiler-array.h"
static RAIIPHYSFS_File gamelog_fp;
2014-07-05 03:32:07 +00:00
static array<console_buffer, CON_LINES_MAX> con_buffer;
static int con_state = CON_STATE_CLOSED, con_scroll_offset = 0, con_size = 0;
2006-03-20 17:12:09 +00:00
static void con_add_buffer_line(int priority, const char *buffer, size_t len)
2006-03-20 17:12:09 +00:00
{
/* shift con_buffer for one line */
2014-07-05 03:32:07 +00:00
std::move(std::next(con_buffer.begin()), con_buffer.end(), con_buffer.begin());
console_buffer &c = con_buffer.back();
c.priority=priority;
2006-03-20 17:12:09 +00:00
size_t copy = std::min(len, CON_LINE_LENGTH - 1);
2014-07-05 03:32:07 +00:00
c.line[copy] = 0;
memcpy(&c.line,buffer, copy);
2006-03-20 17:12:09 +00:00
}
void (con_printf)(int priority, const char *fmt, ...)
2006-03-20 17:12:09 +00:00
{
va_list arglist;
char buffer[CON_LINE_LENGTH];
2015-10-18 21:01:21 +00:00
if (priority <= CGameArg.DbgVerbose)
2006-03-20 17:12:09 +00:00
{
va_start (arglist, fmt);
size_t len = vsnprintf (buffer, sizeof(buffer), fmt, arglist);
2006-03-20 17:12:09 +00:00
va_end (arglist);
con_puts(priority, buffer, len);
}
}
2006-03-20 17:12:09 +00:00
static void con_scrub_markup(char *buffer)
{
char *p1 = buffer, *p2 = p1;
do
switch (*p1)
{
case CC_COLOR:
case CC_LSPACING:
if (!*++p1)
break;
case CC_UNDERLINE:
p1++;
break;
default:
*p2++ = *p1++;
}
while (*p1);
*p2 = 0;
}
2006-03-20 17:12:09 +00:00
static void con_print_file(const char *buffer)
{
/* Print output to stdout */
puts(buffer);
2006-03-20 17:12:09 +00:00
/* Print output to gamelog.txt */
if (gamelog_fp)
{
struct tm *lt;
time_t t;
t=time(NULL);
lt=localtime(&t);
PHYSFSX_printf(gamelog_fp,"%02i:%02i:%02i ",lt->tm_hour,lt->tm_min,lt->tm_sec);
#ifdef _WIN32 // stupid hack to force DOS-style newlines
2013-12-07 00:47:27 +00:00
#define DXX_LF "\r\n"
#else
#define DXX_LF "\n"
#endif
PHYSFSX_printf(gamelog_fp,"%s" DXX_LF,buffer);
}
}
void con_puts(int priority, char *buffer, size_t len)
{
2015-10-18 21:01:21 +00:00
if (priority <= CGameArg.DbgVerbose)
{
con_add_buffer_line(priority, buffer, len);
con_scrub_markup(buffer);
/* Produce a sanitised version and send it to the console */
con_print_file(buffer);
}
}
void con_puts(int priority, const char *buffer, size_t len)
{
2015-10-18 21:01:21 +00:00
if (priority <= CGameArg.DbgVerbose)
{
/* add given string to con_buffer */
con_add_buffer_line(priority, buffer, len);
con_print_file(buffer);
}
2006-03-20 17:12:09 +00:00
}
2015-05-14 02:23:13 +00:00
static color_t get_console_color_by_priority(int priority)
{
switch (priority)
{
case CON_CRITICAL:
return BM_XRGB(28,0,0);
case CON_URGENT:
return BM_XRGB(54,54,0);
case CON_DEBUG:
case CON_VERBOSE:
return BM_XRGB(14,14,14);
case CON_HUD:
return BM_XRGB(0,28,0);
default:
return BM_XRGB(255,255,255);
}
}
static void con_draw(void)
2006-03-20 17:12:09 +00:00
{
2015-09-29 02:41:22 +00:00
int i = 0, y = 0;
2006-03-20 17:12:09 +00:00
if (con_size <= 0)
return;
gr_set_current_canvas(NULL);
gr_set_curfont(GAME_FONT);
2016-02-12 04:02:28 +00:00
const uint8_t color = BM_XRGB(0, 0, 0);
gr_settransblend(7, GR_BLEND_NORMAL);
2015-06-13 22:42:20 +00:00
const auto &&fspacy1 = FSPACY(1);
2015-06-13 22:42:22 +00:00
const auto &&line_spacing = LINE_SPACING;
y = fspacy1 + (line_spacing * con_size);
2016-02-12 04:02:28 +00:00
gr_rect(0, 0, SWIDTH, y, color);
gr_settransblend(GR_FADE_OFF, GR_BLEND_NORMAL);
i+=con_scroll_offset;
gr_set_fontcolor(BM_XRGB(255,255,255), -1);
y = cli_draw(y, line_spacing);
2015-06-13 22:42:20 +00:00
const auto &&fspacx = FSPACX();
2015-06-13 22:42:20 +00:00
const auto &&fspacx1 = fspacx(1);
2015-09-29 02:41:22 +00:00
for (;;)
{
2015-12-22 04:18:50 +00:00
auto &b = con_buffer[CON_LINES_MAX - 1 - i];
gr_set_fontcolor(get_console_color_by_priority(b.priority), -1);
2015-09-29 02:41:22 +00:00
int w,h;
2015-12-22 04:18:50 +00:00
gr_get_string_size(b.line, &w, &h, nullptr);
2015-06-13 22:42:20 +00:00
y -= h + fspacy1;
2015-12-22 04:18:50 +00:00
gr_string(fspacx1, y, b.line, w, h);
i++;
2006-03-20 17:12:09 +00:00
if (y<=0 || CON_LINES_MAX-1-i <= 0 || i < 0)
2015-09-29 02:41:22 +00:00
break;
}
2016-02-12 04:02:28 +00:00
gr_rect(0, 0, SWIDTH, line_spacing, color);
gr_set_fontcolor(BM_XRGB(255,255,255),-1);
2015-06-13 22:42:20 +00:00
gr_printf(fspacx1, fspacy1, "%s LOG", DESCENT_VERSION);
gr_string(SWIDTH - fspacx(110), fspacy1, "PAGE-UP/DOWN TO SCROLL");
2006-03-20 17:12:09 +00:00
}
2014-10-16 02:30:29 +00:00
static window_event_result con_handler(window *wind,const d_event &event, const unused_window_userdata_t *)
2006-03-20 17:12:09 +00:00
{
int key;
static fix64 last_scroll_time = 0;
2014-10-04 21:47:13 +00:00
switch (event.type)
2006-03-20 17:12:09 +00:00
{
case EVENT_WINDOW_ACTIVATED:
key_toggle_repeat(1);
break;
case EVENT_WINDOW_DEACTIVATED:
key_toggle_repeat(0);
con_size = 0;
con_state = CON_STATE_CLOSED;
break;
case EVENT_KEY_COMMAND:
key = event_key_get(event);
switch (key)
{
case KEY_SHIFTED + KEY_ESC:
switch (con_state)
{
case CON_STATE_OPEN:
case CON_STATE_OPENING:
con_state = CON_STATE_CLOSING;
break;
case CON_STATE_CLOSED:
case CON_STATE_CLOSING:
con_state = CON_STATE_OPENING;
default:
break;
}
break;
case KEY_PAGEUP:
con_scroll_offset+=CON_SCROLL_OFFSET;
if (con_scroll_offset >= CON_LINES_MAX-1)
con_scroll_offset = CON_LINES_MAX-1;
while (con_buffer[CON_LINES_MAX-1-con_scroll_offset].line[0]=='\0')
con_scroll_offset--;
break;
case KEY_PAGEDOWN:
con_scroll_offset-=CON_SCROLL_OFFSET;
if (con_scroll_offset<0)
con_scroll_offset=0;
break;
case KEY_CTRLED + KEY_A:
case KEY_HOME: cli_cursor_home(); break;
case KEY_END:
case KEY_CTRLED + KEY_E: cli_cursor_end(); break;
case KEY_CTRLED + KEY_C: cli_clear(); break;
case KEY_LEFT: cli_cursor_left(); break;
case KEY_RIGHT: cli_cursor_right(); break;
case KEY_BACKSP: cli_cursor_backspace(); break;
case KEY_CTRLED + KEY_D:
case KEY_DELETE: cli_cursor_del(); break;
case KEY_UP: cli_history_prev(); break;
case KEY_DOWN: cli_history_next(); break;
case KEY_TAB: cli_autocomplete(); break;
case KEY_ENTER: cli_execute(); break;
case KEY_INSERT:
cli_toggle_overwrite_mode();
break;
default:
int character = key_ascii();
if (character == 255)
break;
cli_add_character(character);
break;
}
2014-08-06 02:10:49 +00:00
return window_event_result::handled;
case EVENT_WINDOW_DRAW:
timer_delay2(50);
if (con_state == CON_STATE_OPENING)
{
if (con_size < CON_LINES_ONSCREEN && timer_query() >= last_scroll_time+(F1_0/30))
{
last_scroll_time = timer_query();
2015-05-14 02:23:13 +00:00
if (++ con_size >= CON_LINES_ONSCREEN)
con_state = CON_STATE_OPEN;
}
}
else if (con_state == CON_STATE_CLOSING)
{
if (con_size > 0 && timer_query() >= last_scroll_time+(F1_0/30))
{
last_scroll_time = timer_query();
2015-05-14 02:23:13 +00:00
if (! -- con_size)
con_state = CON_STATE_CLOSED;
}
}
2014-08-06 02:10:49 +00:00
con_draw();
if (con_state == CON_STATE_CLOSED && wind)
2014-08-06 02:10:49 +00:00
{
return window_event_result::close;
}
break;
case EVENT_WINDOW_CLOSE:
break;
default:
break;
2006-03-20 17:12:09 +00:00
}
2014-08-06 02:10:49 +00:00
return window_event_result::ignored;
2006-03-20 17:12:09 +00:00
}
void con_showup(void)
{
window *wind;
game_flush_inputs();
con_state = CON_STATE_OPENING;
2013-12-01 05:21:47 +00:00
wind = window_create(&grd_curscreen->sc_canvas, 0, 0, SWIDTH, SHEIGHT, con_handler, unused_window_userdata);
if (!wind)
{
d_event event = { EVENT_WINDOW_CLOSE };
2014-10-04 21:47:13 +00:00
con_handler(NULL, event, NULL);
return;
}
}
void con_init(void)
2006-03-20 17:12:09 +00:00
{
2014-07-05 03:32:07 +00:00
con_buffer = {};
2015-10-18 21:01:21 +00:00
if (CGameArg.DbgSafelog)
gamelog_fp.reset(PHYSFS_openWrite("gamelog.txt"));
else
gamelog_fp = PHYSFSX_openWriteBuffered("gamelog.txt");
cli_init();
2015-02-11 07:35:44 +00:00
cmd_init();
cvar_init();
}