|
|
1.1 ! root 1: // console.c ! 2: ! 3: #include "client.h" ! 4: ! 5: console_t con; ! 6: ! 7: cvar_t *con_notifytime; ! 8: ! 9: ! 10: #define MAXCMDLINE 256 ! 11: extern char key_lines[32][MAXCMDLINE]; ! 12: extern int edit_line; ! 13: extern int key_linepos; ! 14: ! 15: ! 16: void DrawString (int x, int y, char *s) ! 17: { ! 18: while (*s) ! 19: { ! 20: re.DrawChar (x, y, *s); ! 21: x+=8; ! 22: s++; ! 23: } ! 24: } ! 25: ! 26: void DrawAltString (int x, int y, char *s) ! 27: { ! 28: while (*s) ! 29: { ! 30: re.DrawChar (x, y, *s ^ 0x80); ! 31: x+=8; ! 32: s++; ! 33: } ! 34: } ! 35: ! 36: ! 37: void Key_ClearTyping (void) ! 38: { ! 39: key_lines[edit_line][1] = 0; // clear any typing ! 40: key_linepos = 1; ! 41: } ! 42: ! 43: /* ! 44: ================ ! 45: Con_ToggleConsole_f ! 46: ================ ! 47: */ ! 48: void Con_ToggleConsole_f (void) ! 49: { ! 50: SCR_EndLoadingPlaque (); // get rid of loading plaque ! 51: ! 52: if (cl.attractloop) ! 53: { ! 54: Cbuf_AddText ("killserver\n"); ! 55: return; ! 56: } ! 57: ! 58: if (cls.state == ca_disconnected) ! 59: { // start the demo loop again ! 60: Cbuf_AddText ("d1\n"); ! 61: return; ! 62: } ! 63: ! 64: Key_ClearTyping (); ! 65: Con_ClearNotify (); ! 66: ! 67: if (cls.key_dest == key_console) ! 68: { ! 69: M_ForceMenuOff (); ! 70: Cvar_Set ("paused", "0"); ! 71: } ! 72: else ! 73: { ! 74: M_ForceMenuOff (); ! 75: cls.key_dest = key_console; ! 76: ! 77: if (Cvar_VariableValue ("maxclients") == 1 ! 78: && Com_ServerState ()) ! 79: Cvar_Set ("paused", "1"); ! 80: } ! 81: } ! 82: ! 83: /* ! 84: ================ ! 85: Con_ToggleChat_f ! 86: ================ ! 87: */ ! 88: void Con_ToggleChat_f (void) ! 89: { ! 90: Key_ClearTyping (); ! 91: ! 92: if (cls.key_dest == key_console) ! 93: { ! 94: if (cls.state == ca_active) ! 95: { ! 96: M_ForceMenuOff (); ! 97: cls.key_dest = key_game; ! 98: } ! 99: } ! 100: else ! 101: cls.key_dest = key_console; ! 102: ! 103: Con_ClearNotify (); ! 104: } ! 105: ! 106: /* ! 107: ================ ! 108: Con_Clear_f ! 109: ================ ! 110: */ ! 111: void Con_Clear_f (void) ! 112: { ! 113: memset (con.text, ' ', CON_TEXTSIZE); ! 114: } ! 115: ! 116: ! 117: /* ! 118: ================ ! 119: Con_Dump_f ! 120: ! 121: Save the console contents out to a file ! 122: ================ ! 123: */ ! 124: void Con_Dump_f (void) ! 125: { ! 126: int l, x; ! 127: char *line; ! 128: FILE *f; ! 129: char buffer[1024]; ! 130: char name[MAX_OSPATH]; ! 131: ! 132: if (Cmd_Argc() != 2) ! 133: { ! 134: Com_Printf ("usage: condump <filename>\n"); ! 135: return; ! 136: } ! 137: ! 138: Com_sprintf (name, sizeof(name), "%s/%s.txt", FS_Gamedir(), Cmd_Argv(1)); ! 139: ! 140: Com_Printf ("Dumped console text to %s.\n", name); ! 141: FS_CreatePath (name); ! 142: f = fopen (name, "w"); ! 143: if (!f) ! 144: { ! 145: Com_Printf ("ERROR: couldn't open.\n"); ! 146: return; ! 147: } ! 148: ! 149: // skip empty lines ! 150: for (l = con.current - con.totallines + 1 ; l <= con.current ; l++) ! 151: { ! 152: line = con.text + (l%con.totallines)*con.linewidth; ! 153: for (x=0 ; x<con.linewidth ; x++) ! 154: if (line[x] != ' ') ! 155: break; ! 156: if (x != con.linewidth) ! 157: break; ! 158: } ! 159: ! 160: // write the remaining lines ! 161: buffer[con.linewidth] = 0; ! 162: for ( ; l <= con.current ; l++) ! 163: { ! 164: line = con.text + (l%con.totallines)*con.linewidth; ! 165: strncpy (buffer, line, con.linewidth); ! 166: for (x=con.linewidth-1 ; x>=0 ; x--) ! 167: { ! 168: if (buffer[x] == ' ') ! 169: buffer[x] = 0; ! 170: else ! 171: break; ! 172: } ! 173: ! 174: fprintf (f, "%s\n", buffer); ! 175: } ! 176: ! 177: fclose (f); ! 178: } ! 179: ! 180: ! 181: /* ! 182: ================ ! 183: Con_ClearNotify ! 184: ================ ! 185: */ ! 186: void Con_ClearNotify (void) ! 187: { ! 188: int i; ! 189: ! 190: for (i=0 ; i<NUM_CON_TIMES ; i++) ! 191: con.times[i] = 0; ! 192: } ! 193: ! 194: ! 195: /* ! 196: ================ ! 197: Con_MessageMode_f ! 198: ================ ! 199: */ ! 200: void Con_MessageMode_f (void) ! 201: { ! 202: chat_team = false; ! 203: cls.key_dest = key_message; ! 204: } ! 205: ! 206: /* ! 207: ================ ! 208: Con_MessageMode2_f ! 209: ================ ! 210: */ ! 211: void Con_MessageMode2_f (void) ! 212: { ! 213: chat_team = true; ! 214: cls.key_dest = key_message; ! 215: } ! 216: ! 217: /* ! 218: ================ ! 219: Con_CheckResize ! 220: ! 221: If the line width has changed, reformat the buffer. ! 222: ================ ! 223: */ ! 224: void Con_CheckResize (void) ! 225: { ! 226: int i, j, width, oldwidth, oldtotallines, numlines, numchars; ! 227: char tbuf[CON_TEXTSIZE]; ! 228: ! 229: width = (viddef.width >> 3) - 2; ! 230: ! 231: if (width == con.linewidth) ! 232: return; ! 233: ! 234: if (width < 1) // video hasn't been initialized yet ! 235: { ! 236: width = 38; ! 237: con.linewidth = width; ! 238: con.totallines = CON_TEXTSIZE / con.linewidth; ! 239: memset (con.text, ' ', CON_TEXTSIZE); ! 240: } ! 241: else ! 242: { ! 243: oldwidth = con.linewidth; ! 244: con.linewidth = width; ! 245: oldtotallines = con.totallines; ! 246: con.totallines = CON_TEXTSIZE / con.linewidth; ! 247: numlines = oldtotallines; ! 248: ! 249: if (con.totallines < numlines) ! 250: numlines = con.totallines; ! 251: ! 252: numchars = oldwidth; ! 253: ! 254: if (con.linewidth < numchars) ! 255: numchars = con.linewidth; ! 256: ! 257: memcpy (tbuf, con.text, CON_TEXTSIZE); ! 258: memset (con.text, ' ', CON_TEXTSIZE); ! 259: ! 260: for (i=0 ; i<numlines ; i++) ! 261: { ! 262: for (j=0 ; j<numchars ; j++) ! 263: { ! 264: con.text[(con.totallines - 1 - i) * con.linewidth + j] = ! 265: tbuf[((con.current - i + oldtotallines) % ! 266: oldtotallines) * oldwidth + j]; ! 267: } ! 268: } ! 269: ! 270: Con_ClearNotify (); ! 271: } ! 272: ! 273: con.current = con.totallines - 1; ! 274: con.display = con.current; ! 275: } ! 276: ! 277: ! 278: /* ! 279: ================ ! 280: Con_Init ! 281: ================ ! 282: */ ! 283: void Con_Init (void) ! 284: { ! 285: con.linewidth = -1; ! 286: ! 287: Con_CheckResize (); ! 288: ! 289: Com_Printf ("Console initialized.\n"); ! 290: ! 291: // ! 292: // register our commands ! 293: // ! 294: con_notifytime = Cvar_Get ("con_notifytime", "3", 0); ! 295: ! 296: Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f); ! 297: Cmd_AddCommand ("togglechat", Con_ToggleChat_f); ! 298: Cmd_AddCommand ("messagemode", Con_MessageMode_f); ! 299: Cmd_AddCommand ("messagemode2", Con_MessageMode2_f); ! 300: Cmd_AddCommand ("clear", Con_Clear_f); ! 301: Cmd_AddCommand ("condump", Con_Dump_f); ! 302: con.initialized = true; ! 303: } ! 304: ! 305: ! 306: /* ! 307: =============== ! 308: Con_Linefeed ! 309: =============== ! 310: */ ! 311: void Con_Linefeed (void) ! 312: { ! 313: con.x = 0; ! 314: if (con.display == con.current) ! 315: con.display++; ! 316: con.current++; ! 317: memset (&con.text[(con.current%con.totallines)*con.linewidth] ! 318: , ' ', con.linewidth); ! 319: } ! 320: ! 321: /* ! 322: ================ ! 323: Con_Print ! 324: ! 325: Handles cursor positioning, line wrapping, etc ! 326: All console printing must go through this in order to be logged to disk ! 327: If no console is visible, the text will appear at the top of the game window ! 328: ================ ! 329: */ ! 330: void Con_Print (char *txt) ! 331: { ! 332: int y; ! 333: int c, l; ! 334: static int cr; ! 335: int mask; ! 336: ! 337: if (!con.initialized) ! 338: return; ! 339: ! 340: if (txt[0] == 1 || txt[0] == 2) ! 341: { ! 342: mask = 128; // go to colored text ! 343: txt++; ! 344: } ! 345: else ! 346: mask = 0; ! 347: ! 348: ! 349: while ( (c = *txt) ) ! 350: { ! 351: // count word length ! 352: for (l=0 ; l< con.linewidth ; l++) ! 353: if ( txt[l] <= ' ') ! 354: break; ! 355: ! 356: // word wrap ! 357: if (l != con.linewidth && (con.x + l > con.linewidth) ) ! 358: con.x = 0; ! 359: ! 360: txt++; ! 361: ! 362: if (cr) ! 363: { ! 364: con.current--; ! 365: cr = false; ! 366: } ! 367: ! 368: ! 369: if (!con.x) ! 370: { ! 371: Con_Linefeed (); ! 372: // mark time for transparent overlay ! 373: if (con.current >= 0) ! 374: con.times[con.current % NUM_CON_TIMES] = cls.realtime; ! 375: } ! 376: ! 377: switch (c) ! 378: { ! 379: case '\n': ! 380: con.x = 0; ! 381: break; ! 382: ! 383: case '\r': ! 384: con.x = 0; ! 385: cr = 1; ! 386: break; ! 387: ! 388: default: // display character and advance ! 389: y = con.current % con.totallines; ! 390: con.text[y*con.linewidth+con.x] = c | mask | con.ormask; ! 391: con.x++; ! 392: if (con.x >= con.linewidth) ! 393: con.x = 0; ! 394: break; ! 395: } ! 396: ! 397: } ! 398: } ! 399: ! 400: ! 401: /* ! 402: ============== ! 403: Con_CenteredPrint ! 404: ============== ! 405: */ ! 406: void Con_CenteredPrint (char *text) ! 407: { ! 408: int l; ! 409: char buffer[1024]; ! 410: ! 411: l = strlen(text); ! 412: l = (con.linewidth-l)/2; ! 413: if (l < 0) ! 414: l = 0; ! 415: memset (buffer, ' ', l); ! 416: strcpy (buffer+l, text); ! 417: strcat (buffer, "\n"); ! 418: Con_Print (buffer); ! 419: } ! 420: ! 421: /* ! 422: ============================================================================== ! 423: ! 424: DRAWING ! 425: ! 426: ============================================================================== ! 427: */ ! 428: ! 429: ! 430: /* ! 431: ================ ! 432: Con_DrawInput ! 433: ! 434: The input line scrolls horizontally if typing goes beyond the right edge ! 435: ================ ! 436: */ ! 437: void Con_DrawInput (void) ! 438: { ! 439: int y; ! 440: int i; ! 441: char *text; ! 442: ! 443: if (cls.key_dest == key_menu) ! 444: return; ! 445: if (cls.key_dest != key_console && cls.state == ca_active) ! 446: return; // don't draw anything (always draw if not active) ! 447: ! 448: text = key_lines[edit_line]; ! 449: ! 450: // add the cursor frame ! 451: text[key_linepos] = 10+((int)(cls.realtime>>8)&1); ! 452: ! 453: // fill out remainder with spaces ! 454: for (i=key_linepos+1 ; i< con.linewidth ; i++) ! 455: text[i] = ' '; ! 456: ! 457: // prestep if horizontally scrolling ! 458: if (key_linepos >= con.linewidth) ! 459: text += 1 + key_linepos - con.linewidth; ! 460: ! 461: // draw it ! 462: y = con.vislines-16; ! 463: ! 464: for (i=0 ; i<con.linewidth ; i++) ! 465: re.DrawChar ( (i+1)<<3, con.vislines - 16, text[i]); ! 466: ! 467: // remove cursor ! 468: key_lines[edit_line][key_linepos] = 0; ! 469: } ! 470: ! 471: ! 472: /* ! 473: ================ ! 474: Con_DrawNotify ! 475: ! 476: Draws the last few lines of output transparently over the game top ! 477: ================ ! 478: */ ! 479: void Con_DrawNotify (void) ! 480: { ! 481: int x, v; ! 482: char *text; ! 483: int i; ! 484: int time; ! 485: char *s; ! 486: int skip; ! 487: ! 488: v = 0; ! 489: for (i= con.current-NUM_CON_TIMES+1 ; i<=con.current ; i++) ! 490: { ! 491: if (i < 0) ! 492: continue; ! 493: time = con.times[i % NUM_CON_TIMES]; ! 494: if (time == 0) ! 495: continue; ! 496: time = cls.realtime - time; ! 497: if (time > con_notifytime->value*1000) ! 498: continue; ! 499: text = con.text + (i % con.totallines)*con.linewidth; ! 500: ! 501: for (x = 0 ; x < con.linewidth ; x++) ! 502: re.DrawChar ( (x+1)<<3, v, text[x]); ! 503: ! 504: v += 8; ! 505: } ! 506: ! 507: ! 508: if (cls.key_dest == key_message) ! 509: { ! 510: if (chat_team) ! 511: { ! 512: DrawString (8, v, "say_team:"); ! 513: skip = 11; ! 514: } ! 515: else ! 516: { ! 517: DrawString (8, v, "say:"); ! 518: skip = 5; ! 519: } ! 520: ! 521: s = chat_buffer; ! 522: if (chat_bufferlen > (viddef.width>>3)-(skip+1)) ! 523: s += chat_bufferlen - ((viddef.width>>3)-(skip+1)); ! 524: x = 0; ! 525: while(s[x]) ! 526: { ! 527: re.DrawChar ( (x+skip)<<3, v, s[x]); ! 528: x++; ! 529: } ! 530: re.DrawChar ( (x+skip)<<3, v, 10+((cls.realtime>>8)&1)); ! 531: v += 8; ! 532: } ! 533: ! 534: if (v) ! 535: { ! 536: SCR_AddDirtyPoint (0,0); ! 537: SCR_AddDirtyPoint (viddef.width-1, v); ! 538: } ! 539: } ! 540: ! 541: /* ! 542: ================ ! 543: Con_DrawConsole ! 544: ! 545: Draws the console with the solid background ! 546: ================ ! 547: */ ! 548: void Con_DrawConsole (float frac) ! 549: { ! 550: int i, x, y; ! 551: int rows; ! 552: char *text; ! 553: int row; ! 554: int lines; ! 555: char version[64]; ! 556: ! 557: lines = viddef.height * frac; ! 558: if (lines <= 0) ! 559: return; ! 560: ! 561: if (lines > viddef.height) ! 562: lines = viddef.height; ! 563: ! 564: // draw the background ! 565: re.DrawStretchPic (0, -viddef.height+lines, viddef.width, viddef.height, "conback"); ! 566: SCR_AddDirtyPoint (0,0); ! 567: SCR_AddDirtyPoint (viddef.width-1,lines-1); ! 568: ! 569: Com_sprintf (version, sizeof(version), "v%4.2f", VERSION); ! 570: for (x=0 ; x<5 ; x++) ! 571: re.DrawChar (viddef.width-44+x*8, lines-12, 128 + version[x] ); ! 572: ! 573: // draw the text ! 574: con.vislines = lines; ! 575: ! 576: rows = (lines-8)>>3; // rows of text to draw ! 577: ! 578: y = lines - 24; ! 579: ! 580: // draw from the bottom up ! 581: if (con.display != con.current) ! 582: { ! 583: // draw arrows to show the buffer is backscrolled ! 584: for (x=0 ; x<con.linewidth ; x+=4) ! 585: re.DrawChar ( (x+1)<<3, y, '^'); ! 586: ! 587: y -= 8; ! 588: rows--; ! 589: } ! 590: ! 591: row = con.display; ! 592: for (i=0 ; i<rows ; i++, y-=8, row--) ! 593: { ! 594: if (row < 0) ! 595: break; ! 596: if (con.current - row >= con.totallines) ! 597: break; // past scrollback wrap point ! 598: ! 599: text = con.text + (row % con.totallines)*con.linewidth; ! 600: ! 601: for (x=0 ; x<con.linewidth ; x++) ! 602: re.DrawChar ( (x+1)<<3, y, text[x]); ! 603: } ! 604: ! 605: // draw the input prompt, user text, and cursor if desired ! 606: Con_DrawInput (); ! 607: } ! 608: ! 609:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.