home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / console.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  13.3 KB  |  694 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // console.c
  21.  
  22. #include "quakedef.h"
  23.  
  24. int     con_ormask;
  25. console_t con_main;
  26. console_t con_chat;
  27. console_t *con;     // point to either con_main or con_chat
  28.  
  29. int     con_linewidth;  // characters across screen
  30. int     con_totallines;   // total lines in console scrollback
  31.  
  32. float   con_cursorspeed = 4;
  33.  
  34.  
  35. cvar_t    con_notifytime = {"con_notifytime","3"};    //seconds
  36.  
  37. #define NUM_CON_TIMES 4
  38. float   con_times[NUM_CON_TIMES]; // realtime time the line was generated
  39.                 // for transparent notify lines
  40.  
  41. int     con_vislines;
  42. int     con_notifylines;    // scan lines to clear for notify lines
  43.  
  44. qboolean  con_debuglog;
  45.  
  46. #define   MAXCMDLINE  256
  47. extern  char  key_lines[32][MAXCMDLINE];
  48. extern  int   edit_line;
  49. extern  int   key_linepos;
  50.     
  51.  
  52. qboolean  con_initialized;
  53.  
  54.  
  55. void Key_ClearTyping (void)
  56. {
  57.   key_lines[edit_line][1] = 0;  // clear any typing
  58.   key_linepos = 1;
  59. }
  60.  
  61. /*
  62. ================
  63. Con_ToggleConsole_f
  64. ================
  65. */
  66. void Con_ToggleConsole_f (void)
  67. {
  68.   Key_ClearTyping ();
  69.  
  70.   if (key_dest == key_console)
  71.   {
  72.     if (cls.state == ca_active)
  73.       key_dest = key_game;
  74.   }
  75.   else
  76.     key_dest = key_console;
  77.   
  78.   Con_ClearNotify ();
  79. }
  80.  
  81. /*
  82. ================
  83. Con_ToggleChat_f
  84. ================
  85. */
  86. void Con_ToggleChat_f (void)
  87. {
  88.   Key_ClearTyping ();
  89.  
  90.   if (key_dest == key_console)
  91.   {
  92.     if (cls.state == ca_active)
  93.       key_dest = key_game;
  94.   }
  95.   else
  96.     key_dest = key_console;
  97.   
  98.   Con_ClearNotify ();
  99. }
  100.  
  101. /*
  102. ================
  103. Con_Clear_f
  104. ================
  105. */
  106. void Con_Clear_f (void)
  107. {
  108.   Q_memset (con_main.text, ' ', CON_TEXTSIZE);
  109.   Q_memset (con_chat.text, ' ', CON_TEXTSIZE);
  110. }
  111.  
  112.             
  113. /*
  114. ================
  115. Con_ClearNotify
  116. ================
  117. */
  118. void Con_ClearNotify (void)
  119. {
  120.   int   i;
  121.   
  122.   for (i=0 ; i<NUM_CON_TIMES ; i++)
  123.     con_times[i] = 0;
  124. }
  125.  
  126.             
  127. /*
  128. ================
  129. Con_MessageMode_f
  130. ================
  131. */
  132. void Con_MessageMode_f (void)
  133. {
  134.   chat_team = false;
  135.   key_dest = key_message;
  136. }
  137.  
  138. /*
  139. ================
  140. Con_MessageMode2_f
  141. ================
  142. */
  143. void Con_MessageMode2_f (void)
  144. {
  145.   chat_team = true;
  146.   key_dest = key_message;
  147. }
  148.  
  149. /*
  150. ================
  151. Con_Resize
  152.  
  153. ================
  154. */
  155. void Con_Resize (console_t *con)
  156. {
  157.   int   i, j, width, oldwidth, oldtotallines, numlines, numchars;
  158.   char  tbuf[CON_TEXTSIZE];
  159.  
  160.   width = (vid.width >> 3) - 2;
  161.  
  162.   if (width == con_linewidth)
  163.     return;
  164.  
  165.   if (width < 1)      // video hasn't been initialized yet
  166.   {
  167.     width = 38;
  168.     con_linewidth = width;
  169.     con_totallines = CON_TEXTSIZE / con_linewidth;
  170.     Q_memset (con->text, ' ', CON_TEXTSIZE);
  171.   }
  172.   else
  173.   {
  174.     oldwidth = con_linewidth;
  175.     con_linewidth = width;
  176.     oldtotallines = con_totallines;
  177.     con_totallines = CON_TEXTSIZE / con_linewidth;
  178.     numlines = oldtotallines;
  179.  
  180.     if (con_totallines < numlines)
  181.       numlines = con_totallines;
  182.  
  183.     numchars = oldwidth;
  184.   
  185.     if (con_linewidth < numchars)
  186.       numchars = con_linewidth;
  187.  
  188.     Q_memcpy (tbuf, con->text, CON_TEXTSIZE);
  189.     Q_memset (con->text, ' ', CON_TEXTSIZE);
  190.  
  191.     for (i=0 ; i<numlines ; i++)
  192.     {
  193.       for (j=0 ; j<numchars ; j++)
  194.       {
  195.         con->text[(con_totallines - 1 - i) * con_linewidth + j] =
  196.             tbuf[((con->current - i + oldtotallines) %
  197.                 oldtotallines) * oldwidth + j];
  198.       }
  199.     }
  200.  
  201.     Con_ClearNotify ();
  202.   }
  203.  
  204.   con->current = con_totallines - 1;
  205.   con->display = con->current;
  206. }
  207.  
  208.           
  209. /*
  210. ================
  211. Con_CheckResize
  212.  
  213. If the line width has changed, reformat the buffer.
  214. ================
  215. */
  216. void Con_CheckResize (void)
  217. {
  218.   Con_Resize (&con_main);
  219.   Con_Resize (&con_chat);
  220. }
  221.  
  222.  
  223. /*
  224. ================
  225. Con_Init
  226. ================
  227. */
  228. void Con_Init (void)
  229. {
  230.   con_debuglog = COM_CheckParm("-condebug");
  231.  
  232.   con = &con_main;
  233.   con_linewidth = -1;
  234.   Con_CheckResize ();
  235.   
  236.   Con_Printf ("Console initialized.\n");
  237.  
  238. //
  239. // register our commands
  240. //
  241.   Cvar_RegisterVariable (&con_notifytime);
  242.  
  243.   Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
  244.   Cmd_AddCommand ("togglechat", Con_ToggleChat_f);
  245.   Cmd_AddCommand ("messagemode", Con_MessageMode_f);
  246.   Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
  247.   Cmd_AddCommand ("clear", Con_Clear_f);
  248.   con_initialized = true;
  249. }
  250.  
  251.  
  252. /*
  253. ===============
  254. Con_Linefeed
  255. ===============
  256. */
  257. void Con_Linefeed (void)
  258. {
  259.   con->x = 0;
  260.   if (con->display == con->current)
  261.     con->display++;
  262.   con->current++;
  263.   Q_memset (&con->text[(con->current%con_totallines)*con_linewidth]
  264.   , ' ', con_linewidth);
  265. }
  266.  
  267. /*
  268. ================
  269. Con_Print
  270.  
  271. Handles cursor positioning, line wrapping, etc
  272. All console printing must go through this in order to be logged to disk
  273. If no console is visible, the notify window will pop up.
  274. ================
  275. */
  276. void Con_Print (char *txt)
  277. {
  278.   int   y;
  279.   int   c, l;
  280.   static int  cr;
  281.   int   mask;
  282.  
  283.   if (txt[0] == 1 || txt[0] == 2)
  284.   {
  285.     mask = 128;   // go to colored text
  286.     txt++;
  287.   }
  288.   else
  289.     mask = 0;
  290.  
  291.  
  292.   while ( (c = *txt) )
  293.   {
  294.   // count word length
  295.     for (l=0 ; l< con_linewidth ; l++)
  296.       if ( txt[l] <= ' ')
  297.         break;
  298.  
  299.   // word wrap
  300.     if (l != con_linewidth && (con->x + l > con_linewidth) )
  301.       con->x = 0;
  302.  
  303.     txt++;
  304.  
  305.     if (cr)
  306.     {
  307.       con->current--;
  308.       cr = false;
  309.     }
  310.  
  311.     
  312.     if (!con->x)
  313.     {
  314.       Con_Linefeed ();
  315.     // mark time for transparent overlay
  316.       if (con->current >= 0)
  317.         con_times[con->current % NUM_CON_TIMES] = realtime;
  318.     }
  319.  
  320.     switch (c)
  321.     {
  322.     case '\n':
  323.       con->x = 0;
  324.       break;
  325.  
  326.     case '\r':
  327.       con->x = 0;
  328.       cr = 1;
  329.       break;
  330.  
  331.     default:  // display character and advance
  332.       y = con->current % con_totallines;
  333.       con->text[y*con_linewidth+con->x] = c | mask | con_ormask;
  334.       con->x++;
  335.       if (con->x >= con_linewidth)
  336.         con->x = 0;
  337.       break;
  338.     }
  339.     
  340.   }
  341. }
  342.  
  343.  
  344. /*
  345. ================
  346. Con_Printf
  347.  
  348. Handles cursor positioning, line wrapping, etc
  349. ================
  350. */
  351. #define MAXPRINTMSG 4096
  352. // FIXME: make a buffer size safe vsprintf?
  353. void Con_Printf (char *fmt, ...)
  354. {
  355.   va_list   argptr;
  356.   char    msg[MAXPRINTMSG];
  357.   static qboolean inupdate;
  358.   
  359.   va_start (argptr,fmt);
  360.   vsprintf (msg,fmt,argptr);
  361.   va_end (argptr);
  362.   
  363. // also echo to debugging console
  364.   Sys_Printf ("%s", msg); // also echo to debugging console
  365.  
  366. // log all messages to file
  367.   if (con_debuglog)
  368.     Sys_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg);
  369.     
  370.   if (!con_initialized)
  371.     return;
  372.     
  373. // write it to the scrollable buffer
  374.   Con_Print (msg);
  375.   
  376. // update the screen immediately if the console is displayed
  377.   if (cls.state != ca_active)
  378.   {
  379.   // protect against infinite loop if something in SCR_UpdateScreen calls
  380.   // Con_Printd
  381.     if (!inupdate)
  382.     {
  383.       inupdate = true;
  384.       SCR_UpdateScreen ();
  385.       inupdate = false;
  386.     }
  387.   }
  388. }
  389.  
  390. /*
  391. ================
  392. Con_DPrintf
  393.  
  394. A Con_Printf that only shows up if the "developer" cvar is set
  395. ================
  396. */
  397. void Con_DPrintf (char *fmt, ...)
  398. {
  399.   va_list   argptr;
  400.   char    msg[MAXPRINTMSG];
  401.     
  402.   if (!developer.value)
  403.     return;     // don't confuse non-developers with techie stuff...
  404.  
  405.   va_start (argptr,fmt);
  406.   vsprintf (msg,fmt,argptr);
  407.   va_end (argptr);
  408.   
  409.   Con_Printf ("%s", msg);
  410. }
  411.  
  412. /*
  413. ==============================================================================
  414.  
  415. DRAWING
  416.  
  417. ==============================================================================
  418. */
  419.  
  420.  
  421. /*
  422. ================
  423. Con_DrawInput
  424.  
  425. The input line scrolls horizontally if typing goes beyond the right edge
  426. ================
  427. */
  428. void Con_DrawInput (void)
  429. {
  430.   int   y;
  431.   int   i;
  432.   char  *text;
  433.  
  434.   if (key_dest != key_console && cls.state == ca_active)
  435.     return;   // don't draw anything (allways draw if not active)
  436.  
  437.   text = key_lines[edit_line];
  438.   
  439. // add the cursor frame
  440.   text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1);
  441.   
  442. // fill out remainder with spaces
  443.   for (i=key_linepos+1 ; i< con_linewidth ; i++)
  444.     text[i] = ' ';
  445.     
  446. //  prestep if horizontally scrolling
  447.   if (key_linepos >= con_linewidth)
  448.     text += 1 + key_linepos - con_linewidth;
  449.     
  450. // draw it
  451.   y = con_vislines-22;
  452.  
  453.   for (i=0 ; i<con_linewidth ; i++)
  454.     Draw_Character ( (i+1)<<3, con_vislines - 22, text[i]);
  455.  
  456. // remove cursor
  457.   key_lines[edit_line][key_linepos] = 0;
  458. }
  459.  
  460.  
  461. /*
  462. ================
  463. Con_DrawNotify
  464.  
  465. Draws the last few lines of output transparently over the game top
  466. ================
  467. */
  468. void Con_DrawNotify (void)
  469. {
  470.   int   x, v;
  471.   char  *text;
  472.   int   i;
  473.   float time;
  474.   char  *s;
  475.   int   skip;
  476.  
  477.   v = 0;
  478.   for (i= con->current-NUM_CON_TIMES+1 ; i<=con->current ; i++)
  479.   {
  480.     if (i < 0)
  481.       continue;
  482.     time = con_times[i % NUM_CON_TIMES];
  483.     if (time == 0)
  484.       continue;
  485.     time = realtime - time;
  486.     if (time > con_notifytime.value)
  487.       continue;
  488.     text = con->text + (i % con_totallines)*con_linewidth;
  489.     
  490.     clearnotify = 0;
  491.     scr_copytop = 1;
  492.  
  493.     for (x = 0 ; x < con_linewidth ; x++)
  494.       Draw_Character ( (x+1)<<3, v, text[x]);
  495.  
  496.     v += 8;
  497.   }
  498.  
  499.  
  500.   if (key_dest == key_message)
  501.   {
  502.     clearnotify = 0;
  503.     scr_copytop = 1;
  504.   
  505.     if (chat_team)
  506.     {
  507.       Draw_String (8, v, "say_team:");
  508.       skip = 11;
  509.     }
  510.     else
  511.     {
  512.       Draw_String (8, v, "say:");
  513.       skip = 5;
  514.     }
  515.  
  516.     s = chat_buffer;
  517.     if (chat_bufferlen > (vid.width>>3)-(skip+1))
  518.       s += chat_bufferlen - ((vid.width>>3)-(skip+1));
  519.     x = 0;
  520.     while(s[x])
  521.     {
  522.       Draw_Character ( (x+skip)<<3, v, s[x]);
  523.       x++;
  524.     }
  525.     Draw_Character ( (x+skip)<<3, v, 10+((int)(realtime*con_cursorspeed)&1));
  526.     v += 8;
  527.   }
  528.   
  529.   if (v > con_notifylines)
  530.     con_notifylines = v;
  531. }
  532.  
  533. /*
  534. ================
  535. Con_DrawConsole
  536.  
  537. Draws the console with the solid background
  538. ================
  539. */
  540. void Con_DrawConsole (int lines)
  541. {
  542.   int       i, j, x, y, n;
  543.   int       rows;
  544.   char      *text;
  545.   int       row;
  546.   char      dlbar[1024];
  547.   
  548.   if (lines <= 0)
  549.     return;
  550.  
  551. // draw the background
  552.   Draw_ConsoleBackground (lines);
  553.  
  554. // draw the text
  555.   con_vislines = lines;
  556.   
  557. // changed to line things up better
  558.   rows = (lines-22)>>3;   // rows of text to draw
  559.  
  560.   y = lines - 30;
  561.  
  562. // draw from the bottom up
  563.   if (con->display != con->current)
  564.   {
  565.   // draw arrows to show the buffer is backscrolled
  566.     for (x=0 ; x<con_linewidth ; x+=4)
  567.       Draw_Character ( (x+1)<<3, y, '^');
  568.   
  569.     y -= 8;
  570.     rows--;
  571.   }
  572.   
  573.   row = con->display;
  574.   for (i=0 ; i<rows ; i++, y-=8, row--)
  575.   {
  576.     if (row < 0)
  577.       break;
  578.     if (con->current - row >= con_totallines)
  579.       break;    // past scrollback wrap point
  580.       
  581.     text = con->text + (row % con_totallines)*con_linewidth;
  582.  
  583.     for (x=0 ; x<con_linewidth ; x++)
  584.       Draw_Character ( (x+1)<<3, y, text[x]);
  585.   }
  586.  
  587.   // draw the download bar
  588.   // figure out width
  589.   if (cls.download) {
  590.     if ((text = strrchr(cls.downloadname, '/')) != NULL)
  591.       text++;
  592.     else
  593.       text = cls.downloadname;
  594.  
  595.     x = con_linewidth - ((con_linewidth * 7) / 40);
  596.     y = x - strlen(text) - 8;
  597.     i = con_linewidth/3;
  598.     if (strlen(text) > i) {
  599.       y = x - i - 11;
  600.       strncpy(dlbar, text, i);
  601.       dlbar[i] = 0;
  602.       strcat(dlbar, "...");
  603.     } else
  604.       strcpy(dlbar, text);
  605.     strcat(dlbar, ": ");
  606.     i = strlen(dlbar);
  607.     dlbar[i++] = '\x80';
  608.     // where's the dot go?
  609.     if (cls.downloadpercent == 0)
  610.       n = 0;
  611.     else
  612.       n = y * cls.downloadpercent / 100;
  613.       
  614.     for (j = 0; j < y; j++)
  615.       if (j == n)
  616.         dlbar[i++] = '\x83';
  617.       else
  618.         dlbar[i++] = '\x81';
  619.     dlbar[i++] = '\x82';
  620.     dlbar[i] = 0;
  621.  
  622.     sprintf(dlbar + strlen(dlbar), " %02d%%", cls.downloadpercent);
  623.  
  624.     // draw it
  625.     y = con_vislines-22 + 8;
  626.     for (i = 0; i < strlen(dlbar); i++)
  627.       Draw_Character ( (i+1)<<3, y, dlbar[i]);
  628.   }
  629.  
  630.  
  631. // draw the input prompt, user text, and cursor if desired
  632.   Con_DrawInput ();
  633. }
  634.  
  635.  
  636. /*
  637. ==================
  638. Con_NotifyBox
  639. ==================
  640. */
  641. void Con_NotifyBox (char *text)
  642. {
  643.   double    t1, t2;
  644.  
  645. // during startup for sound / cd warnings
  646.   Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
  647.  
  648.   Con_Printf (text);
  649.  
  650.   Con_Printf ("Press a key.\n");
  651.   Con_Printf("\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
  652.  
  653.   key_count = -2;   // wait for a key down and up
  654.   key_dest = key_console;
  655.  
  656.   do
  657.   {
  658.     t1 = Sys_DoubleTime ();
  659.     SCR_UpdateScreen ();
  660.     Sys_SendKeyEvents ();
  661.     t2 = Sys_DoubleTime ();
  662.     realtime += t2-t1;    // make the cursor blink
  663.   } while (key_count < 0);
  664.  
  665.   Con_Printf ("\n");
  666.   key_dest = key_game;
  667.   realtime = 0;       // put the cursor back to invisible
  668. }
  669.  
  670.  
  671. /*
  672. ==================
  673. Con_SafePrintf
  674.  
  675. Okay to call even when the screen can't be updated
  676. ==================
  677. */
  678. void Con_SafePrintf (char *fmt, ...)
  679. {
  680.   va_list   argptr;
  681.   char    msg[1024];
  682.   int     temp;
  683.     
  684.   va_start (argptr,fmt);
  685.   vsprintf (msg,fmt,argptr);
  686.   va_end (argptr);
  687.   
  688.   temp = scr_disabled_for_loading;
  689.   scr_disabled_for_loading = true;
  690.   Con_Printf ("%s", msg);
  691.   scr_disabled_for_loading = temp;
  692. }
  693.  
  694.