home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / glquake_src / console.c < prev    next >
C/C++ Source or Header  |  1999-12-28  |  13KB  |  667 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. #ifdef NeXT
  23. #include <libc.h>
  24. #endif
  25. #ifndef AMIGA
  26. #ifndef _MSC_VER
  27. #include <unistd.h>
  28. #endif
  29. #include <fcntl.h>
  30. #endif
  31. #include "quakedef.h"
  32.  
  33. int     con_linewidth;
  34.  
  35. float   con_cursorspeed = 4;
  36.  
  37. #define   CON_TEXTSIZE  16384
  38.  
  39. qboolean  con_forcedup;   // because no entities to refresh
  40.  
  41. int     con_totallines;   // total lines in console scrollback
  42. int     con_backscroll;   // lines up from bottom to display
  43. int     con_current;    // where next message will be printed
  44. int     con_x;        // offset in current line for next print
  45. char    *con_text=0;
  46.  
  47. cvar_t    con_notifytime = {"con_notifytime","3"};    //seconds
  48.  
  49. #define NUM_CON_TIMES 4
  50. float   con_times[NUM_CON_TIMES]; // realtime time the line was generated
  51.                 // for transparent notify lines
  52.  
  53. int     con_vislines;
  54.  
  55. qboolean  con_debuglog;
  56.  
  57. #define   MAXCMDLINE  256
  58. extern  char  key_lines[32][MAXCMDLINE];
  59. extern  int   edit_line;
  60. extern  int   key_linepos;
  61.     
  62.  
  63. qboolean  con_initialized;
  64.  
  65. int     con_notifylines;    // scan lines to clear for notify lines
  66.  
  67. extern void M_Menu_Main_f (void);
  68.  
  69. /*
  70. ================
  71. Con_ToggleConsole_f
  72. ================
  73. */
  74. void Con_ToggleConsole_f (void)
  75. {
  76.   if (key_dest == key_console)
  77.   {
  78.     if (cls.state == ca_connected)
  79.     {
  80.       key_dest = key_game;
  81.       key_lines[edit_line][1] = 0;  // clear any typing
  82.       key_linepos = 1;
  83.     }
  84.     else
  85.     {
  86.       M_Menu_Main_f ();
  87.     }
  88.   }
  89.   else
  90.     key_dest = key_console;
  91.   
  92.   SCR_EndLoadingPlaque ();
  93.   memset (con_times, 0, sizeof(con_times));
  94. }
  95.  
  96. /*
  97. ================
  98. Con_Clear_f
  99. ================
  100. */
  101. void Con_Clear_f (void)
  102. {
  103.   if (con_text)
  104.     Q_memset (con_text, ' ', CON_TEXTSIZE);
  105. }
  106.  
  107.             
  108. /*
  109. ================
  110. Con_ClearNotify
  111. ================
  112. */
  113. void Con_ClearNotify (void)
  114. {
  115.   int   i;
  116.   
  117.   for (i=0 ; i<NUM_CON_TIMES ; i++)
  118.     con_times[i] = 0;
  119. }
  120.  
  121.             
  122. /*
  123. ================
  124. Con_MessageMode_f
  125. ================
  126. */
  127. extern qboolean team_message;
  128.  
  129. void Con_MessageMode_f (void)
  130. {
  131.   key_dest = key_message;
  132.   team_message = false;
  133. }
  134.  
  135.             
  136. /*
  137. ================
  138. Con_MessageMode2_f
  139. ================
  140. */
  141. void Con_MessageMode2_f (void)
  142. {
  143.   key_dest = key_message;
  144.   team_message = true;
  145. }
  146.  
  147.             
  148. /*
  149. ================
  150. Con_CheckResize
  151.  
  152. If the line width has changed, reformat the buffer.
  153. ================
  154. */
  155. void Con_CheckResize (void)
  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_backscroll = 0;
  205.   con_current = con_totallines - 1;
  206. }
  207.  
  208.  
  209. /*
  210. ================
  211. Con_Init
  212. ================
  213. */
  214. void Con_Init (void)
  215. {
  216. #define MAXGAMEDIRLEN 1000
  217.   char  temp[MAXGAMEDIRLEN+1];
  218.   char  *t2 = "/qconsole.log";
  219.  
  220.   con_debuglog = COM_CheckParm("-condebug");
  221.  
  222.   if (con_debuglog)
  223.   {
  224.     if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2)))
  225.     {
  226.       sprintf (temp, "%s%s", com_gamedir, t2);
  227. #ifdef AMIGA
  228.       remove (temp);
  229. #else
  230.       unlink (temp);
  231. #endif
  232.     }
  233.   }
  234.  
  235.   con_text = Hunk_AllocName (CON_TEXTSIZE, "context");
  236.   Q_memset (con_text, ' ', CON_TEXTSIZE);
  237.   con_linewidth = -1;
  238.   Con_CheckResize ();
  239.   
  240.   Con_Printf ("Console initialized.\n");
  241.  
  242. //
  243. // register our commands
  244. //
  245.   Cvar_RegisterVariable (&con_notifytime);
  246.  
  247.   Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
  248.   Cmd_AddCommand ("messagemode", Con_MessageMode_f);
  249.   Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
  250.   Cmd_AddCommand ("clear", Con_Clear_f);
  251.   con_initialized = true;
  252. }
  253.  
  254.  
  255. /*
  256. ===============
  257. Con_Linefeed
  258. ===============
  259. */
  260. void Con_Linefeed (void)
  261. {
  262.   con_x = 0;
  263.   con_current++;
  264.   Q_memset (&con_text[(con_current%con_totallines)*con_linewidth]
  265.   , ' ', con_linewidth);
  266. }
  267.  
  268. /*
  269. ================
  270. Con_Print
  271.  
  272. Handles cursor positioning, line wrapping, etc
  273. All console printing must go through this in order to be logged to disk
  274. If no console is visible, the notify window will pop up.
  275. ================
  276. */
  277. void Con_Print (char *txt)
  278. {
  279.   int   y;
  280.   int   c, l;
  281.   static int  cr;
  282.   int   mask;
  283.   
  284.   con_backscroll = 0;
  285.  
  286.   if (txt[0] == 1)
  287.   {
  288.     mask = 128;   // go to colored text
  289.     S_LocalSound ("misc/talk.wav");
  290.   // play talk wav
  291.     txt++;
  292.   }
  293.   else if (txt[0] == 2)
  294.   {
  295.     mask = 128;   // go to colored text
  296.     txt++;
  297.   }
  298.   else
  299.     mask = 0;
  300.  
  301.  
  302.   while ( (c = *txt) )
  303.   {
  304.   // count word length
  305.     for (l=0 ; l< con_linewidth ; l++)
  306.       if ( txt[l] <= ' ')
  307.         break;
  308.  
  309.   // word wrap
  310.     if (l != con_linewidth && (con_x + l > con_linewidth) )
  311.       con_x = 0;
  312.  
  313.     txt++;
  314.  
  315.     if (cr)
  316.     {
  317.       con_current--;
  318.       cr = false;
  319.     }
  320.  
  321.     
  322.     if (!con_x)
  323.     {
  324.       Con_Linefeed ();
  325.     // mark time for transparent overlay
  326.       if (con_current >= 0)
  327.         con_times[con_current % NUM_CON_TIMES] = realtime;
  328.     }
  329.  
  330.     switch (c)
  331.     {
  332.     case '\n':
  333.       con_x = 0;
  334.       break;
  335.  
  336.     case '\r':
  337.       con_x = 0;
  338.       cr = 1;
  339.       break;
  340.  
  341.     default:  // display character and advance
  342.       y = con_current % con_totallines;
  343.       con_text[y*con_linewidth+con_x] = c | mask;
  344.       con_x++;
  345.       if (con_x >= con_linewidth)
  346.         con_x = 0;
  347.       break;
  348.     }
  349.     
  350.   }
  351. }
  352.  
  353.  
  354. /*
  355. ================
  356. Con_DebugLog
  357. ================
  358. */
  359. void Con_DebugLog(char *file, char *fmt, ...)
  360. {
  361.     va_list argptr; 
  362.     static char data[1024];
  363. #ifdef AMIGA
  364.     FILE *fh;
  365. #else
  366.     int fd;
  367. #endif
  368.     
  369.     va_start(argptr, fmt);
  370.     vsprintf(data, fmt, argptr);
  371.     va_end(argptr);
  372. #ifdef AMIGA
  373.     if (fh = fopen(file,"a")) {
  374.       fwrite(data,1,strlen(data),fh);
  375.       fclose(fh);
  376.     }
  377. #else
  378.     fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
  379.     write(fd, data, strlen(data));
  380.     close(fd);
  381. #endif
  382. }
  383.  
  384.  
  385. /*
  386. ================
  387. Con_Printf
  388.  
  389. Handles cursor positioning, line wrapping, etc
  390. ================
  391. */
  392. #define MAXPRINTMSG 4096
  393. // FIXME: make a buffer size safe vsprintf?
  394. void Con_Printf (char *fmt, ...)
  395. {
  396.   va_list   argptr;
  397.   char    msg[MAXPRINTMSG];
  398.   static qboolean inupdate;
  399.   
  400.   va_start (argptr,fmt);
  401.   vsprintf (msg,fmt,argptr);
  402.   va_end (argptr);
  403.   
  404. // also echo to debugging console
  405.   Sys_Printf ("%s", msg); // also echo to debugging console
  406.  
  407. // log all messages to file
  408.   if (con_debuglog)
  409.     Con_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg);
  410.  
  411.   if (!con_initialized)
  412.     return;
  413.     
  414.   if (cls.state == ca_dedicated)
  415.     return;   // no graphics mode
  416.  
  417. // write it to the scrollable buffer
  418.   Con_Print (msg);
  419.   
  420. // update the screen if the console is displayed
  421.   if (cls.signon != SIGNONS && !scr_disabled_for_loading )
  422.   {
  423.   // protect against infinite loop if something in SCR_UpdateScreen calls
  424.   // Con_Printd
  425.     if (!inupdate)
  426.     {
  427.       inupdate = true;
  428.       SCR_UpdateScreen ();
  429.       inupdate = false;
  430.     }
  431.   }
  432. }
  433.  
  434. /*
  435. ================
  436. Con_DPrintf
  437.  
  438. A Con_Printf that only shows up if the "developer" cvar is set
  439. ================
  440. */
  441. void Con_DPrintf (char *fmt, ...)
  442. {
  443.   va_list   argptr;
  444.   char    msg[MAXPRINTMSG];
  445.     
  446.   if (!developer.value)
  447.     return;     // don't confuse non-developers with techie stuff...
  448.  
  449.   va_start (argptr,fmt);
  450.   vsprintf (msg,fmt,argptr);
  451.   va_end (argptr);
  452.   
  453.   Con_Printf ("%s", msg);
  454. }
  455.  
  456.  
  457. /*
  458. ==================
  459. Con_SafePrintf
  460.  
  461. Okay to call even when the screen can't be updated
  462. ==================
  463. */
  464. void Con_SafePrintf (char *fmt, ...)
  465. {
  466.   va_list   argptr;
  467.   char    msg[1024];
  468.   int     temp;
  469.     
  470.   va_start (argptr,fmt);
  471.   vsprintf (msg,fmt,argptr);
  472.   va_end (argptr);
  473.  
  474.   temp = scr_disabled_for_loading;
  475.   scr_disabled_for_loading = true;
  476.   Con_Printf ("%s", msg);
  477.   scr_disabled_for_loading = temp;
  478. }
  479.  
  480.  
  481. /*
  482. ==============================================================================
  483.  
  484. DRAWING
  485.  
  486. ==============================================================================
  487. */
  488.  
  489.  
  490. /*
  491. ================
  492. Con_DrawInput
  493.  
  494. The input line scrolls horizontally if typing goes beyond the right edge
  495. ================
  496. */
  497. void Con_DrawInput (void)
  498. {
  499.   int   y;
  500.   int   i;
  501.   char  *text;
  502.  
  503.   if (key_dest != key_console && !con_forcedup)
  504.     return;   // don't draw anything
  505.  
  506.   text = key_lines[edit_line];
  507.   
  508. // add the cursor frame
  509.   text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1);
  510.   
  511. // fill out remainder with spaces
  512.   for (i=key_linepos+1 ; i< con_linewidth ; i++)
  513.     text[i] = ' ';
  514.     
  515. //  prestep if horizontally scrolling
  516.   if (key_linepos >= con_linewidth)
  517.     text += 1 + key_linepos - con_linewidth;
  518.     
  519. // draw it
  520.   y = con_vislines-16;
  521.  
  522.   for (i=0 ; i<con_linewidth ; i++)
  523.     Draw_Character ( (i+1)<<3, con_vislines - 16, text[i]);
  524.  
  525. // remove cursor
  526.   key_lines[edit_line][key_linepos] = 0;
  527. }
  528.  
  529.  
  530. /*
  531. ================
  532. Con_DrawNotify
  533.  
  534. Draws the last few lines of output transparently over the game top
  535. ================
  536. */
  537. void Con_DrawNotify (void)
  538. {
  539.   int   x, v;
  540.   char  *text;
  541.   int   i;
  542.   float time;
  543.   extern char chat_buffer[];
  544.  
  545.   v = 0;
  546.   for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
  547.   {
  548.     if (i < 0)
  549.       continue;
  550.     time = con_times[i % NUM_CON_TIMES];
  551.     if (time == 0)
  552.       continue;
  553.     time = realtime - time;
  554.     if (time > con_notifytime.value)
  555.       continue;
  556.     text = con_text + (i % con_totallines)*con_linewidth;
  557.     
  558.     clearnotify = 0;
  559.     scr_copytop = 1;
  560.  
  561.     for (x = 0 ; x < con_linewidth ; x++)
  562.       Draw_Character ( (x+1)<<3, v, text[x]);
  563.  
  564.     v += 8;
  565.   }
  566.  
  567.  
  568.   if (key_dest == key_message)
  569.   {
  570.     clearnotify = 0;
  571.     scr_copytop = 1;
  572.   
  573.     x = 0;
  574.     
  575.     Draw_String (8, v, "say:");
  576.     while(chat_buffer[x])
  577.     {
  578.       Draw_Character ( (x+5)<<3, v, chat_buffer[x]);
  579.       x++;
  580.     }
  581.     Draw_Character ( (x+5)<<3, v, 10+((int)(realtime*con_cursorspeed)&1));
  582.     v += 8;
  583.   }
  584.   
  585.   if (v > con_notifylines)
  586.     con_notifylines = v;
  587. }
  588.  
  589. /*
  590. ================
  591. Con_DrawConsole
  592.  
  593. Draws the console with the solid background
  594. The typing input line at the bottom should only be drawn if typing is allowed
  595. ================
  596. */
  597. void Con_DrawConsole (int lines, qboolean drawinput)
  598. {
  599.   int       i, x, y;
  600.   int       rows;
  601.   char      *text;
  602.   int       j;
  603.   
  604.   if (lines <= 0)
  605.     return;
  606.  
  607. // draw the background
  608.   Draw_ConsoleBackground (lines);
  609.  
  610. // draw the text
  611.   con_vislines = lines;
  612.  
  613.   rows = (lines-16)>>3;   // rows of text to draw
  614.   y = lines - 16 - (rows<<3); // may start slightly negative
  615.  
  616.   for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8 )
  617.   {
  618.     j = i - con_backscroll;
  619.     if (j<0)
  620.       j = 0;
  621.     text = con_text + (j % con_totallines)*con_linewidth;
  622.  
  623.     for (x=0 ; x<con_linewidth ; x++)
  624.       Draw_Character ( (x+1)<<3, y, text[x]);
  625.   }
  626.  
  627. // draw the input prompt, user text, and cursor if desired
  628.   if (drawinput)
  629.     Con_DrawInput ();
  630. }
  631.  
  632.  
  633. /*
  634. ==================
  635. Con_NotifyBox
  636. ==================
  637. */
  638. void Con_NotifyBox (char *text)
  639. {
  640.   double    t1, t2;
  641.  
  642. // during startup for sound / cd warnings
  643.   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");
  644.  
  645.   Con_Printf (text);
  646.  
  647.   Con_Printf ("Press a key.\n");
  648.   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");
  649.  
  650.   key_count = -2;   // wait for a key down and up
  651.   key_dest = key_console;
  652.  
  653.   do
  654.   {
  655.     t1 = Sys_FloatTime ();
  656.     SCR_UpdateScreen ();
  657.     Sys_SendKeyEvents ();
  658.     t2 = Sys_FloatTime ();
  659.     realtime += t2-t1;    // make the cursor blink
  660.   } while (key_count < 0);
  661.  
  662.   Con_Printf ("\n");
  663.   key_dest = key_game;
  664.   realtime = 0;       // put the cursor back to invisible
  665. }
  666.  
  667.