123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- /* Copyright (c) 2002-2012 Croteam Ltd.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as published by
- the Free Software Foundation
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
- #include "stdh.h"
- #include <Engine/Base/Console.h>
- #include <Engine/Base/Console_Internal.h>
- #include <Engine/Base/Timer.h>
- #include <Engine/Base/ErrorReporting.h>
- #include <Engine/Base/CTString.h>
- #include <Engine/Base/FileName.h>
- #include <Engine/Base/Memory.h>
- #include <Engine/Math/Functions.h>
- extern CConsole *_pConsole = NULL;
- extern INDEX con_iLastLines;
- extern BOOL con_bCapture = FALSE;
- extern CTString con_strCapture = "";
- // Constructor.
- CConsole::CConsole(void)
- {
- con_strBuffer = NULL;
- con_strLineBuffer = NULL;
- con_atmLines = NULL;
- con_fLog = NULL;
- }
- // Destructor.
- CConsole::~CConsole(void)
- {
- if (this==NULL) {
- return;
- }
- if (con_fLog!=NULL) {
- fclose(con_fLog);
- con_fLog = NULL;
- }
- if (con_strBuffer!=NULL) {
- FreeMemory(con_strBuffer);
- }
- if (con_strLineBuffer!=NULL) {
- FreeMemory(con_strLineBuffer);
- }
- if (con_atmLines!=NULL) {
- FreeMemory(con_atmLines);
- }
- }
- // Initialize the console.
- void CConsole::Initialize(const CTFileName &fnmLog, INDEX ctCharsPerLine, INDEX ctLines)
- {
- con_csConsole.cs_iIndex = -1;
- // synchronize access to console
- CTSingleLock slConsole(&con_csConsole, TRUE);
- // allocate the buffer
- con_ctCharsPerLine = ctCharsPerLine;
- con_ctLines = ctLines;
- con_ctLinesPrinted = 0;
- // note: we add +1 for '\n' perline and +1 '\0' at the end of buffer
- con_strBuffer = (char *)AllocMemory((ctCharsPerLine+1)*ctLines+1);
- con_strLineBuffer = (char *)AllocMemory(ctCharsPerLine+2); // includes '\n' and '\0'
- con_atmLines = (TIME*)AllocMemory((ctLines+1)*sizeof(TIME));
- // make it empty
- for(INDEX iLine=0; iLine<ctLines; iLine++) {
- ClearLine(iLine);
- }
- // add string terminator at the end
- con_strBuffer[(ctCharsPerLine+1)*ctLines] = 0;
- // start printing in last line
- con_strLastLine = con_strBuffer+(ctCharsPerLine+1)*(ctLines-1);
- con_strCurrent = con_strLastLine;
- // open console file
- con_fLog = fopen(fnmLog, "wt");
- if (con_fLog==NULL) {
- FatalError("%s", strerror(errno));
- }
- // print one dummy line on start
- CPrintF("\n");
- }
- // Get current console buffer.
- const char *CConsole::GetBuffer(void)
- {
- if (this==NULL) {
- return "";
- }
- return con_strBuffer+(con_ctLines-con_ctLinesPrinted)*(con_ctCharsPerLine+1);
- }
- INDEX CConsole::GetBufferSize(void)
- {
- if (this==NULL) {
- return 1;
- }
- return (con_ctCharsPerLine+1)*con_ctLines+1;
- }
- // Discard timing info for last lines
- void CConsole::DiscardLastLineTimes(void)
- {
- if (this==NULL) {
- return;
- }
- for(INDEX i=0; i<con_ctLines; i++) {
- con_atmLines[i] = -10000.0f;
- }
- }
- // Get number of lines newer than given time
- INDEX CConsole::NumberOfLinesAfter(TIME tmLast)
- {
- if (this==NULL) {
- return 0;
- }
- // clamp console variable
- con_iLastLines = Clamp( con_iLastLines, 0L, (INDEX)CONSOLE_MAXLASTLINES);
- // find number of last console lines to be displayed on screen
- for(INDEX i=0; i<con_iLastLines; i++) {
- if (con_atmLines[con_ctLines-1-i]<tmLast) {
- return i;
- }
- }
- return con_iLastLines;
- }
- // Get one of last lines
- CTString CConsole::GetLastLine(INDEX iLine)
- {
- if (this==NULL) {
- return "";
- }
- if (iLine>=con_ctLinesPrinted) {
- return "";
- }
- ASSERT(iLine>=0 && iLine<con_ctLines);
- // get line number from the start of buffer
- iLine = con_ctLines-1-iLine;
- // copy line
- memcpy(con_strLineBuffer, con_strBuffer+iLine*(con_ctCharsPerLine+1), con_ctCharsPerLine);
- // put terminator at the end
- con_strLineBuffer[con_ctCharsPerLine] = 0;
- // return it
- return con_strLineBuffer;
- }
- // clear one given line in buffer
- void CConsole::ClearLine(INDEX iLine)
- {
- if (this==NULL) {
- return;
- }
- // line must be valid
- ASSERT(iLine>=0 && iLine<con_ctLines);
- // get start of line
- char *pchLine = con_strBuffer+iLine*(con_ctCharsPerLine+1);
- // fill it with spaces
- memset(pchLine, ' ', con_ctCharsPerLine);
- // add return at the end of line
- pchLine[con_ctCharsPerLine] = '\n';
- con_atmLines[iLine] = _pTimer!=NULL?_pTimer->GetRealTimeTick():0.0f;
- }
- // scroll buffer up, discarding lines at the start
- void CConsole::ScrollBufferUp(INDEX ctLines)
- {
- if (this==NULL) {
- return;
- }
- ASSERT(ctLines>0 && ctLines<con_ctLines);
- // move buffer up
- memmove(
- con_strBuffer,
- con_strBuffer+ctLines*(con_ctCharsPerLine+1),
- (con_ctLines-ctLines)*(con_ctCharsPerLine+1));
- // move buffer up
- memmove(
- con_atmLines,
- con_atmLines+ctLines,
- (con_ctLines-ctLines)*sizeof(TIME));
- con_ctLinesPrinted = ClampUp(con_ctLinesPrinted+1L, con_ctLines);
- // clear lines at the end
- for(INDEX iLine=con_ctLines-ctLines; iLine<con_ctLines; iLine++) {
- ClearLine(iLine);
- }
- }
- // Add a line of text to console
- void CConsole::PutString(const char *strString)
- {
- if (this==NULL) {
- return;
- }
- // synchronize access to console
- CTSingleLock slConsole(&con_csConsole, TRUE);
- // if in debug version, report it to output window
- _RPT1(_CRT_WARN, "%s", strString);
- // first append that string to the console output file
- if (con_fLog!=NULL) {
- fprintf(con_fLog, "%s", strString);
- fflush(con_fLog);
- }
- // if needed, append to capture string
- if (con_bCapture) {
- con_strCapture+=strString;
- }
- // if dedicated server
- extern BOOL _bDedicatedServer;
- if (_bDedicatedServer) {
- // print to output
- printf("%s", strString);
- }
- // start at the beginning of the string
- const char *pch=strString;
- // while not end of string
- while(*pch!=0) {
- // if line buffer full
- if (con_strCurrent==con_strLastLine+con_ctCharsPerLine) {
- // move buffer up
- ScrollBufferUp(1);
- // restart new line
- con_strCurrent=con_strLastLine;
- }
- // get char
- char c = *pch++;
- // skip cr
- if (c=='\r') {
- continue;
- }
- // if it is end of line
- if (c=='\n') {
- // move buffer up
- ScrollBufferUp(1);
- // restart new line
- con_strCurrent=con_strLastLine;
- continue;
- }
- // otherwise, add the char to buffer
- *con_strCurrent++ = c;
- }
- }
- // Close console log file buffers (call only when force-exiting!)
- void CConsole::CloseLog(void)
- {
- if (this==NULL) {
- return;
- }
- if (con_fLog!=NULL) {
- fclose(con_fLog);
- }
- con_fLog = NULL;
- }
- // Print formated text to the main console.
- extern void CPrintF(const char *strFormat, ...)
- {
- if (_pConsole==NULL) {
- return;
- }
- // format the message in buffer
- va_list arg;
- va_start(arg, strFormat);
- CTString strBuffer;
- strBuffer.VPrintF(strFormat, arg);
- // print it to the main console
- _pConsole->PutString(strBuffer);
- }
- // Add a string of text to console
- void CPutString(const char *strString)
- {
- if (_pConsole==NULL) {
- return;
- }
- _pConsole->PutString(strString);
- }
- // Get number of lines newer than given time
- INDEX CON_NumberOfLinesAfter(TIME tmLast)
- {
- if (_pConsole==NULL) {
- return 0;
- }
- return _pConsole->NumberOfLinesAfter(tmLast);
- }
- // Get one of last lines
- CTString CON_GetLastLine(INDEX iLine)
- {
- if (_pConsole==NULL) {
- return "";
- }
- return _pConsole->GetLastLine(iLine);
- }
- // Discard timing info for last lines
- void CON_DiscardLastLineTimes(void)
- {
- if (_pConsole==NULL) {
- return;
- }
- _pConsole->DiscardLastLineTimes();
- }
- // Get current console buffer.
- const char *CON_GetBuffer(void)
- {
- if (_pConsole==NULL) {
- return "";
- }
- return _pConsole->GetBuffer();
- }
- INDEX CON_GetBufferSize(void)
- {
- if (_pConsole==NULL) {
- return 1;
- }
- return _pConsole->GetBufferSize();
- }
|