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 = {"con_notifytime","3"}; //seconds
51 cvar_t logfile = {"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 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 if (key_dest == key_console)
83 if (cls.state == ca_connected)
86 // key_lines[edit_line][1] = 0; // clear any typing
93 key_dest = key_console;
95 // SCR_EndLoadingPlaque ();
96 memset (con_times, 0, sizeof(con_times));
104 void Con_Clear_f (void)
107 memset (con_text, ' ', CON_TEXTSIZE);
116 void Con_ClearNotify (void)
120 for (i=0 ; i<NUM_CON_TIMES ; i++)
130 extern qboolean team_message;
132 void Con_MessageMode_f (void)
134 key_dest = key_message;
135 team_message = false;
144 void Con_MessageMode2_f (void)
146 key_dest = key_message;
155 If the line width has changed, reformat the buffer.
158 void Con_CheckResize (void)
160 int i, j, width, oldwidth, oldtotallines, numlines, numchars;
161 char tbuf[CON_TEXTSIZE];
163 width = (vid.width >> 3) - 2;
165 if (width == con_linewidth)
168 if (width < 1) // video hasn't been initialized yet
170 width = 78; // LordHavoc: changed from 38 to 78 (320 -> 640 conversion)
171 con_linewidth = width;
172 con_totallines = CON_TEXTSIZE / con_linewidth;
173 memset (con_text, ' ', CON_TEXTSIZE);
177 oldwidth = con_linewidth;
178 con_linewidth = width;
179 oldtotallines = con_totallines;
180 con_totallines = CON_TEXTSIZE / con_linewidth;
181 numlines = oldtotallines;
183 if (con_totallines < numlines)
184 numlines = con_totallines;
188 if (con_linewidth < numchars)
189 numchars = con_linewidth;
191 memcpy (tbuf, con_text, CON_TEXTSIZE);
192 memset (con_text, ' ', CON_TEXTSIZE);
194 for (i=0 ; i<numlines ; i++)
196 for (j=0 ; j<numchars ; j++)
198 con_text[(con_totallines - 1 - i) * con_linewidth + j] =
199 tbuf[((con_current - i + oldtotallines) %
200 oldtotallines) * oldwidth + j];
208 con_current = con_totallines - 1;
219 #define MAXGAMEDIRLEN 1000
220 char temp[MAXGAMEDIRLEN+1];
221 char *t2 = "/qconsole.log";
223 Cvar_RegisterVariable(&logfile);
224 con_debuglog = COM_CheckParm("-condebug");
228 if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2)))
230 sprintf (temp, "%s%s", com_gamedir, t2);
236 con_text = Hunk_AllocName (CON_TEXTSIZE, "context");
237 memset (con_text, ' ', CON_TEXTSIZE);
241 Con_Printf ("Console initialized.\n");
244 // register our commands
246 Cvar_RegisterVariable (&con_notifytime);
248 Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
249 Cmd_AddCommand ("messagemode", Con_MessageMode_f);
250 Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
251 Cmd_AddCommand ("clear", Con_Clear_f);
252 con_initialized = true;
261 void Con_Linefeed (void)
265 memset (&con_text[(con_current%con_totallines)*con_linewidth]
266 , ' ', con_linewidth);
273 Handles cursor positioning, line wrapping, etc
274 All console printing must go through this in order to be logged to disk
275 If no console is visible, the notify window will pop up.
278 void Con_Print (char *txt)
289 mask = 128; // go to colored text
290 S_LocalSound ("misc/talk.wav");
294 else if (txt[0] == 2)
296 mask = 128; // go to colored text
306 for (l=0 ; l< con_linewidth ; l++)
311 if (l != con_linewidth && (con_x + l > con_linewidth) )
326 // mark time for transparent overlay
327 if (con_current >= 0)
328 con_times[con_current % NUM_CON_TIMES] = realtime;
342 default: // display character and advance
343 y = con_current % con_totallines;
344 con_text[y*con_linewidth+con_x] = c | mask;
346 if (con_x >= con_linewidth)
360 void Con_DebugLog(char *file, char *fmt, ...)
363 static char data[1024];
366 va_start(argptr, fmt);
367 vsprintf(data, fmt, argptr);
369 fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
370 write(fd, data, strlen(data));
379 Handles cursor positioning, line wrapping, etc
382 // LordHavoc: increased from 4096 to 16384
383 #define MAXPRINTMSG 16384
384 // FIXME: make a buffer size safe vsprintf?
385 void Con_Printf (char *fmt, ...)
388 char msg[MAXPRINTMSG];
389 // static qboolean inupdate;
391 va_start (argptr,fmt);
392 vsprintf (msg,fmt,argptr);
395 // also echo to debugging console
396 Sys_Printf ("%s", msg); // also echo to debugging console
398 // log all messages to file
400 Con_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg);
402 if (!con_initialized)
405 if (cls.state == ca_dedicated)
406 return; // no graphics mode
408 // write it to the scrollable buffer
411 // update the screen if the console is displayed
412 // LordHavoc: I don't think there's a real need for this
414 // LordHavoc: don't print text while loading scripts
415 if (cls.state != ca_disconnected)
416 if (cls.signon != SIGNONS && !scr_disabled_for_loading )
418 // protect against infinite loop if something in SCR_UpdateScreen calls
434 A Con_Printf that only shows up if the "developer" cvar is set
437 void Con_DPrintf (char *fmt, ...)
440 char msg[MAXPRINTMSG];
442 if (!developer.value)
443 return; // don't confuse non-developers with techie stuff...
445 va_start (argptr,fmt);
446 vsprintf (msg,fmt,argptr);
449 Con_Printf ("%s", msg);
457 Okay to call even when the screen can't be updated
460 void Con_SafePrintf (char *fmt, ...)
466 va_start (argptr,fmt);
467 vsprintf (msg,fmt,argptr);
470 temp = scr_disabled_for_loading;
471 scr_disabled_for_loading = true;
472 Con_Printf ("%s", msg);
473 scr_disabled_for_loading = temp;
478 ==============================================================================
482 ==============================================================================
490 The input line scrolls horizontally if typing goes beyond the right edge
492 Modified by EvilTypeGuy eviltypeguy@qeradiant.com
495 void Con_DrawInput (void)
499 char editlinecopy[256];
501 if (key_dest != key_console && !con_forcedup)
502 return; // don't draw anything
504 text = strcpy(editlinecopy, key_lines[edit_line]);
507 // Advanced Console Editing by Radix radix@planetquake.com
508 // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
509 // use strlen of edit_line instead of key_linepos to allow editing
510 // of early characters w/o erasing
512 // add the cursor frame
513 if ((int)(realtime*con_cursorspeed) & 1) // cursor is visible
514 text[key_linepos] = 11 + 130 * key_insert; // either solid or triangle facing right
516 text[key_linepos + 1] = 0; // LordHavoc: null terminate, rather than padding with spaces
517 // text[key_linepos] = 10 + ((int)(realtime*con_cursorspeed) & 1);
520 // fill out remainder with spaces
521 // for (i=key_linepos+1 ; i< con_linewidth ; i++)
524 // prestep if horizontally scrolling
525 if (key_linepos >= con_linewidth)
526 text += 1 + key_linepos - con_linewidth;
529 y = con_vislines - 16;
531 // for (i=0 ; i<con_linewidth ; i++)
532 // Draw_Character ( (i+1)<<3, con_vislines - 16, text[i]);
534 // LordHavoc: speedup
535 Draw_String(8, con_vislines - 16, text, con_linewidth);
538 key_lines[edit_line][key_linepos] = 0;
546 Draws the last few lines of output transparently over the game top
549 void Con_DrawNotify (void)
555 extern char chat_buffer[];
559 for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
563 time = con_times[i % NUM_CON_TIMES];
566 time = realtime - time;
567 if (time > con_notifytime.value)
569 text = con_text + (i % con_totallines)*con_linewidth;
573 // for (x = 0 ; x < con_linewidth ; x++)
574 // Draw_Character ( (x+1)<<3, v, text[x]);
575 // LordHavoc: speedup
576 Draw_String(8, v, text, con_linewidth);
582 if (key_dest == key_message)
588 // LordHavoc: speedup, and other improvements
590 sprintf(temptext, "say_team:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
592 sprintf(temptext, "say:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
593 while (strlen(temptext) >= con_linewidth)
595 Draw_String (8, v, temptext, con_linewidth);
596 strcpy(temptext, &temptext[con_linewidth]);
599 if (strlen(temptext) > 0)
601 Draw_String (8, v, temptext, 0);
604 // Draw_String (8, v, "say:", 0);
605 // while(chat_buffer[x])
607 // Draw_Character ( (x+5)<<3, v, chat_buffer[x]);
610 // Draw_Character ( (x+5)<<3, v, 10+((int)(realtime*con_cursorspeed)&1));
614 if (v > con_notifylines)
622 Draws the console with the solid background
623 The typing input line at the bottom should only be drawn if typing is allowed
626 void Con_DrawConsole (int lines, qboolean drawinput)
636 // draw the background
637 Draw_ConsoleBackground (lines);
640 con_vislines = lines;
642 rows = (lines-16)>>3; // rows of text to draw
643 y = lines - 16 - (rows<<3); // may start slightly negative
645 for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8 )
647 j = i - con_backscroll;
650 text = con_text + (j % con_totallines)*con_linewidth;
652 // for (x=0 ; x<con_linewidth ; x++)
653 // Draw_Character ( (x+1)<<3, y, text[x]);
654 // LordHavoc: speedup
655 Draw_String(8, y, text, con_linewidth);
658 // draw the input prompt, user text, and cursor if desired
666 New function for tab-completion system
668 MEGA Thanks to Taniwha
672 Con_DisplayList(char **list)
678 int width = (con_linewidth - 4);
691 if (pos + maxlen >= width) {
696 Con_Printf("%s", *list);
697 for (i = 0; i < (maxlen - len); i++)
709 Con_CompleteCommandLine
711 New function for tab-completion system
713 Thanks to Fett erich@heintz.com
718 Con_CompleteCommandLine (void)
724 char **list[3] = {0, 0, 0};
726 s = key_lines[edit_line] + 1;
727 // Count number of possible matches
728 c = Cmd_CompleteCountPossible(s);
729 v = Cvar_CompleteCountPossible(s);
730 a = Cmd_CompleteAliasCountPossible(s);
732 if (!(c + v + a)) // No possible matches
735 if (c + v + a == 1) {
737 list[0] = Cmd_CompleteBuildList(s);
739 list[0] = Cvar_CompleteBuildList(s);
741 list[0] = Cmd_CompleteAliasBuildList(s);
743 cmd_len = strlen (cmd);
746 cmd = *(list[0] = Cmd_CompleteBuildList(s));
748 cmd = *(list[1] = Cvar_CompleteBuildList(s));
750 cmd = *(list[2] = Cmd_CompleteAliasBuildList(s));
752 cmd_len = strlen (s);
754 for (i = 0; i < 3; i++) {
755 char ch = cmd[cmd_len];
758 while (*l && (*l)[cmd_len] == ch)
769 for (i = 0; i < con_linewidth - 4; i++)
773 // Print Possible Commands
775 Con_Printf("%i possible command%s\n", c, (c > 1) ? "s: " : ":");
776 Con_DisplayList(list[0]);
780 Con_Printf("%i possible variable%s\n", v, (v > 1) ? "s: " : ":");
781 Con_DisplayList(list[1]);
785 Con_Printf("%i possible aliases%s\n", a, (a > 1) ? "s: " : ":");
786 Con_DisplayList(list[2]);
792 strncpy(key_lines[edit_line] + 1, cmd, cmd_len);
793 key_linepos = cmd_len + 1;
794 if (c + v + a == 1) {
795 key_lines[edit_line][key_linepos] = ' ';
798 key_lines[edit_line][key_linepos] = 0;
800 for (i = 0; i < 3; i++)