Console.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 1997-2001 Id Software, Inc.
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013 See the GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 
00019 */
00020 // console.c
00021 
00022 #include "pent_include.h"
00023 #include "ODataSource.h"
00024 #include "RenderSurface.h"
00025 #include "util.h"
00026 #include "FixedWidthFont.h"
00027 
00028 #include <cstdio>
00029 #include <cstring>
00030 #include <cstdlib>
00031 #include <cstdarg>
00032 
00033 using namespace std;
00034 
00035 #define MAXPRINTMSG     4096
00036 
00037 // The console
00038 Console         con;
00039 
00040 
00041 
00042 // Standard Output Stream Object
00043 #ifndef SAFE_CONSOLE_STREAMS
00044 console_ostream<char>           pout;
00045 console_ostream<char>           *ppout = &pout;
00046 #else
00047 console_ostream<char>           *ppout = 0;
00048 #endif
00049 
00050 // Error Output Stream Object
00051 #ifndef SAFE_CONSOLE_STREAMS
00052 console_err_ostream<char>       perr;
00053 console_err_ostream<char>       *pperr = &perr;
00054 #else
00055 console_err_ostream<char>       *pperr = 0;
00056 #endif
00057 
00058 
00059 /*
00060 ================
00061 Con_Clear_f
00062 ================
00063 */
00064 void Console::Clear ()
00065 {
00066         std::memset (text, ' ', CON_TEXTSIZE);
00067         putchar_count = 0;
00068 }
00069 
00070                                                 
00071 /*
00072 ================
00073 Con_Dump_f
00074 
00075 Save the console contents out to a file
00076 ================
00077 */
00078 void Console::Dump (const char *name)
00079 {
00080         int             l, x;
00081         char    *line;
00082         FILE    *f;
00083         char    buffer[1024];
00084 
00085         // Need to do this first
00086         PrintPutchar();
00087 
00088         Printf ("Dumped console text to %s.\n", name);
00089         f = std::fopen (name, "wa");
00090         if (!f)
00091         {
00092                 Print ("ERROR: couldn't open.\n");
00093                 return;
00094         }
00095 
00096         // skip empty lines
00097         for (l = current - totallines + 1 ; l <= current ; l++)
00098         {
00099                 line = text + (l%totallines)*linewidth;
00100                 for (x=0 ; x<linewidth ; x++)
00101                         if (line[x] != ' ')
00102                                 break;
00103                 if (x != linewidth)
00104                         break;
00105         }
00106 
00107         // write the remaining lines
00108         buffer[linewidth] = 0;
00109         for ( ; l <= current ; l++)
00110         {
00111                 line = text + (l%totallines)*linewidth;
00112                 std::strncpy (buffer, line, linewidth);
00113                 for (x=linewidth-1 ; x>=0 ; x--)
00114                 {
00115                         if (buffer[x] == ' ')
00116                                 buffer[x] = 0;
00117                         else
00118                                 break;
00119                 }
00120                 for (x=0; buffer[x]; x++)
00121                         buffer[x] &= 0x7f;
00122 
00123                 std::fprintf (f, "%s\n", buffer);
00124         }
00125 
00126         std::fclose (f);
00127 }
00128                                                 
00129 
00130 /*
00131 ================
00132 Con_CheckResize
00133 
00134 If the line width has changed, reformat the buffer.
00135 ================
00136 */
00137 void Console::CheckResize (int scrwidth)
00138 {
00139         int             i, j, width, oldwidth, oldtotallines, numlines, numchars;
00140         char    tbuf[CON_TEXTSIZE];
00141 
00142         // Need to do this first
00143         PrintPutchar();
00144 
00145         if (!confont)
00146                 width = (scrwidth >> 3) - 2;
00147         else
00148                 width = (scrwidth / confont->width) - 2;
00149 
00150         if (width == linewidth)
00151                 return;
00152 
00153         if (width < 1)                  // video hasn't been initialized yet
00154         {
00155                 width = 78;
00156                 linewidth = width;
00157                 totallines = CON_TEXTSIZE / linewidth;
00158                 std::memset (text, ' ', CON_TEXTSIZE);
00159         }
00160         else
00161         {
00162                 oldwidth = linewidth;
00163                 linewidth = width;
00164                 oldtotallines = totallines;
00165                 totallines = CON_TEXTSIZE / linewidth;
00166                 numlines = oldtotallines;
00167 
00168                 if (totallines < numlines)
00169                         numlines = totallines;
00170 
00171                 numchars = oldwidth;
00172         
00173                 if (linewidth < numchars)
00174                         numchars = linewidth;
00175 
00176                 std::memcpy (tbuf, text, CON_TEXTSIZE);
00177                 std::memset (text, ' ', CON_TEXTSIZE);
00178 
00179                 for (i=0 ; i<numlines ; i++)
00180                 {
00181                         for (j=0 ; j<numchars ; j++)
00182                         {
00183                                 text[(totallines - 1 - i) * linewidth + j] =
00184                                                 tbuf[((current - i + oldtotallines) %
00185                                                           oldtotallines) * oldwidth + j];
00186                         }
00187                 }
00188         }
00189 
00190         current = totallines - 1;
00191         display = current;
00192 }
00193 
00194 //
00195 // Constructor
00196 //
00197 Console::Console () : current(0), x(0), display(0), linewidth(-1),
00198                                          totallines(0), vislines(0), wordwrap(true), cr(false),
00199                                          putchar_count(0), std_output_enabled(0xFFFFFFFF),
00200                                          stdout_redir(0), stderr_redir(0), confont(0),
00201                                          auto_paint(0), msgMask(MM_ALL), framenum(0),
00202                                          commandCursorPos(0), commandInsert(true), commandHistoryPos(0)
00203 {
00204         linewidth = -1;
00205 
00206         CheckResize (0);
00207 
00208         std::memset (times, 0, sizeof(times));
00209         
00210         // Lets try adding a Console command!
00211         AddConsoleCommand("Console::CmdList", ConCmd_CmdList);
00212         AddConsoleCommand("Console::CmdHistory", ConCmd_CmdHistory);
00213 
00214         PrintInternal ("Console initialized.\n");
00215 }
00216 
00217 //
00218 // Destructor
00219 //
00220 Console::~Console()
00221 {
00222         RemoveConsoleCommand(Console::ConCmd_CmdList);
00223         RemoveConsoleCommand(Console::ConCmd_CmdHistory);
00224 
00225         // Need to do this first
00226         PrintPutchar();
00227 }
00228 
00229 
00230 //
00231 // Internal Methods
00232 //
00233 
00234 // Print a text string to the console
00235 void Console::PrintInternal (const char *txt)
00236 {
00237         int             y;
00238         int             c, l;
00239 
00240         // Need to do this first
00241         PrintPutchar();
00242 
00243         while ( 0 != (c = *txt) )
00244         {
00245                 if (wordwrap) {
00246                         // count word length
00247                         for (l=0 ; l< linewidth ; l++)
00248                                 if ( txt[l] <= ' ')
00249                                         break;
00250 
00251                         // word wrap
00252                         if (l != linewidth && (x + l > linewidth) )
00253                                 x = 0;
00254                 }
00255 
00256                 txt++;
00257 
00258                 if (cr)
00259                 {
00260                         current--;
00261                         cr = false;
00262                 }
00263                 
00264                 if (!x) 
00265                 {
00266                         Linefeed ();
00267                         // mark time for transparent overlay
00268                         if (current >= 0) times[current % CON_NUM_TIMES] = framenum;
00269                 }
00270 
00271                 switch (c)
00272                 {
00273                 case '\n':
00274                         x = 0;
00275                         break;
00276 
00277                 case '\r':
00278                         x = 0;
00279                         cr = true;
00280                         break;
00281 
00282                 default:        // display character and advance
00283                         y = current % totallines;
00284                         text[y*linewidth+x] = static_cast<char>(c);
00285                         x++;
00286                         if (x >= linewidth) x = 0;
00287                         break;
00288                 }
00289                 
00290         }
00291 }
00292 
00293 // Print a text string to the console
00294 void Console::PrintRawInternal (const char *txt, int n)
00295 {
00296         int             y;
00297         int             c, l;
00298 
00299         // Need to do this first
00300         PrintPutchar();
00301 
00302         for ( int i = 0; i < n; i++ )
00303         {
00304                 c = *txt;
00305 
00306                 if (wordwrap) {
00307                         // count word length
00308                         for (l=0 ; l < linewidth && l < n; l++)
00309                                 if ( txt[l] <= ' ') break;
00310 
00311                         // word wrap
00312                         if (l != linewidth && (x + l > linewidth) )
00313                                 x = 0;
00314                 }
00315 
00316                 txt++;
00317 
00318                 if (cr)
00319                 {
00320                         current--;
00321                         cr = false;
00322                 }
00323                 
00324                 if (!x) 
00325                 {
00326                         Linefeed ();
00327                         // mark time for transparent overlay
00328                         if (current >= 0) times[current % CON_NUM_TIMES] = framenum;
00329                 }
00330 
00331                 switch (c)
00332                 {
00333                 case '\n':
00334                         x = 0;
00335                         break;
00336 
00337                 case '\r':
00338                         x = 0;
00339                         cr = true;
00340                         break;
00341 
00342                 default:        // display character and advance
00343                         y = current % totallines;
00344                         text[y*linewidth+x] = static_cast<char>(c);
00345                         x++;
00346                         if (x >= linewidth) x = 0;
00347                         break;
00348                 }
00349                 
00350         }
00351 }
00352 
00353 // Add a linefeed to the buffer
00354 void Console::Linefeed (void)
00355 {
00356         x = 0;
00357         display++;
00358         current++;
00359         std::memset (&text[(current%totallines)*linewidth], ' ', linewidth);
00360 
00361         if (auto_paint) auto_paint();
00362 }
00363 
00364 // Print a text string to the console
00365 void Console::PutcharInternal (int c)
00366 {
00367         // Add the character
00368         putchar_buf[putchar_count] = static_cast<char>(c);
00369 
00370         // Increment the counter
00371         putchar_count++;
00372 
00373         // If it was a space or less, or we've hit the limit we'll add it to the
00374         // actual buffer
00375         if (c <= ' ' || putchar_count == (CON_PUTCHAR_SIZE-1)) PrintPutchar();
00376 }
00377 
00378 // Print the Putchar data, if possible
00379 void Console::PrintPutchar()
00380 {
00381         if (!putchar_count) return;
00382 
00383         // Get the count
00384         //int count = putchar_count; //Darke: UNUSED?
00385         
00386         // Terminate the string
00387         putchar_buf[putchar_count] = 0;
00388 
00389         // Clear the counter
00390         putchar_count = 0;
00391 
00392         // Print it
00393         PrintInternal(putchar_buf);
00394 }
00395 
00396 //
00397 // STDOUT Methods
00398 //
00399 
00400 // Print a text string to the console, and output to stdout
00401 void Console::Print(const char *txt)
00402 {
00403         if (std_output_enabled & CON_STDOUT) fputs(txt, stdout);
00404         if (stdout_redir) stdout_redir->write(txt, std::strlen(txt));
00405         PrintInternal(txt);
00406 }
00407 
00408 // Print a text string to the console, and output to stdout, with message filtering
00409 void Console::Print(const MsgMask mm, const char *txt)
00410 {
00411         if(mm & msgMask) Print(txt);
00412 }
00413 
00414 // printf, and output to stdout
00415 sint32 Console::Printf(const char *fmt, ...)
00416 {
00417         va_list argptr;
00418 
00419         va_start(argptr,fmt);
00420         sint32 count = vPrintf(fmt, argptr);
00421         va_end(argptr);
00422 
00423         return count;
00424 }
00425 
00426 // printf, and output to stdout, with message filtering.
00427 sint32 Console::Printf(const MsgMask mm, const char *fmt, ...)
00428 {
00429         if(!(mm & msgMask)) return 0;
00430 
00431         va_list argptr;
00432         
00433         va_start(argptr,fmt);
00434         sint32 count = vPrintf(fmt, argptr);
00435         va_end(argptr);
00436 
00437         return count;
00438 }
00439 
00440 // printf, and output to stdout (va_list)
00441 sint32 Console::vPrintf (const char *fmt, va_list argptr)
00442 {
00443         char msg[MAXPRINTMSG];
00444 
00445         if (std_output_enabled & CON_STDOUT) {
00446                 va_list argptr2;
00447                 va_copy(argptr2, argptr);
00448                 vfprintf (stdout, fmt, argptr2);
00449                 va_end(argptr2);
00450         }
00451         sint32 count = vsnprintf (msg, MAXPRINTMSG, fmt, argptr);
00452         if (stdout_redir) stdout_redir->write(msg, count);
00453         PrintInternal(msg);
00454 
00455         return count;
00456 }
00457 
00458 // Print a text string to the console, and output to stdout
00459 void Console::PrintRaw (const char *txt, int n)
00460 {
00461         if (std_output_enabled & CON_STDOUT) std::fwrite(txt, n, 1, stdout);
00462         if (stdout_redir) stdout_redir->write(txt, n);
00463         PrintRawInternal (txt, n);
00464 }
00465 
00466 // putchar, and output to stdout
00467 void Console::Putchar (int c)
00468 {
00469         if (std_output_enabled & CON_STDOUT) fputc(c, stdout);
00470         if (stdout_redir) stdout_redir->write1(c);
00471         PutcharInternal(c);
00472 }
00473 
00474 
00475 //
00476 // STDERR Methods
00477 //
00478 
00479 // Print a text string to the console, and output to stderr
00480 void Console::Print_err (const char *txt)
00481 {
00482         if (std_output_enabled & CON_STDERR) fputs(txt, stderr);
00483         if (stderr_redir) stderr_redir->write(txt, std::strlen(txt));
00484         PrintInternal (txt);
00485 }
00486 
00487 // Print a text string to the console, and output to stderr, with message filtering
00488 void Console::Print_err(const MsgMask mm, const char *txt)
00489 {
00490         if(mm & msgMask) Print_err(txt);
00491 }
00492 
00493 // printf, and output to stderr
00494 sint32 Console::Printf_err (const char *fmt, ...)
00495 {
00496         va_list argptr;
00497 
00498         va_start (argptr, fmt);
00499         sint32 count = vPrintf_err(fmt, argptr);
00500         va_end (argptr);
00501 
00502         return count;
00503 }
00504 
00505 // printf, and output to stderr, with message filtering
00506 sint32 Console::Printf_err(const MsgMask mm, const char *fmt, ...)
00507 {
00508         if(!(mm & msgMask)) return 0;
00509 
00510         va_list argptr;
00511 
00512         va_start(argptr,fmt);
00513         sint32 count = vPrintf_err(fmt, argptr);
00514         va_end(argptr);
00515 
00516         return count;
00517 }
00518 
00519 // printf, and output to stderr (va_list)
00520 sint32 Console::vPrintf_err (const char *fmt, va_list argptr)
00521 {
00522         char msg[MAXPRINTMSG];
00523 
00524         if (std_output_enabled & CON_STDERR) {
00525                 va_list argptr2;
00526                 va_copy(argptr2, argptr);
00527                 vfprintf (stderr, fmt, argptr2);
00528                 va_end(argptr2);
00529         }
00530         sint32 count = vsnprintf (msg, MAXPRINTMSG, fmt, argptr);
00531         if (stderr_redir) stderr_redir->write(msg, count);
00532         PrintInternal (msg);
00533 
00534         return count;
00535 }
00536 
00537 // Print a text string to the console, and output to stderr
00538 void Console::PrintRaw_err (const char *txt, int n)
00539 {
00540         if (std_output_enabled & CON_STDERR) std::fwrite(txt,n,1,stderr);
00541         if (stderr_redir) stderr_redir->write(txt, n);
00542         PrintRawInternal (txt, n);
00543 }
00544 
00545 // putchar, and output to stderr
00546 void Console::Putchar_err (int c)
00547 {
00548         if (std_output_enabled & CON_STDERR) fputc(c, stderr);
00549         if (stderr_redir) stderr_redir->write1(c);
00550         PutcharInternal(c);
00551 }
00552 
00553 void Console::ScrollConsole(sint32 lines)
00554 {
00555         display += lines;
00556 
00557         if (display < 0) display = 0;
00558         if (display > current) display = current;
00559 }
00560 
00561 //
00562 // Console commands
00563 //
00564 
00565 void Console::AddConsoleCommand(const ArgsType &command, Console::Function function)
00566 {
00567         ConsoleCommands[command] = function;
00568 }
00569 
00570 void Console::RemoveConsoleCommand(Console::Function function)
00571 {
00572         std::map<Console::ArgsType,Console::Function>::iterator it;
00573         for (it = ConsoleCommands.begin(); it != ConsoleCommands.end(); ++it)
00574         {
00575                 if (it->second == function)
00576                 {
00577                         //pout << "Removing command: " << it->first << std::endl;
00578                         it->second = 0;
00579                 }
00580         }
00581 }
00582 void Console::ExecuteConsoleCommand(const Console::ArgsType &args)
00583 {
00584         Console::ArgvType argv;
00585         Pentagram::StringToArgv(args,argv);
00586 
00587         ExecuteConsoleCommand(argv);
00588 }
00589 
00590 void Console::ExecuteConsoleCommand(const Console::ArgvType &argv)
00591 {
00592         std::map<Console::ArgsType,Console::Function>::iterator it;
00593 
00594         // Empty?!?
00595         if (argv.empty()) return;
00596 
00597         it = ConsoleCommands.find(argv[0]);
00598 
00599         if (it != ConsoleCommands.end())
00600                 it->second(argv);
00601         else
00602                 pout << "Unknown command: " << argv[0] << std::endl;
00603 }
00604 
00605 void Console::ExecuteCommandBuffer()
00606 {
00607         if (commandBuffer.empty()) return;
00608 
00609         Console::ArgsType args = commandBuffer;
00610         commandBuffer.clear();
00611 
00612         pout << "]" << args << std::endl;
00613 
00614         ExecuteConsoleCommand(args);
00615 
00616         commandHistory.push_back(args);
00617         commandHistoryPos = 0;
00618         commandCursorPos = 0;
00619 }
00620 
00621 void Console::ScrollCommandHistory(int num)
00622 {
00623         int total = commandHistory.size();
00624 
00625         // No history, don't do anything
00626         if (!total) return;
00627 
00628         if ((commandHistoryPos-num) <= 0)
00629         {
00630                 if (commandHistoryPos == 1) return;
00631                 commandHistoryPos = 1;
00632         }
00633         else
00634                 commandHistoryPos -= num;
00635 
00636         if (commandHistoryPos > total)
00637                 commandHistoryPos = total;
00638 
00639         commandBuffer = commandHistory[total-commandHistoryPos];
00640         commandCursorPos = commandBuffer.size();
00641 }
00642 
00643 void Console::ClearCommandBuffer()
00644 {
00645         commandBuffer.clear();
00646         commandCursorPos = 0;
00647 }
00648 
00649 void Console::AddCharacterToCommandBuffer(int ch)
00650 {
00651         // Enter (execute command)
00652         if (ch == Console::Enter) {
00653 
00654                 ExecuteCommandBuffer();
00655         }
00656         // Backspace
00657         else if (ch == Console::Backspace) {
00658 
00659                 DeleteCommandBufferChars(-1);
00660         }
00661         // Tab (command completion)
00662         else if (ch == Console::Tab) {
00663 
00664                 if (!commandBuffer.empty()) {
00665 
00666                         int count = 0;
00667                         Console::ArgsType common;
00668                         std::map<Console::ArgsType,Console::Function>::iterator it;
00669                         std::map<Console::ArgsType,Console::Function>::iterator found;
00670 
00671                         for (it = ConsoleCommands.begin(); it != ConsoleCommands.end(); ++it)
00672                                 if (it->second) {
00673                                         if (it->first.compare(0, commandBuffer.size(), commandBuffer))
00674                                                 continue;
00675 
00676                                         if (!count)
00677                                         {
00678                                                 common = it->first;
00679                                                 found = it;
00680                                         }
00681                                         else
00682                                         {
00683                                                 Console::ArgsType::iterator it1 = common.begin();
00684                                                 Console::ArgsType::const_iterator it2 = it->first.begin();
00685                                                 int comsize = 0;
00686 
00687                                                 while (it1 != common.end())
00688                                                 {
00689                                                         if (!Console::ArgsType::traits_type::eq(*it1,*it2)) break;
00690                                                         
00691                                                         comsize++;
00692                                                         ++it1;
00693                                                         ++it2;
00694                                                 }
00695 
00696                                                 common.resize(comsize);
00697                                         }
00698                                         count++;
00699                                 }
00700 
00701                                 if (count) 
00702                                 {
00703 
00704                                         if (count > 1) {
00705                                                 pout << "]" << commandBuffer << std::endl;
00706 
00707                                                 ArgsType args = "CmdList \""; 
00708                                                 args += commandBuffer;
00709                                                 args += '\"';
00710                                                         
00711                                                 ArgvType argv;
00712                                                 Pentagram::StringToArgv(args,argv);
00713 
00714                                                 ConCmd_CmdList(argv);
00715                                                 commandBuffer = common;
00716                                         }
00717                                         else 
00718                                                 commandBuffer = common;
00719 
00720                                         commandCursorPos = commandBuffer.size();
00721                                 }
00722                         }
00723         }
00724         // Add the character to the command buffer
00725         else {
00726 
00727                 if (commandCursorPos == static_cast<int>(commandBuffer.size()))
00728                 {
00729                         commandBuffer += ch;
00730                 }
00731                 else if (commandInsert)
00732                 {
00733                         commandBuffer.insert(commandCursorPos, 1, ch);
00734                 }
00735                 else
00736                 {
00737                         commandBuffer[commandCursorPos] = ch;
00738                 }
00739 
00740                 commandCursorPos++;
00741         }
00742 }
00743 
00744 void Console::DeleteCommandBufferChars(int num)
00745 {
00746         if (!num || commandBuffer.empty()) return;
00747 
00748         if (num < 0)
00749         {
00750                 num = -num;
00751                 if (num > commandCursorPos) num = commandCursorPos;
00752                 commandCursorPos -= num;
00753         }
00754         else
00755         {
00756                 if ((num+commandCursorPos) > static_cast<int>(commandBuffer.size()))
00757                         num = commandBuffer.size()-commandCursorPos;
00758         }
00759 
00760         commandBuffer.erase(commandCursorPos, num);
00761 }
00762 
00763 void Console::MoveCommandCursor(int num)
00764 {
00765         commandCursorPos += num;
00766 
00767         if (commandCursorPos < 0) commandCursorPos = 0;
00768         if (commandCursorPos > static_cast<int>(commandBuffer.size())) commandCursorPos = static_cast<int>(commandBuffer.size());
00769 }
00770 
00771 void Console::ConCmd_CmdList(const Console::ArgvType &argv)
00772 {
00773         std::map<ArgsType,Function>::iterator it;
00774         int i = 0;
00775 
00776         //pout << std::endl;
00777 
00778         if (argv.size() > 1)
00779         {
00780                 for (std::size_t a = 1; a < argv.size(); a++)
00781                 {
00782                         const ArgsType &arg = argv[a];
00783 
00784                         for (it = con.ConsoleCommands.begin(); it != con.ConsoleCommands.end(); ++it)
00785                                 if (it->second) {
00786                                         if (it->first.compare(0, arg.size(), arg)) continue;
00787                 
00788                                         pout << " " << it->first << std::endl;
00789                                         i ++;
00790                                 }
00791                 }
00792         }
00793         else
00794         {
00795                 for (it = con.ConsoleCommands.begin(); it != con.ConsoleCommands.end(); ++it)
00796                         if (it->second) {
00797                                 pout << " " << it->first << std::endl;
00798                                 i ++;
00799                         }
00800         }
00801 
00802         pout << i << " commands" << std::endl;
00803 }
00804 
00805 void Console::ConCmd_CmdHistory(const Console::ArgvType & /*argv*/)
00806 {
00807         std::vector<ArgsType>::iterator it;
00808 
00809         for (it = con.commandHistory.begin(); it != con.commandHistory.end(); ++it)
00810                 pout << " " << *it << std::endl;
00811 
00812         pout << con.commandHistory.size() << " commands" << std::endl;
00813 }
00814 
00815 /*
00816 ==============================================================================
00817 
00818 DRAWING
00819 
00820 ==============================================================================
00821 */
00822 
00823 void Console::DrawConsole (RenderSurface *surf, int height)
00824 {
00825         int                             i, x, y;
00826         int                             rows;
00827         int                             row;
00828         int                             lines;
00830 
00831         // Need to do this first
00832         PrintPutchar();
00833 
00834         lines = height;
00835         if (lines <= 0)
00836                 return;
00837 
00838         //if (lines > viddef.height)
00839         //      lines = viddef.height;
00840 
00841         //Com_sprintf (version, sizeof(version), "v%4.2f", VERSION);
00842         //for (x=0 ; x<5 ; x++)
00843         //      re.DrawChar (viddef.width-44+x*8, lines-12, 128 + version[x] );
00844 
00845         // draw the text
00846         vislines = lines;
00847         
00848 #if 0
00849         rows = (lines-8)>>3;            // rows of text to draw
00850 
00851         y = lines - 24;
00852 #else
00853         rows = (lines/confont->height)-2;               // rows of text to draw
00854 
00855         y = lines - (confont->height*3);
00856 #endif
00857 
00858 // draw from the bottom up
00859         if (display != current)
00860         {
00861         // draw arrows to show the buffer is backscrolled
00862                 for (x=0 ; x<linewidth ; x+=4)
00863                         surf->PrintCharFixed(confont, '^', (x+1)*confont->width, y);
00864         
00865                 y -= confont->height;
00866                 rows--;
00867         }
00868         
00869         row = display;
00870         for (i=0 ; i<rows ; i++, y-=confont->height, row--)
00871         {
00872                 if (row < 0)
00873                         break;
00874                 if (current - row >= totallines)
00875                         break;          // past scrollback wrap point
00876                         
00877                 char *txt = text + (row % totallines)*linewidth;
00878 
00879                 for (x=0 ; x<linewidth ; x++) {
00880                         surf->PrintCharFixed(confont, txt[x], (x+1)*confont->width, y);
00881                 //      putchar (txt[x]);
00882                 }
00883                 //putchar ('\n');
00884         }
00885 
00886         const char *com = commandBuffer.c_str();
00887         int com_size = commandBuffer.size();
00888         int cur_pos = commandCursorPos;
00889 
00890         if (com_size >= (linewidth-1))
00891         {
00892                 com_size = cur_pos;
00893         }
00894 
00895         //      prestep if horizontally scrolling
00896         if (com_size >= (linewidth-1))
00897         {
00898                 com += 1 + com_size - (linewidth-1);
00899                 cur_pos = linewidth-2;
00900         }
00901 
00902         y = lines-(confont->height*2);
00903 
00904         surf->PrintCharFixed(confont, ']', confont->width, y);
00905 
00906         for (x=0 ; x<(linewidth-2) && com[x]; x++) {
00907                 surf->PrintCharFixed(confont, com[x], (x+2)*confont->width, y);
00908         //      putchar (txt[x]);
00909         }
00910 
00911         // Now for cursor position
00912         if (commandInsert)
00913                 surf->Fill32(0xFFFFFFFF, ((cur_pos+2)*confont->width)+1, y, 2, confont->height);
00914         else
00915                 surf->Fill32(0xFFFFFFFF, ((cur_pos+2)*confont->width)+1, y+confont->height-2, confont->width, 2);
00916 }
00917 
00918 
00919 void Console::DrawConsoleNotify (RenderSurface *surf)
00920 {
00921         int             x, v;
00922         char    *txt;
00923         int             i;
00924         int             time;
00925 
00926         v = 0;
00927         for (i = current-CON_NUM_TIMES+1 ; i<=current ; i++)
00928         {
00929                 if (i < 0) continue;
00930                 time = con.times[i % CON_NUM_TIMES];
00931                 if (time == 0) continue;
00932 
00933                 time = framenum - time;
00934                 //if (time > con_notifytime->value*1000)
00935                 if (time > 150) // Each message lasts 5 seconds  (30*5=150 frames)
00936                         continue;
00937                 txt = text + (i % totallines)*linewidth;
00938                 
00939                 for (x = 0 ; x < con.linewidth ; x++)
00940                         surf->PrintCharFixed(confont, txt[x], (x+1)*confont->width, v);
00941 
00942                 v += confont->height;
00943         }
00944 }
00945 
00946 

Generated on Fri Jul 27 22:27:11 2007 for pentagram by  doxygen 1.4.7