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 key_consoleactive = !key_consoleactive;
82 memset (con_times, 0, sizeof(con_times));
90 void Con_Clear_f (void)
93 memset (con_text, ' ', CON_TEXTSIZE);
102 void Con_ClearNotify (void)
106 for (i=0 ; i<NUM_CON_TIMES ; i++)
116 extern qboolean team_message;
118 void Con_MessageMode_f (void)
120 key_dest = key_message;
121 team_message = false;
130 void Con_MessageMode2_f (void)
132 key_dest = key_message;
141 If the line width has changed, reformat the buffer.
144 void Con_CheckResize (void)
146 int i, j, width, oldwidth, oldtotallines, numlines, numchars;
147 char tbuf[CON_TEXTSIZE];
149 width = (vid.conwidth >> 3);
151 if (width == con_linewidth)
154 if (width < 1) // video hasn't been initialized yet
157 con_linewidth = width;
158 con_totallines = CON_TEXTSIZE / con_linewidth;
159 memset (con_text, ' ', CON_TEXTSIZE);
163 oldwidth = con_linewidth;
164 con_linewidth = width;
165 oldtotallines = con_totallines;
166 con_totallines = CON_TEXTSIZE / con_linewidth;
167 numlines = oldtotallines;
169 if (con_totallines < numlines)
170 numlines = con_totallines;
174 if (con_linewidth < numchars)
175 numchars = con_linewidth;
177 memcpy (tbuf, con_text, CON_TEXTSIZE);
178 memset (con_text, ' ', CON_TEXTSIZE);
180 for (i=0 ; i<numlines ; i++)
182 for (j=0 ; j<numchars ; j++)
184 con_text[(con_totallines - 1 - i) * con_linewidth + j] =
185 tbuf[((con_current - i + oldtotallines) %
186 oldtotallines) * oldwidth + j];
194 con_current = con_totallines - 1;
205 #define MAXGAMEDIRLEN 1000
206 char temp[MAXGAMEDIRLEN+1];
207 char *t2 = "/qconsole.log";
209 Cvar_RegisterVariable(&logfile);
210 con_debuglog = COM_CheckParm("-condebug");
214 if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2)))
216 sprintf (temp, "%s%s", com_gamedir, t2);
222 console_mempool = Mem_AllocPool("console");
223 con_text = Mem_Alloc(console_mempool, CON_TEXTSIZE);
224 memset (con_text, ' ', CON_TEXTSIZE);
228 Con_Printf ("Console initialized.\n");
231 // register our commands
233 Cvar_RegisterVariable (&con_notifytime);
235 Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
236 Cmd_AddCommand ("messagemode", Con_MessageMode_f);
237 Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
238 Cmd_AddCommand ("clear", Con_Clear_f);
239 con_initialized = true;
248 void Con_Linefeed (void)
252 memset (&con_text[(con_current%con_totallines)*con_linewidth], ' ', con_linewidth);
259 Handles cursor positioning, line wrapping, etc
260 All console printing must go through this in order to be logged to disk
261 If no console is visible, the notify window will pop up.
264 void Con_Print (char *txt)
275 mask = 128; // go to colored text
276 S_LocalSound ("misc/talk.wav");
280 else if (txt[0] == 2)
282 mask = 128; // go to colored text
292 for (l=0 ; l< con_linewidth ; l++)
297 if (l != con_linewidth && (con_x + l > con_linewidth) )
312 // mark time for transparent overlay
313 if (con_current >= 0)
314 con_times[con_current % NUM_CON_TIMES] = realtime;
328 default: // display character and advance
329 y = con_current % con_totallines;
330 con_text[y*con_linewidth+con_x] = c | mask;
332 if (con_x >= con_linewidth)
346 void Con_DebugLog(char *file, char *fmt, ...)
351 fd = fopen(file, "at");
352 va_start(argptr, fmt);
353 vfprintf (fd, fmt, argptr);
363 Handles cursor positioning, line wrapping, etc
366 // LordHavoc: increased from 4096 to 16384
367 #define MAXPRINTMSG 16384
368 // FIXME: make a buffer size safe vsprintf?
369 void Con_Printf (char *fmt, ...)
372 char msg[MAXPRINTMSG];
374 va_start (argptr,fmt);
375 vsprintf (msg,fmt,argptr);
378 // also echo to debugging console
379 Sys_Printf ("%s", msg);
381 // log all messages to file
384 // can't use va() here because it might overwrite other important things
385 char logname[MAX_OSPATH];
386 sprintf(logname, "%s/qconsole.log", com_gamedir);
387 Con_DebugLog(logname, "%s", msg);
390 if (!con_initialized)
393 if (cls.state == ca_dedicated)
394 return; // no graphics mode
396 // write it to the scrollable buffer
404 A Con_Printf that only shows up if the "developer" cvar is set
407 void Con_DPrintf (char *fmt, ...)
410 char msg[MAXPRINTMSG];
412 if (!developer.integer)
413 return; // don't confuse non-developers with techie stuff...
415 va_start (argptr,fmt);
416 vsprintf (msg,fmt,argptr);
419 Con_Printf ("%s", msg);
427 Okay to call even when the screen can't be updated
430 void Con_SafePrintf (char *fmt, ...)
435 va_start (argptr,fmt);
436 vsprintf (msg,fmt,argptr);
439 Con_Printf ("%s", msg);
444 ==============================================================================
448 ==============================================================================
456 The input line scrolls horizontally if typing goes beyond the right edge
458 Modified by EvilTypeGuy eviltypeguy@qeradiant.com
461 void Con_DrawInput (void)
463 char editlinecopy[256], *text;
465 if (!key_consoleactive)
466 return; // don't draw anything
468 text = strcpy(editlinecopy, key_lines[edit_line]);
470 // Advanced Console Editing by Radix radix@planetquake.com
471 // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
472 // use strlen of edit_line instead of key_linepos to allow editing
473 // of early characters w/o erasing
475 // add the cursor frame
476 if ((int)(realtime*con_cursorspeed) & 1) // cursor is visible
477 text[key_linepos] = 11 + 130 * key_insert; // either solid or triangle facing right
479 text[key_linepos + 1] = 0;
481 // prestep if horizontally scrolling
482 if (key_linepos >= con_linewidth)
483 text += 1 + key_linepos - con_linewidth;
486 DrawQ_String(0, con_vislines - 16, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
489 key_lines[edit_line][key_linepos] = 0;
497 Draws the last few lines of output transparently over the game top
500 void Con_DrawNotify (void)
506 extern char chat_buffer[];
510 for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
514 time = con_times[i % NUM_CON_TIMES];
517 time = realtime - time;
518 if (time > con_notifytime.value)
520 text = con_text + (i % con_totallines)*con_linewidth;
524 DrawQ_String(0, v, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
530 if (key_dest == key_message)
536 // LordHavoc: speedup, and other improvements
538 sprintf(temptext, "say_team:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
540 sprintf(temptext, "say:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
541 while (strlen(temptext) >= con_linewidth)
543 DrawQ_String (0, v, temptext, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
544 strcpy(temptext, &temptext[con_linewidth]);
547 if (strlen(temptext) > 0)
549 DrawQ_String (0, v, temptext, 0, 8, 8, 1, 1, 1, 1, 0);
554 if (v > con_notifylines)
562 Draws the console with the solid background
563 The typing input line at the bottom should only be drawn if typing is allowed
566 extern cvar_t scr_conalpha;
567 extern char engineversion[40];
568 void Con_DrawConsole (int lines)
578 // draw the background
579 DrawQ_Pic(0, lines - vid.conheight, "gfx/conback", vid.conwidth, vid.conheight, 1, 1, 1, scr_conalpha.value * lines / vid.conheight, 0);
580 DrawQ_String(vid.conwidth - strlen(engineversion) * 8 - 8, lines - 8, engineversion, 0, 8, 8, 1, 0, 0, 1, 0);
583 con_vislines = lines;
585 rows = (lines-16)>>3; // rows of text to draw
586 y = lines - 16 - (rows<<3); // may start slightly negative
588 for (i = con_current - rows + 1;i <= con_current;i++, y += 8)
590 j = max(i - con_backscroll, 0);
591 text = con_text + (j % con_totallines)*con_linewidth;
593 DrawQ_String(0, y, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
596 // draw the input prompt, user text, and cursor if desired
603 New function for tab-completion system
605 MEGA Thanks to Taniwha
609 Con_DisplayList(char **list)
615 int width = (con_linewidth - 4);
628 if (pos + maxlen >= width) {
633 Con_Printf("%s", *list);
634 for (i = 0; i < (maxlen - len); i++)
646 Con_CompleteCommandLine
648 New function for tab-completion system
650 Thanks to Fett erich@heintz.com
655 Con_CompleteCommandLine (void)
661 char **list[3] = {0, 0, 0};
663 s = key_lines[edit_line] + 1;
664 // Count number of possible matches
665 c = Cmd_CompleteCountPossible(s);
666 v = Cvar_CompleteCountPossible(s);
667 a = Cmd_CompleteAliasCountPossible(s);
669 if (!(c + v + a)) // No possible matches
672 if (c + v + a == 1) {
674 list[0] = Cmd_CompleteBuildList(s);
676 list[0] = Cvar_CompleteBuildList(s);
678 list[0] = Cmd_CompleteAliasBuildList(s);
680 cmd_len = strlen (cmd);
683 cmd = *(list[0] = Cmd_CompleteBuildList(s));
685 cmd = *(list[1] = Cvar_CompleteBuildList(s));
687 cmd = *(list[2] = Cmd_CompleteAliasBuildList(s));
689 cmd_len = strlen (s);
691 for (i = 0; i < 3; i++) {
692 char ch = cmd[cmd_len];
695 while (*l && (*l)[cmd_len] == ch)
706 for (i = 0; i < con_linewidth - 4; i++)
710 // Print Possible Commands
712 Con_Printf("%i possible command%s\n", c, (c > 1) ? "s: " : ":");
713 Con_DisplayList(list[0]);
717 Con_Printf("%i possible variable%s\n", v, (v > 1) ? "s: " : ":");
718 Con_DisplayList(list[1]);
722 Con_Printf("%i possible aliases%s\n", a, (a > 1) ? "s: " : ":");
723 Con_DisplayList(list[2]);
728 strncpy(key_lines[edit_line] + 1, cmd, cmd_len);
729 key_linepos = cmd_len + 1;
730 if (c + v + a == 1) {
731 key_lines[edit_line][key_linepos] = ' ';
734 key_lines[edit_line][key_linepos] = 0;
736 for (i = 0; i < 3; i++)