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)
88 // key_lines[edit_line][1] = 0; // clear any typing
95 key_dest = key_console;
97 // SCR_EndLoadingPlaque ();
98 memset (con_times, 0, sizeof(con_times));
106 void Con_Clear_f (void)
109 memset (con_text, ' ', CON_TEXTSIZE);
118 void Con_ClearNotify (void)
122 for (i=0 ; i<NUM_CON_TIMES ; i++)
132 extern qboolean team_message;
134 void Con_MessageMode_f (void)
136 key_dest = key_message;
137 team_message = false;
146 void Con_MessageMode2_f (void)
148 key_dest = key_message;
157 If the line width has changed, reformat the buffer.
160 void Con_CheckResize (void)
162 int i, j, width, oldwidth, oldtotallines, numlines, numchars;
163 char tbuf[CON_TEXTSIZE];
165 width = (vid.conwidth >> 3) - 2;
167 if (width == con_linewidth)
170 if (width < 1) // video hasn't been initialized yet
172 width = 78; // LordHavoc: changed from 38 to 78 (320 -> 640 conversion)
173 con_linewidth = width;
174 con_totallines = CON_TEXTSIZE / con_linewidth;
175 memset (con_text, ' ', CON_TEXTSIZE);
179 oldwidth = con_linewidth;
180 con_linewidth = width;
181 oldtotallines = con_totallines;
182 con_totallines = CON_TEXTSIZE / con_linewidth;
183 numlines = oldtotallines;
185 if (con_totallines < numlines)
186 numlines = con_totallines;
190 if (con_linewidth < numchars)
191 numchars = con_linewidth;
193 memcpy (tbuf, con_text, CON_TEXTSIZE);
194 memset (con_text, ' ', CON_TEXTSIZE);
196 for (i=0 ; i<numlines ; i++)
198 for (j=0 ; j<numchars ; j++)
200 con_text[(con_totallines - 1 - i) * con_linewidth + j] =
201 tbuf[((con_current - i + oldtotallines) %
202 oldtotallines) * oldwidth + j];
210 con_current = con_totallines - 1;
221 #define MAXGAMEDIRLEN 1000
222 char temp[MAXGAMEDIRLEN+1];
223 char *t2 = "/qconsole.log";
225 Cvar_RegisterVariable(&logfile);
226 con_debuglog = COM_CheckParm("-condebug");
230 if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2)))
232 sprintf (temp, "%s%s", com_gamedir, t2);
238 console_mempool = Mem_AllocPool("console");
239 con_text = Mem_Alloc(console_mempool, CON_TEXTSIZE);
240 memset (con_text, ' ', CON_TEXTSIZE);
244 Con_Printf ("Console initialized.\n");
247 // register our commands
249 Cvar_RegisterVariable (&con_notifytime);
251 Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
252 Cmd_AddCommand ("messagemode", Con_MessageMode_f);
253 Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
254 Cmd_AddCommand ("clear", Con_Clear_f);
255 con_initialized = true;
264 void Con_Linefeed (void)
268 memset (&con_text[(con_current%con_totallines)*con_linewidth]
269 , ' ', con_linewidth);
276 Handles cursor positioning, line wrapping, etc
277 All console printing must go through this in order to be logged to disk
278 If no console is visible, the notify window will pop up.
281 void Con_Print (char *txt)
292 mask = 128; // go to colored text
293 S_LocalSound ("misc/talk.wav");
297 else if (txt[0] == 2)
299 mask = 128; // go to colored text
309 for (l=0 ; l< con_linewidth ; l++)
314 if (l != con_linewidth && (con_x + l > con_linewidth) )
329 // mark time for transparent overlay
330 if (con_current >= 0)
331 con_times[con_current % NUM_CON_TIMES] = realtime;
345 default: // display character and advance
346 y = con_current % con_totallines;
347 con_text[y*con_linewidth+con_x] = c | mask;
349 if (con_x >= con_linewidth)
363 void Con_DebugLog(char *file, char *fmt, ...)
366 static char data[1024];
369 va_start(argptr, fmt);
370 vsprintf(data, fmt, argptr);
372 fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
373 write(fd, data, strlen(data));
382 Handles cursor positioning, line wrapping, etc
385 // LordHavoc: increased from 4096 to 16384
386 #define MAXPRINTMSG 16384
387 // FIXME: make a buffer size safe vsprintf?
388 void Con_Printf (char *fmt, ...)
391 char msg[MAXPRINTMSG];
392 // static qboolean inupdate;
394 va_start (argptr,fmt);
395 vsprintf (msg,fmt,argptr);
398 // also echo to debugging console
399 Sys_Printf ("%s", msg);
401 // log all messages to file
403 Con_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg);
405 if (!con_initialized)
408 if (cls.state == ca_dedicated)
409 return; // no graphics mode
411 // write it to the scrollable buffer
414 // update the screen if the console is displayed
415 // LordHavoc: I don't think there's a real need for this
417 // LordHavoc: don't print text while loading scripts
418 if (cls.state != ca_disconnected)
419 if (cls.signon != SIGNONS && !scr_disabled_for_loading )
421 // protect against infinite loop if something in SCR_UpdateScreen calls
437 A Con_Printf that only shows up if the "developer" cvar is set
440 void Con_DPrintf (char *fmt, ...)
443 char msg[MAXPRINTMSG];
445 if (!developer.integer)
446 return; // don't confuse non-developers with techie stuff...
448 va_start (argptr,fmt);
449 vsprintf (msg,fmt,argptr);
452 Con_Printf ("%s", msg);
460 Okay to call even when the screen can't be updated
463 void Con_SafePrintf (char *fmt, ...)
469 va_start (argptr,fmt);
470 vsprintf (msg,fmt,argptr);
473 temp = scr_disabled_for_loading;
474 scr_disabled_for_loading = true;
475 Con_Printf ("%s", msg);
476 scr_disabled_for_loading = temp;
481 ==============================================================================
485 ==============================================================================
493 The input line scrolls horizontally if typing goes beyond the right edge
495 Modified by EvilTypeGuy eviltypeguy@qeradiant.com
498 void Con_DrawInput (void)
502 char editlinecopy[256];
504 if (key_dest != key_console && !con_forcedup)
505 return; // don't draw anything
507 text = strcpy(editlinecopy, key_lines[edit_line]);
510 // Advanced Console Editing by Radix radix@planetquake.com
511 // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
512 // use strlen of edit_line instead of key_linepos to allow editing
513 // of early characters w/o erasing
515 // add the cursor frame
516 if ((int)(realtime*con_cursorspeed) & 1) // cursor is visible
517 text[key_linepos] = 11 + 130 * key_insert; // either solid or triangle facing right
519 text[key_linepos + 1] = 0; // LordHavoc: null terminate, rather than padding with spaces
520 // text[key_linepos] = 10 + ((int)(realtime*con_cursorspeed) & 1);
523 // fill out remainder with spaces
524 // for (i=key_linepos+1 ; i< con_linewidth ; i++)
527 // prestep if horizontally scrolling
528 if (key_linepos >= con_linewidth)
529 text += 1 + key_linepos - con_linewidth;
532 y = con_vislines - 16;
534 // for (i=0 ; i<con_linewidth ; i++)
535 // Draw_Character ( (i+1)<<3, con_vislines - 16, text[i]);
537 // LordHavoc: speedup
538 Draw_String(8, con_vislines - 16, text, con_linewidth);
541 key_lines[edit_line][key_linepos] = 0;
549 Draws the last few lines of output transparently over the game top
552 void Con_DrawNotify (void)
558 extern char chat_buffer[];
562 for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
566 time = con_times[i % NUM_CON_TIMES];
569 time = realtime - time;
570 if (time > con_notifytime.value)
572 text = con_text + (i % con_totallines)*con_linewidth;
576 // for (x = 0 ; x < con_linewidth ; x++)
577 // Draw_Character ( (x+1)<<3, v, text[x]);
578 // LordHavoc: speedup
579 Draw_String(8, v, text, con_linewidth);
585 if (key_dest == key_message)
591 // LordHavoc: speedup, and other improvements
593 sprintf(temptext, "say_team:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
595 sprintf(temptext, "say:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
596 while (strlen(temptext) >= con_linewidth)
598 Draw_String (8, v, temptext, con_linewidth);
599 strcpy(temptext, &temptext[con_linewidth]);
602 if (strlen(temptext) > 0)
604 Draw_String (8, v, temptext, 0);
607 // Draw_String (8, v, "say:", 0);
608 // while(chat_buffer[x])
610 // Draw_Character ( (x+5)<<3, v, chat_buffer[x]);
613 // Draw_Character ( (x+5)<<3, v, 10+((int)(realtime*con_cursorspeed)&1));
617 if (v > con_notifylines)
625 Draws the console with the solid background
626 The typing input line at the bottom should only be drawn if typing is allowed
629 void Con_DrawConsole (int lines, qboolean drawinput)
639 // draw the background
640 Draw_ConsoleBackground (lines);
643 con_vislines = lines;
645 rows = (lines-16)>>3; // rows of text to draw
646 y = lines - 16 - (rows<<3); // may start slightly negative
648 for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8 )
650 j = i - con_backscroll;
653 text = con_text + (j % con_totallines)*con_linewidth;
655 // for (x=0 ; x<con_linewidth ; x++)
656 // Draw_Character ( (x+1)<<3, y, text[x]);
657 // LordHavoc: speedup
658 Draw_String(8, y, text, con_linewidth);
661 // draw the input prompt, user text, and cursor if desired
669 New function for tab-completion system
671 MEGA Thanks to Taniwha
675 Con_DisplayList(char **list)
681 int width = (con_linewidth - 4);
694 if (pos + maxlen >= width) {
699 Con_Printf("%s", *list);
700 for (i = 0; i < (maxlen - len); i++)
712 Con_CompleteCommandLine
714 New function for tab-completion system
716 Thanks to Fett erich@heintz.com
721 Con_CompleteCommandLine (void)
727 char **list[3] = {0, 0, 0};
729 s = key_lines[edit_line] + 1;
730 // Count number of possible matches
731 c = Cmd_CompleteCountPossible(s);
732 v = Cvar_CompleteCountPossible(s);
733 a = Cmd_CompleteAliasCountPossible(s);
735 if (!(c + v + a)) // No possible matches
738 if (c + v + a == 1) {
740 list[0] = Cmd_CompleteBuildList(s);
742 list[0] = Cvar_CompleteBuildList(s);
744 list[0] = Cmd_CompleteAliasBuildList(s);
746 cmd_len = strlen (cmd);
749 cmd = *(list[0] = Cmd_CompleteBuildList(s));
751 cmd = *(list[1] = Cvar_CompleteBuildList(s));
753 cmd = *(list[2] = Cmd_CompleteAliasBuildList(s));
755 cmd_len = strlen (s);
757 for (i = 0; i < 3; i++) {
758 char ch = cmd[cmd_len];
761 while (*l && (*l)[cmd_len] == ch)
772 for (i = 0; i < con_linewidth - 4; i++)
776 // Print Possible Commands
778 Con_Printf("%i possible command%s\n", c, (c > 1) ? "s: " : ":");
779 Con_DisplayList(list[0]);
783 Con_Printf("%i possible variable%s\n", v, (v > 1) ? "s: " : ":");
784 Con_DisplayList(list[1]);
788 Con_Printf("%i possible aliases%s\n", a, (a > 1) ? "s: " : ":");
789 Con_DisplayList(list[2]);
794 strncpy(key_lines[edit_line] + 1, cmd, cmd_len);
795 key_linepos = cmd_len + 1;
796 if (c + v + a == 1) {
797 key_lines[edit_line][key_linepos] = ' ';
800 key_lines[edit_line][key_linepos] = 0;
802 for (i = 0; i < 3; i++)