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;
67 qboolean con_initialized;
69 int con_notifylines; // scan lines to clear for notify lines
71 extern void M_Menu_Main_f (void);
78 void Con_ToggleConsole_f (void)
80 if (key_dest == key_console)
82 if (cls.state == ca_connected)
85 key_lines[edit_line][1] = 0; // clear any typing
94 key_dest = key_console;
96 SCR_EndLoadingPlaque ();
97 memset (con_times, 0, sizeof(con_times));
105 void Con_Clear_f (void)
108 memset (con_text, ' ', CON_TEXTSIZE);
117 void Con_ClearNotify (void)
121 for (i=0 ; i<NUM_CON_TIMES ; i++)
131 extern qboolean team_message;
133 void Con_MessageMode_f (void)
135 key_dest = key_message;
136 team_message = false;
145 void Con_MessageMode2_f (void)
147 key_dest = key_message;
156 If the line width has changed, reformat the buffer.
159 void Con_CheckResize (void)
161 int i, j, width, oldwidth, oldtotallines, numlines, numchars;
162 char tbuf[CON_TEXTSIZE];
164 width = (vid.width >> 3) - 2;
166 if (width == con_linewidth)
169 if (width < 1) // video hasn't been initialized yet
171 width = 78; // LordHavoc: changed from 38 to 78 (320 -> 640 conversion)
172 con_linewidth = width;
173 con_totallines = CON_TEXTSIZE / con_linewidth;
174 memset (con_text, ' ', CON_TEXTSIZE);
178 oldwidth = con_linewidth;
179 con_linewidth = width;
180 oldtotallines = con_totallines;
181 con_totallines = CON_TEXTSIZE / con_linewidth;
182 numlines = oldtotallines;
184 if (con_totallines < numlines)
185 numlines = con_totallines;
189 if (con_linewidth < numchars)
190 numchars = con_linewidth;
192 memcpy (tbuf, con_text, CON_TEXTSIZE);
193 memset (con_text, ' ', CON_TEXTSIZE);
195 for (i=0 ; i<numlines ; i++)
197 for (j=0 ; j<numchars ; j++)
199 con_text[(con_totallines - 1 - i) * con_linewidth + j] =
200 tbuf[((con_current - i + oldtotallines) %
201 oldtotallines) * oldwidth + j];
209 con_current = con_totallines - 1;
220 #define MAXGAMEDIRLEN 1000
221 char temp[MAXGAMEDIRLEN+1];
222 char *t2 = "/qconsole.log";
224 Cvar_RegisterVariable(&logfile);
225 con_debuglog = COM_CheckParm("-condebug");
229 if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2)))
231 sprintf (temp, "%s%s", com_gamedir, t2);
237 con_text = Hunk_AllocName (CON_TEXTSIZE, "context");
238 memset (con_text, ' ', CON_TEXTSIZE);
242 Con_Printf ("Console initialized.\n");
245 // register our commands
247 Cvar_RegisterVariable (&con_notifytime);
249 Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
250 Cmd_AddCommand ("messagemode", Con_MessageMode_f);
251 Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
252 Cmd_AddCommand ("clear", Con_Clear_f);
253 con_initialized = true;
262 void Con_Linefeed (void)
266 memset (&con_text[(con_current%con_totallines)*con_linewidth]
267 , ' ', con_linewidth);
274 Handles cursor positioning, line wrapping, etc
275 All console printing must go through this in order to be logged to disk
276 If no console is visible, the notify window will pop up.
279 void Con_Print (char *txt)
290 mask = 128; // go to colored text
291 S_LocalSound ("misc/talk.wav");
295 else if (txt[0] == 2)
297 mask = 128; // go to colored text
307 for (l=0 ; l< con_linewidth ; l++)
312 if (l != con_linewidth && (con_x + l > con_linewidth) )
327 // mark time for transparent overlay
328 if (con_current >= 0)
329 con_times[con_current % NUM_CON_TIMES] = realtime;
343 default: // display character and advance
344 y = con_current % con_totallines;
345 con_text[y*con_linewidth+con_x] = c | mask;
347 if (con_x >= con_linewidth)
361 void Con_DebugLog(char *file, char *fmt, ...)
364 static char data[1024];
367 va_start(argptr, fmt);
368 vsprintf(data, fmt, argptr);
370 fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
371 write(fd, data, strlen(data));
380 Handles cursor positioning, line wrapping, etc
383 // LordHavoc: increased from 4096 to 16384
384 #define MAXPRINTMSG 16384
385 // FIXME: make a buffer size safe vsprintf?
386 void Con_Printf (char *fmt, ...)
389 char msg[MAXPRINTMSG];
390 static qboolean inupdate;
392 va_start (argptr,fmt);
393 vsprintf (msg,fmt,argptr);
396 // also echo to debugging console
397 Sys_Printf ("%s", msg); // also echo to debugging console
399 // log all messages to file
401 Con_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg);
403 if (!con_initialized)
406 if (cls.state == ca_dedicated)
407 return; // no graphics mode
409 // write it to the scrollable buffer
412 // update the screen if the console is displayed
413 // LordHavoc: don't print text while loading scripts
414 if (cls.state != ca_disconnected)
415 if (cls.signon != SIGNONS && !scr_disabled_for_loading )
417 // protect against infinite loop if something in SCR_UpdateScreen calls
432 A Con_Printf that only shows up if the "developer" cvar is set
435 void Con_DPrintf (char *fmt, ...)
438 char msg[MAXPRINTMSG];
440 if (!developer.value)
441 return; // don't confuse non-developers with techie stuff...
443 va_start (argptr,fmt);
444 vsprintf (msg,fmt,argptr);
447 Con_Printf ("%s", msg);
455 Okay to call even when the screen can't be updated
458 void Con_SafePrintf (char *fmt, ...)
464 va_start (argptr,fmt);
465 vsprintf (msg,fmt,argptr);
468 temp = scr_disabled_for_loading;
469 scr_disabled_for_loading = true;
470 Con_Printf ("%s", msg);
471 scr_disabled_for_loading = temp;
476 ==============================================================================
480 ==============================================================================
488 The input line scrolls horizontally if typing goes beyond the right edge
491 void Con_DrawInput (void)
496 if (key_dest != key_console && !con_forcedup)
497 return; // don't draw anything
499 text = key_lines[edit_line];
501 // add the cursor frame
502 text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1);
504 text[key_linepos+1] = 0; // LordHavoc: null terminate, rather than padding with spaces
505 // fill out remainder with spaces
506 // for (i=key_linepos+1 ; i< con_linewidth ; i++)
509 // prestep if horizontally scrolling
510 if (key_linepos >= con_linewidth)
511 text += 1 + key_linepos - con_linewidth;
516 // for (i=0 ; i<con_linewidth ; i++)
517 // Draw_Character ( (i+1)<<3, con_vislines - 16, text[i]);
518 // LordHavoc: speedup
519 Draw_String(8, con_vislines - 16, text, con_linewidth);
522 key_lines[edit_line][key_linepos] = 0;
530 Draws the last few lines of output transparently over the game top
533 void Con_DrawNotify (void)
539 extern char chat_buffer[];
543 for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
547 time = con_times[i % NUM_CON_TIMES];
550 time = realtime - time;
551 if (time > con_notifytime.value)
553 text = con_text + (i % con_totallines)*con_linewidth;
558 // for (x = 0 ; x < con_linewidth ; x++)
559 // Draw_Character ( (x+1)<<3, v, text[x]);
560 // LordHavoc: speedup
561 Draw_String(8, v, text, con_linewidth);
567 if (key_dest == key_message)
574 // LordHavoc: speedup, and other improvements
576 sprintf(temptext, "say_team:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
578 sprintf(temptext, "say:%s%c", chat_buffer, (int) 10+((int)(realtime*con_cursorspeed)&1));
579 while (strlen(temptext) >= con_linewidth)
581 Draw_String (8, v, temptext, con_linewidth);
582 strcpy(temptext, &temptext[con_linewidth]);
585 if (strlen(temptext) > 0)
587 Draw_String (8, v, temptext, 0);
590 // Draw_String (8, v, "say:", 0);
591 // while(chat_buffer[x])
593 // Draw_Character ( (x+5)<<3, v, chat_buffer[x]);
596 // Draw_Character ( (x+5)<<3, v, 10+((int)(realtime*con_cursorspeed)&1));
600 if (v > con_notifylines)
608 Draws the console with the solid background
609 The typing input line at the bottom should only be drawn if typing is allowed
612 void Con_DrawConsole (int lines, qboolean drawinput)
622 // draw the background
623 Draw_ConsoleBackground (lines);
626 con_vislines = lines;
628 rows = (lines-16)>>3; // rows of text to draw
629 y = lines - 16 - (rows<<3); // may start slightly negative
631 for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8 )
633 j = i - con_backscroll;
636 text = con_text + (j % con_totallines)*con_linewidth;
638 // for (x=0 ; x<con_linewidth ; x++)
639 // Draw_Character ( (x+1)<<3, y, text[x]);
640 // LordHavoc: speedup
641 Draw_String(8, y, text, con_linewidth);
644 // draw the input prompt, user text, and cursor if desired
655 void Con_NotifyBox (char *text)
659 // during startup for sound / cd warnings
660 Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
664 Con_Printf ("Press a key.\n");
665 Con_Printf("\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
667 key_count = -2; // wait for a key down and up
668 key_dest = key_console;
672 t1 = Sys_FloatTime ();
674 Sys_SendKeyEvents ();
675 t2 = Sys_FloatTime ();
676 realtime += t2-t1; // make the cursor blink
677 } while (key_count < 0);
681 realtime = 0; // put the cursor back to invisible