2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
38 float con_cursorspeed = 4;
40 #define CON_TEXTSIZE 16384
42 int con_totallines; // total lines in console scrollback
43 int con_backscroll; // lines up from bottom to display
44 int con_current; // where next message will be printed
45 int con_x; // offset in current line for next print
48 cvar_t con_notifytime = {CVAR_SAVE, "con_notifytime","3"}; //seconds
49 cvar_t logfile = {0, "logfile","0"};
51 #define NUM_CON_TIMES 4
52 float con_times[NUM_CON_TIMES]; // realtime time the line was generated
53 // for transparent notify lines
57 qboolean con_debuglog;
59 #define MAXCMDLINE 256
60 extern char key_lines[32][MAXCMDLINE];
62 extern int key_linepos;
63 extern int key_insert;
66 qboolean con_initialized;
68 mempool_t *console_mempool;
70 int con_notifylines; // scan lines to clear for notify lines
72 extern void M_Menu_Main_f (void);
79 void Con_ToggleConsole_f (void)
81 // toggle the 'user wants console' bit
82 key_consoleactive ^= KEY_CONSOLEACTIVE_USER;
83 memset (con_times, 0, sizeof(con_times));
91 void Con_Clear_f (void)
94 memset (con_text, ' ', CON_TEXTSIZE);
103 void Con_ClearNotify (void)
107 for (i=0 ; i<NUM_CON_TIMES ; i++)
117 extern qboolean team_message;
119 void Con_MessageMode_f (void)
121 key_dest = key_message;
122 team_message = false;
131 void Con_MessageMode2_f (void)
133 key_dest = key_message;
142 If the line width has changed, reformat the buffer.
145 void Con_CheckResize (void)
147 int i, j, width, oldwidth, oldtotallines, numlines, numchars;
148 char tbuf[CON_TEXTSIZE];
150 width = (vid.conwidth >> 3);
152 if (width == con_linewidth)
155 if (width < 1) // video hasn't been initialized yet
158 con_linewidth = width;
159 con_totallines = CON_TEXTSIZE / con_linewidth;
160 memset (con_text, ' ', CON_TEXTSIZE);
164 oldwidth = con_linewidth;
165 con_linewidth = width;
166 oldtotallines = con_totallines;
167 con_totallines = CON_TEXTSIZE / con_linewidth;
168 numlines = oldtotallines;
170 if (con_totallines < numlines)
171 numlines = con_totallines;
175 if (con_linewidth < numchars)
176 numchars = con_linewidth;
178 memcpy (tbuf, con_text, CON_TEXTSIZE);
179 memset (con_text, ' ', CON_TEXTSIZE);
181 for (i=0 ; i<numlines ; i++)
183 for (j=0 ; j<numchars ; j++)
185 con_text[(con_totallines - 1 - i) * con_linewidth + j] =
186 tbuf[((con_current - i + oldtotallines) %
187 oldtotallines) * oldwidth + j];
195 con_current = con_totallines - 1;
206 #define MAXGAMEDIRLEN 1000
207 char temp[MAXGAMEDIRLEN+1];
208 char *t2 = "/qconsole.log";
210 Cvar_RegisterVariable(&logfile);
211 con_debuglog = COM_CheckParm("-condebug");
215 if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2)))
217 sprintf (temp, "%s%s", com_gamedir, t2);
223 console_mempool = Mem_AllocPool("console");
224 con_text = Mem_Alloc(console_mempool, CON_TEXTSIZE);
225 memset (con_text, ' ', CON_TEXTSIZE);
229 Con_Printf ("Console initialized.\n");
232 // register our commands
234 Cvar_RegisterVariable (&con_notifytime);
236 Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
237 Cmd_AddCommand ("messagemode", Con_MessageMode_f);
238 Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
239 Cmd_AddCommand ("clear", Con_Clear_f);
240 con_initialized = true;
249 void Con_Linefeed (void)
253 memset (&con_text[(con_current%con_totallines)*con_linewidth], ' ', con_linewidth);
260 Handles cursor positioning, line wrapping, etc
261 All console printing must go through this in order to be logged to disk
262 If no console is visible, the notify window will pop up.
265 void Con_Print (char *txt)
276 mask = 128; // go to colored text
277 S_LocalSound ("misc/talk.wav");
281 else if (txt[0] == 2)
283 mask = 128; // go to colored text
293 for (l=0 ; l< con_linewidth ; l++)
298 if (l != con_linewidth && (con_x + l > con_linewidth) )
313 // mark time for transparent overlay
314 if (con_current >= 0)
315 con_times[con_current % NUM_CON_TIMES] = realtime;
329 default: // display character and advance
330 y = con_current % con_totallines;
331 con_text[y*con_linewidth+con_x] = c | mask;
333 if (con_x >= con_linewidth)
347 void Con_DebugLog(char *file, char *fmt, ...)
352 fd = fopen(file, "at");
353 va_start(argptr, fmt);
354 vfprintf (fd, fmt, argptr);
364 Handles cursor positioning, line wrapping, etc
367 // LordHavoc: increased from 4096 to 16384
368 #define MAXPRINTMSG 16384
369 // FIXME: make a buffer size safe vsprintf?
370 void Con_Printf (char *fmt, ...)
373 char msg[MAXPRINTMSG];
375 va_start (argptr,fmt);
376 vsprintf (msg,fmt,argptr);
379 // also echo to debugging console
380 Sys_Printf ("%s", msg);
382 // log all messages to file
385 // can't use va() here because it might overwrite other important things
386 char logname[MAX_OSPATH];
387 sprintf(logname, "%s/qconsole.log", com_gamedir);
388 Con_DebugLog(logname, "%s", msg);
391 if (!con_initialized)
394 if (cls.state == ca_dedicated)
395 return; // no graphics mode
397 // write it to the scrollable buffer
405 A Con_Printf that only shows up if the "developer" cvar is set
408 void Con_DPrintf (char *fmt, ...)
411 char msg[MAXPRINTMSG];
413 if (!developer.integer)
414 return; // don't confuse non-developers with techie stuff...
416 va_start (argptr,fmt);
417 vsprintf (msg,fmt,argptr);
420 Con_Printf ("%s", msg);
428 Okay to call even when the screen can't be updated
431 void Con_SafePrintf (char *fmt, ...)
436 va_start (argptr,fmt);
437 vsprintf (msg,fmt,argptr);
440 Con_Printf ("%s", msg);
445 ==============================================================================
449 ==============================================================================
457 The input line scrolls horizontally if typing goes beyond the right edge
459 Modified by EvilTypeGuy eviltypeguy@qeradiant.com
462 void Con_DrawInput (void)
464 char editlinecopy[256], *text;
466 if (!key_consoleactive)
467 return; // don't draw anything
469 text = strcpy(editlinecopy, key_lines[edit_line]);
471 // Advanced Console Editing by Radix radix@planetquake.com
472 // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
473 // use strlen of edit_line instead of key_linepos to allow editing
474 // of early characters w/o erasing
476 // add the cursor frame
477 if ((int)(realtime*con_cursorspeed) & 1) // cursor is visible
478 text[key_linepos] = 11 + 130 * key_insert; // either solid or triangle facing right
480 text[key_linepos + 1] = 0;
482 // prestep if horizontally scrolling
483 if (key_linepos >= con_linewidth)
484 text += 1 + key_linepos - con_linewidth;
487 DrawQ_String(0, con_vislines - 16, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
490 key_lines[edit_line][key_linepos] = 0;
498 Draws the last few lines of output transparently over the game top
501 void Con_DrawNotify (void)
507 extern char chat_buffer[];
511 for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
515 time = con_times[i % NUM_CON_TIMES];
518 time = realtime - time;
519 if (time > con_notifytime.value)
521 text = con_text + (i % con_totallines)*con_linewidth;
525 DrawQ_String(0, v, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
531 if (key_dest == key_message)
537 // LordHavoc: speedup, and other improvements
539 sprintf(temptext, "say_team:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
541 sprintf(temptext, "say:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
542 while (strlen(temptext) >= con_linewidth)
544 DrawQ_String (0, v, temptext, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
545 strcpy(temptext, &temptext[con_linewidth]);
548 if (strlen(temptext) > 0)
550 DrawQ_String (0, v, temptext, 0, 8, 8, 1, 1, 1, 1, 0);
555 if (v > con_notifylines)
563 Draws the console with the solid background
564 The typing input line at the bottom should only be drawn if typing is allowed
567 extern cvar_t scr_conalpha;
568 extern char engineversion[40];
569 void Con_DrawConsole (int lines)
579 // draw the background
580 DrawQ_Pic(0, lines - vid.conheight, "gfx/conback", vid.conwidth, vid.conheight, 1, 1, 1, scr_conalpha.value * lines / vid.conheight, 0);
581 DrawQ_String(vid.conwidth - strlen(engineversion) * 8 - 8, lines - 8, engineversion, 0, 8, 8, 1, 0, 0, 1, 0);
584 con_vislines = lines;
586 rows = (lines-16)>>3; // rows of text to draw
587 y = lines - 16 - (rows<<3); // may start slightly negative
589 for (i = con_current - rows + 1;i <= con_current;i++, y += 8)
591 j = max(i - con_backscroll, 0);
592 text = con_text + (j % con_totallines)*con_linewidth;
594 DrawQ_String(0, y, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
597 // draw the input prompt, user text, and cursor if desired
604 New function for tab-completion system
606 MEGA Thanks to Taniwha
610 Con_DisplayList(char **list)
616 int width = (con_linewidth - 4);
629 if (pos + maxlen >= width) {
634 Con_Printf("%s", *list);
635 for (i = 0; i < (maxlen - len); i++)
647 Con_CompleteCommandLine
649 New function for tab-completion system
651 Thanks to Fett erich@heintz.com
656 Con_CompleteCommandLine (void)
662 char **list[3] = {0, 0, 0};
664 s = key_lines[edit_line] + 1;
665 // Count number of possible matches
666 c = Cmd_CompleteCountPossible(s);
667 v = Cvar_CompleteCountPossible(s);
668 a = Cmd_CompleteAliasCountPossible(s);
670 if (!(c + v + a)) // No possible matches
673 if (c + v + a == 1) {
675 list[0] = Cmd_CompleteBuildList(s);
677 list[0] = Cvar_CompleteBuildList(s);
679 list[0] = Cmd_CompleteAliasBuildList(s);
681 cmd_len = strlen (cmd);
684 cmd = *(list[0] = Cmd_CompleteBuildList(s));
686 cmd = *(list[1] = Cvar_CompleteBuildList(s));
688 cmd = *(list[2] = Cmd_CompleteAliasBuildList(s));
690 cmd_len = strlen (s);
692 for (i = 0; i < 3; i++) {
693 char ch = cmd[cmd_len];
696 while (*l && (*l)[cmd_len] == ch)
707 for (i = 0; i < con_linewidth - 4; i++)
711 // Print Possible Commands
713 Con_Printf("%i possible command%s\n", c, (c > 1) ? "s: " : ":");
714 Con_DisplayList(list[0]);
718 Con_Printf("%i possible variable%s\n", v, (v > 1) ? "s: " : ":");
719 Con_DisplayList(list[1]);
723 Con_Printf("%i possible aliases%s\n", a, (a > 1) ? "s: " : ":");
724 Con_DisplayList(list[2]);
729 strncpy(key_lines[edit_line] + 1, cmd, cmd_len);
730 key_linepos = cmd_len + 1;
731 if (c + v + a == 1) {
732 key_lines[edit_line][key_linepos] = ' ';
735 key_lines[edit_line][key_linepos] = 0;
737 for (i = 0; i < 3; i++)