Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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