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) - 2;
162 if (width == con_linewidth)
165 if (width < 1) // video hasn't been initialized yet
167 width = 78; // LordHavoc: changed from 38 to 78 (320 -> 640 conversion)
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]
264 , ' ', con_linewidth);
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.
276 void Con_Print (char *txt)
287 mask = 128; // go to colored text
288 S_LocalSound ("misc/talk.wav");
292 else if (txt[0] == 2)
294 mask = 128; // go to colored text
304 for (l=0 ; l< con_linewidth ; l++)
309 if (l != con_linewidth && (con_x + l > con_linewidth) )
324 // mark time for transparent overlay
325 if (con_current >= 0)
326 con_times[con_current % NUM_CON_TIMES] = realtime;
340 default: // display character and advance
341 y = con_current % con_totallines;
342 con_text[y*con_linewidth+con_x] = c | mask;
344 if (con_x >= con_linewidth)
358 void Con_DebugLog(char *file, char *fmt, ...)
361 static char data[1024];
364 va_start(argptr, fmt);
365 vsprintf(data, fmt, argptr);
367 fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
368 write(fd, data, strlen(data));
377 Handles cursor positioning, line wrapping, etc
380 // LordHavoc: increased from 4096 to 16384
381 #define MAXPRINTMSG 16384
382 // FIXME: make a buffer size safe vsprintf?
383 void Con_Printf (char *fmt, ...)
386 char msg[MAXPRINTMSG];
388 va_start (argptr,fmt);
389 vsprintf (msg,fmt,argptr);
392 // also echo to debugging console
393 Sys_Printf ("%s", msg);
395 // log all messages to file
398 // can't use va() here because it might overwrite other important things
399 char logname[MAX_OSPATH];
400 sprintf(logname, "%s/qconsole.log", com_gamedir);
401 Con_DebugLog(logname, "%s", msg);
404 if (!con_initialized)
407 if (cls.state == ca_dedicated)
408 return; // no graphics mode
410 // write it to the scrollable buffer
418 A Con_Printf that only shows up if the "developer" cvar is set
421 void Con_DPrintf (char *fmt, ...)
424 char msg[MAXPRINTMSG];
426 if (!developer.integer)
427 return; // don't confuse non-developers with techie stuff...
429 va_start (argptr,fmt);
430 vsprintf (msg,fmt,argptr);
433 Con_Printf ("%s", msg);
441 Okay to call even when the screen can't be updated
444 void Con_SafePrintf (char *fmt, ...)
449 va_start (argptr,fmt);
450 vsprintf (msg,fmt,argptr);
453 Con_Printf ("%s", msg);
458 ==============================================================================
462 ==============================================================================
470 The input line scrolls horizontally if typing goes beyond the right edge
472 Modified by EvilTypeGuy eviltypeguy@qeradiant.com
475 void Con_DrawInput (void)
477 char editlinecopy[256], *text;
479 if (key_dest != key_console && !con_forcedup)
480 return; // don't draw anything
482 text = strcpy(editlinecopy, key_lines[edit_line]);
484 // Advanced Console Editing by Radix radix@planetquake.com
485 // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
486 // use strlen of edit_line instead of key_linepos to allow editing
487 // of early characters w/o erasing
489 // add the cursor frame
490 if ((int)(realtime*con_cursorspeed) & 1) // cursor is visible
491 text[key_linepos] = 11 + 130 * key_insert; // either solid or triangle facing right
493 text[key_linepos + 1] = 0;
495 // prestep if horizontally scrolling
496 if (key_linepos >= con_linewidth)
497 text += 1 + key_linepos - con_linewidth;
500 DrawQ_String(8, con_vislines - 16, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
503 key_lines[edit_line][key_linepos] = 0;
511 Draws the last few lines of output transparently over the game top
514 void Con_DrawNotify (void)
520 extern char chat_buffer[];
524 for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
528 time = con_times[i % NUM_CON_TIMES];
531 time = realtime - time;
532 if (time > con_notifytime.value)
534 text = con_text + (i % con_totallines)*con_linewidth;
538 DrawQ_String(8, v, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
544 if (key_dest == key_message)
550 // LordHavoc: speedup, and other improvements
552 sprintf(temptext, "say_team:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
554 sprintf(temptext, "say:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
555 while (strlen(temptext) >= con_linewidth)
557 DrawQ_String (8, v, temptext, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
558 strcpy(temptext, &temptext[con_linewidth]);
561 if (strlen(temptext) > 0)
563 DrawQ_String (8, v, temptext, 0, 8, 8, 1, 1, 1, 1, 0);
568 if (v > con_notifylines)
576 Draws the console with the solid background
577 The typing input line at the bottom should only be drawn if typing is allowed
580 extern cvar_t scr_conalpha;
581 extern char engineversion[40];
582 void Con_DrawConsole (int lines)
592 // draw the background
593 DrawQ_Pic(0, lines - vid.conheight, "gfx/conback", vid.conwidth, vid.conheight, 1, 1, 1, scr_conalpha.value * lines / vid.conheight, 0);
594 DrawQ_String(vid.conwidth - strlen(engineversion) * 8 - 8, lines - 8, engineversion, 0, 8, 8, 1, 0, 0, 1, 0);
597 con_vislines = lines;
599 rows = (lines-16)>>3; // rows of text to draw
600 y = lines - 16 - (rows<<3); // may start slightly negative
602 for (i = con_current - rows + 1;i <= con_current;i++, y += 8)
604 j = max(i - con_backscroll, 0);
605 text = con_text + (j % con_totallines)*con_linewidth;
607 DrawQ_String(8, y, text, con_linewidth, 8, 8, 1, 1, 1, 1, 0);
610 // draw the input prompt, user text, and cursor if desired
617 New function for tab-completion system
619 MEGA Thanks to Taniwha
623 Con_DisplayList(char **list)
629 int width = (con_linewidth - 4);
642 if (pos + maxlen >= width) {
647 Con_Printf("%s", *list);
648 for (i = 0; i < (maxlen - len); i++)
660 Con_CompleteCommandLine
662 New function for tab-completion system
664 Thanks to Fett erich@heintz.com
669 Con_CompleteCommandLine (void)
675 char **list[3] = {0, 0, 0};
677 s = key_lines[edit_line] + 1;
678 // Count number of possible matches
679 c = Cmd_CompleteCountPossible(s);
680 v = Cvar_CompleteCountPossible(s);
681 a = Cmd_CompleteAliasCountPossible(s);
683 if (!(c + v + a)) // No possible matches
686 if (c + v + a == 1) {
688 list[0] = Cmd_CompleteBuildList(s);
690 list[0] = Cvar_CompleteBuildList(s);
692 list[0] = Cmd_CompleteAliasBuildList(s);
694 cmd_len = strlen (cmd);
697 cmd = *(list[0] = Cmd_CompleteBuildList(s));
699 cmd = *(list[1] = Cvar_CompleteBuildList(s));
701 cmd = *(list[2] = Cmd_CompleteAliasBuildList(s));
703 cmd_len = strlen (s);
705 for (i = 0; i < 3; i++) {
706 char ch = cmd[cmd_len];
709 while (*l && (*l)[cmd_len] == ch)
720 for (i = 0; i < con_linewidth - 4; i++)
724 // Print Possible Commands
726 Con_Printf("%i possible command%s\n", c, (c > 1) ? "s: " : ":");
727 Con_DisplayList(list[0]);
731 Con_Printf("%i possible variable%s\n", v, (v > 1) ? "s: " : ":");
732 Con_DisplayList(list[1]);
736 Con_Printf("%i possible aliases%s\n", a, (a > 1) ? "s: " : ":");
737 Con_DisplayList(list[2]);
742 strncpy(key_lines[edit_line] + 1, cmd, cmd_len);
743 key_linepos = cmd_len + 1;
744 if (c + v + a == 1) {
745 key_lines[edit_line][key_linepos] = ' ';
748 key_lines[edit_line][key_linepos] = 0;
750 for (i = 0; i < 3; i++)