Annotation of quakeworld/client/console.c, revision 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.