Console.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdh.h"
  13. #include <Engine/Base/Console.h>
  14. #include <Engine/Base/Console_Internal.h>
  15. #include <Engine/Base/Timer.h>
  16. #include <Engine/Base/ErrorReporting.h>
  17. #include <Engine/Base/CTString.h>
  18. #include <Engine/Base/FileName.h>
  19. #include <Engine/Base/Memory.h>
  20. #include <Engine/Math/Functions.h>
  21. extern CConsole *_pConsole = NULL;
  22. extern INDEX con_iLastLines;
  23. extern BOOL con_bCapture = FALSE;
  24. extern CTString con_strCapture = "";
  25. // Constructor.
  26. CConsole::CConsole(void)
  27. {
  28. con_strBuffer = NULL;
  29. con_strLineBuffer = NULL;
  30. con_atmLines = NULL;
  31. con_fLog = NULL;
  32. }
  33. // Destructor.
  34. CConsole::~CConsole(void)
  35. {
  36. if (this==NULL) {
  37. return;
  38. }
  39. if (con_fLog!=NULL) {
  40. fclose(con_fLog);
  41. con_fLog = NULL;
  42. }
  43. if (con_strBuffer!=NULL) {
  44. FreeMemory(con_strBuffer);
  45. }
  46. if (con_strLineBuffer!=NULL) {
  47. FreeMemory(con_strLineBuffer);
  48. }
  49. if (con_atmLines!=NULL) {
  50. FreeMemory(con_atmLines);
  51. }
  52. }
  53. // Initialize the console.
  54. void CConsole::Initialize(const CTFileName &fnmLog, INDEX ctCharsPerLine, INDEX ctLines)
  55. {
  56. con_csConsole.cs_iIndex = -1;
  57. // synchronize access to console
  58. CTSingleLock slConsole(&con_csConsole, TRUE);
  59. // allocate the buffer
  60. con_ctCharsPerLine = ctCharsPerLine;
  61. con_ctLines = ctLines;
  62. con_ctLinesPrinted = 0;
  63. // note: we add +1 for '\n' perline and +1 '\0' at the end of buffer
  64. con_strBuffer = (char *)AllocMemory((ctCharsPerLine+1)*ctLines+1);
  65. con_strLineBuffer = (char *)AllocMemory(ctCharsPerLine+2); // includes '\n' and '\0'
  66. con_atmLines = (TIME*)AllocMemory((ctLines+1)*sizeof(TIME));
  67. // make it empty
  68. for(INDEX iLine=0; iLine<ctLines; iLine++) {
  69. ClearLine(iLine);
  70. }
  71. // add string terminator at the end
  72. con_strBuffer[(ctCharsPerLine+1)*ctLines] = 0;
  73. // start printing in last line
  74. con_strLastLine = con_strBuffer+(ctCharsPerLine+1)*(ctLines-1);
  75. con_strCurrent = con_strLastLine;
  76. // open console file
  77. con_fLog = fopen(fnmLog, "wt");
  78. if (con_fLog==NULL) {
  79. FatalError("%s", strerror(errno));
  80. }
  81. // print one dummy line on start
  82. CPrintF("\n");
  83. }
  84. // Get current console buffer.
  85. const char *CConsole::GetBuffer(void)
  86. {
  87. if (this==NULL) {
  88. return "";
  89. }
  90. return con_strBuffer+(con_ctLines-con_ctLinesPrinted)*(con_ctCharsPerLine+1);
  91. }
  92. INDEX CConsole::GetBufferSize(void)
  93. {
  94. if (this==NULL) {
  95. return 1;
  96. }
  97. return (con_ctCharsPerLine+1)*con_ctLines+1;
  98. }
  99. // Discard timing info for last lines
  100. void CConsole::DiscardLastLineTimes(void)
  101. {
  102. if (this==NULL) {
  103. return;
  104. }
  105. for(INDEX i=0; i<con_ctLines; i++) {
  106. con_atmLines[i] = -10000.0f;
  107. }
  108. }
  109. // Get number of lines newer than given time
  110. INDEX CConsole::NumberOfLinesAfter(TIME tmLast)
  111. {
  112. if (this==NULL) {
  113. return 0;
  114. }
  115. // clamp console variable
  116. con_iLastLines = Clamp( con_iLastLines, 0L, (INDEX)CONSOLE_MAXLASTLINES);
  117. // find number of last console lines to be displayed on screen
  118. for(INDEX i=0; i<con_iLastLines; i++) {
  119. if (con_atmLines[con_ctLines-1-i]<tmLast) {
  120. return i;
  121. }
  122. }
  123. return con_iLastLines;
  124. }
  125. // Get one of last lines
  126. CTString CConsole::GetLastLine(INDEX iLine)
  127. {
  128. if (this==NULL) {
  129. return "";
  130. }
  131. if (iLine>=con_ctLinesPrinted) {
  132. return "";
  133. }
  134. ASSERT(iLine>=0 && iLine<con_ctLines);
  135. // get line number from the start of buffer
  136. iLine = con_ctLines-1-iLine;
  137. // copy line
  138. memcpy(con_strLineBuffer, con_strBuffer+iLine*(con_ctCharsPerLine+1), con_ctCharsPerLine);
  139. // put terminator at the end
  140. con_strLineBuffer[con_ctCharsPerLine] = 0;
  141. // return it
  142. return con_strLineBuffer;
  143. }
  144. // clear one given line in buffer
  145. void CConsole::ClearLine(INDEX iLine)
  146. {
  147. if (this==NULL) {
  148. return;
  149. }
  150. // line must be valid
  151. ASSERT(iLine>=0 && iLine<con_ctLines);
  152. // get start of line
  153. char *pchLine = con_strBuffer+iLine*(con_ctCharsPerLine+1);
  154. // fill it with spaces
  155. memset(pchLine, ' ', con_ctCharsPerLine);
  156. // add return at the end of line
  157. pchLine[con_ctCharsPerLine] = '\n';
  158. con_atmLines[iLine] = _pTimer!=NULL?_pTimer->GetRealTimeTick():0.0f;
  159. }
  160. // scroll buffer up, discarding lines at the start
  161. void CConsole::ScrollBufferUp(INDEX ctLines)
  162. {
  163. if (this==NULL) {
  164. return;
  165. }
  166. ASSERT(ctLines>0 && ctLines<con_ctLines);
  167. // move buffer up
  168. memmove(
  169. con_strBuffer,
  170. con_strBuffer+ctLines*(con_ctCharsPerLine+1),
  171. (con_ctLines-ctLines)*(con_ctCharsPerLine+1));
  172. // move buffer up
  173. memmove(
  174. con_atmLines,
  175. con_atmLines+ctLines,
  176. (con_ctLines-ctLines)*sizeof(TIME));
  177. con_ctLinesPrinted = ClampUp(con_ctLinesPrinted+1L, con_ctLines);
  178. // clear lines at the end
  179. for(INDEX iLine=con_ctLines-ctLines; iLine<con_ctLines; iLine++) {
  180. ClearLine(iLine);
  181. }
  182. }
  183. // Add a line of text to console
  184. void CConsole::PutString(const char *strString)
  185. {
  186. if (this==NULL) {
  187. return;
  188. }
  189. // synchronize access to console
  190. CTSingleLock slConsole(&con_csConsole, TRUE);
  191. // if in debug version, report it to output window
  192. _RPT1(_CRT_WARN, "%s", strString);
  193. // first append that string to the console output file
  194. if (con_fLog!=NULL) {
  195. fprintf(con_fLog, "%s", strString);
  196. fflush(con_fLog);
  197. }
  198. // if needed, append to capture string
  199. if (con_bCapture) {
  200. con_strCapture+=strString;
  201. }
  202. // if dedicated server
  203. extern BOOL _bDedicatedServer;
  204. if (_bDedicatedServer) {
  205. // print to output
  206. printf("%s", strString);
  207. }
  208. // start at the beginning of the string
  209. const char *pch=strString;
  210. // while not end of string
  211. while(*pch!=0) {
  212. // if line buffer full
  213. if (con_strCurrent==con_strLastLine+con_ctCharsPerLine) {
  214. // move buffer up
  215. ScrollBufferUp(1);
  216. // restart new line
  217. con_strCurrent=con_strLastLine;
  218. }
  219. // get char
  220. char c = *pch++;
  221. // skip cr
  222. if (c=='\r') {
  223. continue;
  224. }
  225. // if it is end of line
  226. if (c=='\n') {
  227. // move buffer up
  228. ScrollBufferUp(1);
  229. // restart new line
  230. con_strCurrent=con_strLastLine;
  231. continue;
  232. }
  233. // otherwise, add the char to buffer
  234. *con_strCurrent++ = c;
  235. }
  236. }
  237. // Close console log file buffers (call only when force-exiting!)
  238. void CConsole::CloseLog(void)
  239. {
  240. if (this==NULL) {
  241. return;
  242. }
  243. if (con_fLog!=NULL) {
  244. fclose(con_fLog);
  245. }
  246. con_fLog = NULL;
  247. }
  248. // Print formated text to the main console.
  249. extern void CPrintF(const char *strFormat, ...)
  250. {
  251. if (_pConsole==NULL) {
  252. return;
  253. }
  254. // format the message in buffer
  255. va_list arg;
  256. va_start(arg, strFormat);
  257. CTString strBuffer;
  258. strBuffer.VPrintF(strFormat, arg);
  259. // print it to the main console
  260. _pConsole->PutString(strBuffer);
  261. }
  262. // Add a string of text to console
  263. void CPutString(const char *strString)
  264. {
  265. if (_pConsole==NULL) {
  266. return;
  267. }
  268. _pConsole->PutString(strString);
  269. }
  270. // Get number of lines newer than given time
  271. INDEX CON_NumberOfLinesAfter(TIME tmLast)
  272. {
  273. if (_pConsole==NULL) {
  274. return 0;
  275. }
  276. return _pConsole->NumberOfLinesAfter(tmLast);
  277. }
  278. // Get one of last lines
  279. CTString CON_GetLastLine(INDEX iLine)
  280. {
  281. if (_pConsole==NULL) {
  282. return "";
  283. }
  284. return _pConsole->GetLastLine(iLine);
  285. }
  286. // Discard timing info for last lines
  287. void CON_DiscardLastLineTimes(void)
  288. {
  289. if (_pConsole==NULL) {
  290. return;
  291. }
  292. _pConsole->DiscardLastLineTimes();
  293. }
  294. // Get current console buffer.
  295. const char *CON_GetBuffer(void)
  296. {
  297. if (_pConsole==NULL) {
  298. return "";
  299. }
  300. return _pConsole->GetBuffer();
  301. }
  302. INDEX CON_GetBufferSize(void)
  303. {
  304. if (_pConsole==NULL) {
  305. return 1;
  306. }
  307. return _pConsole->GetBufferSize();
  308. }