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 qboolean con_forcedup; // because no entities to refresh
44 int con_totallines; // total lines in console scrollback
45 int con_backscroll; // lines up from bottom to display
46 int con_current; // where next message will be printed
47 int con_x; // offset in current line for next print
50 cvar_t con_notifytime = {CVAR_SAVE, "con_notifytime","3"}; //seconds
51 cvar_t logfile = {0, "logfile","0"};
53 #define NUM_CON_TIMES 4
54 float con_times[NUM_CON_TIMES]; // realtime time the line was generated
55 // for transparent notify lines
59 qboolean con_debuglog;
61 #define MAXCMDLINE 256
62 extern char key_lines[32][MAXCMDLINE];
64 extern int key_linepos;
65 extern int key_insert;
68 qboolean con_initialized;
70 mempool_t *console_mempool;
72 int con_notifylines; // scan lines to clear for notify lines
74 extern void M_Menu_Main_f (void);
81 void Con_ToggleConsole_f (void)
83 if (key_dest == key_console)
85 if (cls.state == ca_connected)
91 key_dest = key_console;
93 memset (con_times, 0, sizeof(con_times));
101 void Con_Clear_f (void)
104 memset (con_text, ' ', CON_TEXTSIZE);
113 void Con_ClearNotify (void)
117 for (i=0 ; i<NUM_CON_TIMES ; i++)
127 extern qboolean team_message;
129 void Con_MessageMode_f (void)
131 key_dest = key_message;
132 team_message = false;
141 void Con_MessageMode2_f (void)
143 key_dest = key_message;
152 If the line width has changed, reformat the buffer.
155 void Con_CheckResize (void)
157 int i, j, width, oldwidth, oldtotallines, numlines, numchars;
158 char tbuf[CON_TEXTSIZE];
160 width = (vid.conwidth >> 3);
162 if (width == con_linewidth)
165 if (width < 1) // video hasn't been initialized yet
168 con_linewidth = width;
169 con_totallines = CON_TEXTSIZE / con_linewidth;
170 memset (con_text, ' ', CON_TEXTSIZE);
174 oldwidth = con_linewidth;
175 con_linewidth = width;
176 oldtotallines = con_totallines;
177 con_totallines = CON_TEXTSIZE / con_linewidth;
178 numlines = oldtotallines;
180 if (con_totallines < numlines)
181 numlines = con_totallines;
185 if (con_linewidth < numchars)
186 numchars = con_linewidth;
188 memcpy (tbuf, con_text, CON_TEXTSIZE);
189 memset (con_text, ' ', CON_TEXTSIZE);
191 for (i=0 ; i<numlines ; i++)
193 for (j=0 ; j<numchars ; j++)
195 con_text[(con_totallines - 1 - i) * con_linewidth + j] =
196 tbuf[((con_current - i + oldtotallines) %
197 oldtotallines) * oldwidth + j];
205 con_current = con_totallines - 1;
216 #define MAXGAMEDIRLEN 1000
217 char temp[MAXGAMEDIRLEN+1];
218 char *t2 = "/qconsole.log";
220 Cvar_RegisterVariable(&logfile);
221 con_debuglog = COM_CheckParm("-condebug");
225 if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2)))
227 sprintf (temp, "%s%s", com_gamedir, t2);
233 console_mempool = Mem_AllocPool("console");
234 con_text = Mem_Alloc(console_mempool, CON_TEXTSIZE);
235 memset (con_text, ' ', CON_TEXTSIZE);
239 Con_Printf ("Console initialized.\n");
242 // register our commands
244 Cvar_RegisterVariable (&con_notifytime);
246 Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
247 Cmd_AddCommand ("messagemode", Con_MessageMode_f);
248 Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
249 Cmd_AddCommand ("clear", Con_Clear_f);
250 con_initialized = true;
259 void Con_Linefeed (void)
263 memset (&con_text[(con_current%con_totallines)*con_linewidth], ' ', con_linewidth);
270 Handles cursor positioning, line wrapping, etc
271 All console printing must go through this in order to be logged to disk
272 If no console is visible, the notify window will pop up.
275 void Con_Print (char *txt)
286 mask = 128; // go to colored text
287 S_LocalSound ("misc/talk.wav");
291 else if (txt[0] == 2)
293 mask = 128; // go to colored text
303 for (l=0 ; l< con_linewidth ; l++)
308 if (l != con_linewidth && (con_x + l > con_linewidth) )
323 // mark time for transparent overlay
324 if (con_current >= 0)
325 con_times[con_current % NUM_CON_TIMES] = realtime;
339 default: // display character and advance
340 y = con_current % con_totallines;
341 con_text[y*con_linewidth+con_x] = c | mask;
343 if (con_x >= con_linewidth)
357 void Con_DebugLog(char *file, char *fmt, ...)
362 fd = fopen(file, "at");
363 va_start(argptr, fmt);
364 vfprintf (fd, fmt, argptr);
374 Handles cursor positioning, line wrapping, etc
377 // LordHavoc: increased from 4096 to 16384
378 #define MAXPRINTMSG 16384
379 // FIXME: make a buffer size safe vsprintf?
380 void Con_Printf (char *fmt, ...)
383 char msg[MAXPRINTMSG];
385 va_start (argptr,fmt);
386 vsprintf (msg,fmt,argptr);
389 // also echo to debugging console
390 Sys_Printf ("%s", msg);
392 // log all messages to file
395 // can't use va() here because it might overwrite other important things
396 char logname[MAX_OSPATH];
397 sprintf(logname, "%s/qconsole.log", com_gamedir);
398 Con_DebugLog(logname, "%s", msg);
401 if (!con_initialized)
404 if (cls.state == ca_dedicated)
405 return; // no graphics mode
407 // write it to the scrollable buffer
415 A Con_Printf that only shows up if the "developer" cvar is set
418 void Con_DPrintf (char *fmt, ...)
421 char msg[MAXPRINTMSG];
423 if (!developer.integer)
424 return; // don't confuse non-developers with techie stuff...
426 va_start (argptr,fmt);
427 vsprintf (msg,fmt,argptr);
430 Con_Printf ("%s", msg);
438 Okay to call even when the screen can't be updated
441 void Con_SafePrintf (char *fmt, ...)
446 va_start (argptr,fmt);
447 vsprintf (msg,fmt,argptr);
450 Con_Printf ("%s", msg);
455 ==============================================================================
459 ==============================================================================
467 The input line scrolls horizontally if typing goes beyond the right edge
469 Modified by EvilTypeGuy eviltypeguy@qeradiant.com
472 void Con_DrawInput (void)
474 char editlinecopy[256], *text;
476 if (key_dest != key_console && !con_forcedup)
477 return; // don't draw anything
479 text = strcpy(editlinecopy, key_lines[edit_line]);
481 // Advanced Console Editing by Radix radix@planetquake.com
482 // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
483 // use strlen of edit_line instead of key_linepos to allow editing
484 // of early characters w/o erasing
486 // add the cursor frame
487 if ((int)(realtime*con_cursorspeed) & 1) // cursor is visible
488 text[key_linepos] = 11 + 130 * key_insert; // either solid or triangle facing right
490 text[key_linepos + 1] = 0;
492 // prestep if horizontally scrolling
493 if (key_linepos >= con_linewidth)
494 text += 1 + key_linepos - con_linewidth;
497 DrawQ_String(0, con_vislines - 16, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
500 key_lines[edit_line][key_linepos] = 0;
508 Draws the last few lines of output transparently over the game top
511 void Con_DrawNotify (void)
517 extern char chat_buffer[];
521 for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
525 time = con_times[i % NUM_CON_TIMES];
528 time = realtime - time;
529 if (time > con_notifytime.value)
531 text = con_text + (i % con_totallines)*con_linewidth;
535 DrawQ_String(0, v, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
541 if (key_dest == key_message)
547 // LordHavoc: speedup, and other improvements
549 sprintf(temptext, "say_team:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
551 sprintf(temptext, "say:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
552 while (strlen(temptext) >= con_linewidth)
554 DrawQ_String (0, v, temptext, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
555 strcpy(temptext, &temptext[con_linewidth]);
558 if (strlen(temptext) > 0)
560 DrawQ_String (0, v, temptext, 0, 8, 8, 1, 1, 1, 1, 0);
565 if (v > con_notifylines)
573 Draws the console with the solid background
574 The typing input line at the bottom should only be drawn if typing is allowed
577 extern cvar_t scr_conalpha;
578 extern char engineversion[40];
579 void Con_DrawConsole (int lines)
589 // draw the background
590 DrawQ_Pic(0, lines - vid.conheight, "gfx/conback", vid.conwidth, vid.conheight, 1, 1, 1, scr_conalpha.value * lines / vid.conheight, 0);
591 DrawQ_String(vid.conwidth - strlen(engineversion) * 8 - 8, lines - 8, engineversion, 0, 8, 8, 1, 0, 0, 1, 0);
594 con_vislines = lines;
596 rows = (lines-16)>>3; // rows of text to draw
597 y = lines - 16 - (rows<<3); // may start slightly negative
599 for (i = con_current - rows + 1;i <= con_current;i++, y += 8)
601 j = max(i - con_backscroll, 0);
602 text = con_text + (j % con_totallines)*con_linewidth;
604 DrawQ_String(0, y, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
607 // draw the input prompt, user text, and cursor if desired
614 New function for tab-completion system
616 MEGA Thanks to Taniwha
620 Con_DisplayList(char **list)
626 int width = (con_linewidth - 4);
639 if (pos + maxlen >= width) {
644 Con_Printf("%s", *list);
645 for (i = 0; i < (maxlen - len); i++)
657 Con_CompleteCommandLine
659 New function for tab-completion system
661 Thanks to Fett erich@heintz.com
666 Con_CompleteCommandLine (void)
672 char **list[3] = {0, 0, 0};
674 s = key_lines[edit_line] + 1;
675 // Count number of possible matches
676 c = Cmd_CompleteCountPossible(s);
677 v = Cvar_CompleteCountPossible(s);
678 a = Cmd_CompleteAliasCountPossible(s);
680 if (!(c + v + a)) // No possible matches
683 if (c + v + a == 1) {
685 list[0] = Cmd_CompleteBuildList(s);
687 list[0] = Cvar_CompleteBuildList(s);
689 list[0] = Cmd_CompleteAliasBuildList(s);
691 cmd_len = strlen (cmd);
694 cmd = *(list[0] = Cmd_CompleteBuildList(s));
696 cmd = *(list[1] = Cvar_CompleteBuildList(s));
698 cmd = *(list[2] = Cmd_CompleteAliasBuildList(s));
700 cmd_len = strlen (s);
702 for (i = 0; i < 3; i++) {
703 char ch = cmd[cmd_len];
706 while (*l && (*l)[cmd_len] == ch)
717 for (i = 0; i < con_linewidth - 4; i++)
721 // Print Possible Commands
723 Con_Printf("%i possible command%s\n", c, (c > 1) ? "s: " : ":");
724 Con_DisplayList(list[0]);
728 Con_Printf("%i possible variable%s\n", v, (v > 1) ? "s: " : ":");
729 Con_DisplayList(list[1]);
733 Con_Printf("%i possible aliases%s\n", a, (a > 1) ? "s: " : ":");
734 Con_DisplayList(list[2]);
739 strncpy(key_lines[edit_line] + 1, cmd, cmd_len);
740 key_linepos = cmd_len + 1;
741 if (c + v + a == 1) {
742 key_lines[edit_line][key_linepos] = ' ';
745 key_lines[edit_line][key_linepos] = 0;
747 for (i = 0; i < 3; i++)