Annotation of quakeworld/client/console.c, revision 1.1.1.1

1.1       root        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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.