git-svn-id: http://bladebattles.com/kurok/SVN@11 20cd92bb-ff49-0410-b73e-96a06e42c3b9
[kurok.git] / console.c
blobde94372661eabd2da8c34b3b89f1f067ee659872
1 /*
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.
20 // console.c
22 #ifdef NeXT
23 #include <libc.h>
24 #endif
25 #ifndef _MSC_VER
26 #include <unistd.h>
27 #endif
28 #include <fcntl.h>
29 #include "quakedef.h"
31 int con_linewidth;
33 float con_cursorspeed = 4;
35 #define CON_TEXTSIZE 16384
37 qboolean con_forcedup; // because no entities to refresh
39 int con_totallines; // total lines in console scrollback
40 int con_backscroll; // lines up from bottom to display
41 int con_current; // where next message will be printed
42 int con_x; // offset in current line for next print
43 char *con_text=0;
45 cvar_t con_notifytime = {"con_notifytime","3"}; //seconds
47 #define NUM_CON_TIMES 4
48 float con_times[NUM_CON_TIMES]; // realtime time the line was generated
49 // for transparent notify lines
51 int con_vislines;
53 qboolean con_debuglog;
55 #define MAXCMDLINE 256
56 extern char key_lines[32][MAXCMDLINE];
57 extern int edit_line;
58 extern int key_linepos;
61 qboolean con_initialized;
63 int con_notifylines; // scan lines to clear for notify lines
65 extern void M_Menu_Main_f (void);
67 void M_OSK_Draw (void);
68 void Con_OSK_f (char *input, char *output, int outlen);
69 void Con_OSK_Key(int key);
70 void Con_DrawOSK(void);
73 ================
74 Con_ToggleConsole_f
75 ================
77 void Con_ToggleConsole_f (void)
79 if (key_dest == key_console)
81 if (cls.state == ca_connected)
83 key_dest = key_game;
84 key_lines[edit_line][1] = 0; // clear any typing
85 key_linepos = 1;
87 else
89 M_Menu_Main_f ();
92 else
93 key_dest = key_console;
95 SCR_EndLoadingPlaque ();
96 memset (con_times, 0, sizeof(con_times));
100 ================
101 Con_Clear_f
102 ================
104 void Con_Clear_f (void)
106 if (con_text)
107 Q_memset (con_text, ' ', CON_TEXTSIZE);
112 ================
113 Con_ClearNotify
114 ================
116 void Con_ClearNotify (void)
118 int i;
120 for (i=0 ; i<NUM_CON_TIMES ; i++)
121 con_times[i] = 0;
126 ================
127 Con_MessageMode_f
128 ================
130 extern qboolean team_message;
132 void Con_MessageMode_f (void)
134 key_dest = key_message;
135 team_message = false;
140 ================
141 Con_MessageMode2_f
142 ================
144 void Con_MessageMode2_f (void)
146 key_dest = key_message;
147 team_message = true;
152 ================
153 Con_CheckResize
155 If the line width has changed, reformat the buffer.
156 ================
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)
166 return;
168 if (width < 1) // video hasn't been initialized yet
170 width = 38;
171 con_linewidth = width;
172 con_totallines = CON_TEXTSIZE / con_linewidth;
173 Q_memset (con_text, ' ', CON_TEXTSIZE);
175 else
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;
186 numchars = oldwidth;
188 if (con_linewidth < numchars)
189 numchars = con_linewidth;
191 Q_memcpy (tbuf, con_text, CON_TEXTSIZE);
192 Q_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];
204 Con_ClearNotify ();
207 con_backscroll = 0;
208 con_current = con_totallines - 1;
213 ================
214 Con_Init
215 ================
217 void Con_Init (void)
219 #define MAXGAMEDIRLEN 1000
220 char temp[MAXGAMEDIRLEN+1];
221 char *t2 = "/qconsole.log";
223 con_debuglog = COM_CheckParm("-condebug");
225 if (con_debuglog)
227 if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2)))
229 sprintf (temp, "%s%s", com_gamedir, t2);
230 unlink (temp);
234 con_text = Hunk_AllocName (CON_TEXTSIZE, "context");
235 Q_memset (con_text, ' ', CON_TEXTSIZE);
236 con_linewidth = -1;
237 Con_CheckResize ();
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;
255 ===============
256 Con_Linefeed
257 ===============
259 void Con_Linefeed (void)
261 con_x = 0;
262 con_current++;
263 Q_memset (&con_text[(con_current%con_totallines)*con_linewidth]
264 , ' ', con_linewidth);
268 ================
269 Con_Print
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.
274 ================
276 void Con_Print (char *txt)
278 int y;
279 int c, l;
280 static int cr;
281 int mask;
283 con_backscroll = 0;
285 if (txt[0] == 1)
287 mask = 128; // go to colored text
288 S_LocalSound ("misc/talk.wav");
289 // play talk wav
290 txt++;
292 else if (txt[0] == 2)
294 mask = 128; // go to colored text
295 txt++;
297 else
298 mask = 0;
301 while ( (c = *txt) )
303 // count word length
304 for (l=0 ; l< con_linewidth ; l++)
305 if ( txt[l] <= ' ')
306 break;
308 // word wrap
309 if (l != con_linewidth && (con_x + l > con_linewidth) )
310 con_x = 0;
312 txt++;
314 if (cr)
316 con_current--;
317 cr = false;
321 if (!con_x)
323 Con_Linefeed ();
324 // mark time for transparent overlay
325 if (con_current >= 0)
326 con_times[con_current % NUM_CON_TIMES] = realtime;
329 switch (c)
331 case '\n':
332 con_x = 0;
333 break;
335 case '\r':
336 con_x = 0;
337 cr = 1;
338 break;
340 default: // display character and advance
341 y = con_current % con_totallines;
342 con_text[y*con_linewidth+con_x] = c | mask;
343 con_x++;
344 if (con_x >= con_linewidth)
345 con_x = 0;
346 break;
354 ================
355 Con_DebugLog
356 ================
358 void Con_DebugLog(char *file, char *fmt, ...)
360 va_list argptr;
361 static char data[1024];
362 int fd;
364 va_start(argptr, fmt);
365 vsprintf(data, fmt, argptr);
366 va_end(argptr);
367 fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
368 write(fd, data, strlen(data));
369 close(fd);
374 ================
375 Con_Printf
377 Handles cursor positioning, line wrapping, etc
378 ================
380 #define MAXPRINTMSG 4096
381 // FIXME: make a buffer size safe vsprintf?
382 void Con_Printf (char *fmt, ...)
384 va_list argptr;
385 char msg[MAXPRINTMSG];
386 static qboolean inupdate;
388 va_start (argptr,fmt);
389 vsprintf (msg,fmt,argptr);
390 va_end (argptr);
392 // also echo to debugging console
393 Sys_Printf ("%s", msg); // also echo to debugging console
395 // log all messages to file
396 if (con_debuglog)
397 Con_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg);
399 if (!con_initialized)
400 return;
402 if (cls.state == ca_dedicated)
403 return; // no graphics mode
405 // write it to the scrollable buffer
406 Con_Print (msg);
408 // update the screen if the console is displayed
409 if (cls.signon != SIGNONS && !scr_disabled_for_loading )
411 // protect against infinite loop if something in SCR_UpdateScreen calls
412 // Con_Printd
413 if (!inupdate)
415 inupdate = true;
416 SCR_UpdateScreen ();
417 inupdate = false;
423 ================
424 Con_DPrintf
426 A Con_Printf that only shows up if the "developer" cvar is set
427 ================
429 void Con_DPrintf (char *fmt, ...)
431 va_list argptr;
432 char msg[MAXPRINTMSG];
434 if (!developer.value)
435 return; // don't confuse non-developers with techie stuff...
437 va_start (argptr,fmt);
438 vsprintf (msg,fmt,argptr);
439 va_end (argptr);
441 Con_Printf ("%s", msg);
446 ==================
447 Con_SafePrintf
449 Okay to call even when the screen can't be updated
450 ==================
452 void Con_SafePrintf (char *fmt, ...)
454 va_list argptr;
455 char msg[1024];
456 int temp;
458 va_start (argptr,fmt);
459 vsprintf (msg,fmt,argptr);
460 va_end (argptr);
462 temp = scr_disabled_for_loading;
463 scr_disabled_for_loading = true;
464 Con_Printf ("%s", msg);
465 scr_disabled_for_loading = temp;
470 ==============================================================================
472 DRAWING
474 ==============================================================================
479 ================
480 Con_DrawInput
482 The input line scrolls horizontally if typing goes beyond the right edge
483 ================
485 void Con_DrawInput (void)
487 int y;
488 int i;
489 char *text;
491 if (key_dest != key_console && !con_forcedup)
492 return; // don't draw anything
494 text = key_lines[edit_line];
496 // add the cursor frame
497 text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1);
499 // fill out remainder with spaces
500 for (i=key_linepos+1 ; i< con_linewidth ; i++)
501 text[i] = ' ';
503 // prestep if horizontally scrolling
504 if (key_linepos >= con_linewidth)
505 text += 1 + key_linepos - con_linewidth;
507 // draw it
508 y = con_vislines-16;
510 for (i=0 ; i<con_linewidth ; i++)
511 Draw_Character ( (i+1)<<3, con_vislines - 16, text[i]);
513 // remove cursor
514 key_lines[edit_line][key_linepos] = 0;
519 ================
520 Con_DrawNotify
522 Draws the last few lines of output transparently over the game top
523 ================
525 void Con_DrawNotify (void)
527 int x, v;
528 char *text;
529 int i;
530 float time;
531 extern char chat_buffer[];
533 v = 0;
534 for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
536 if (i < 0)
537 continue;
538 time = con_times[i % NUM_CON_TIMES];
539 if (time == 0)
540 continue;
541 time = realtime - time;
542 if (time > con_notifytime.value)
543 continue;
544 text = con_text + (i % con_totallines)*con_linewidth;
546 clearnotify = 0;
547 scr_copytop = 1;
549 for (x = 0 ; x < con_linewidth ; x++)
550 Draw_Character ( (x+1)<<3, v, text[x]);
552 v += 8;
556 if (key_dest == key_message)
558 clearnotify = 0;
559 scr_copytop = 1;
561 x = 0;
563 Draw_String (8, v, "say:");
564 while(chat_buffer[x])
566 Draw_Character ( (x+5)<<3, v, chat_buffer[x]);
567 x++;
569 Draw_Character ( (x+5)<<3, v, 10+((int)(realtime*con_cursorspeed)&1));
570 v += 8;
573 if (v > con_notifylines)
574 con_notifylines = v;
578 ================
579 Con_DrawConsole
581 Draws the console with the solid background
582 The typing input line at the bottom should only be drawn if typing is allowed
583 ================
585 void Con_DrawConsole (int lines, qboolean drawinput)
587 int i, x, y;
588 int rows;
589 char *text;
590 int j;
592 if (lines <= 0)
593 return;
595 // draw the background
596 Draw_ConsoleBackground (lines);
598 // draw the text
599 con_vislines = lines;
601 rows = (lines-16)>>3; // rows of text to draw
602 y = lines - 16 - (rows<<3); // may start slightly negative
604 for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8 )
606 j = i - con_backscroll;
607 if (j<0)
608 j = 0;
609 text = con_text + (j % con_totallines)*con_linewidth;
611 for (x=0 ; x<con_linewidth ; x++)
612 Draw_Character ( (x+1)<<3, y, text[x]);
615 // draw the input prompt, user text, and cursor if desired
616 if (drawinput)
617 Con_DrawInput ();
619 Con_DrawOSK();
622 static qboolean scr_osk_active = false;
625 void Con_SetOSKActive(qboolean active) {
626 scr_osk_active = active;
629 qboolean Con_isSetOSKActive(void) {
630 return scr_osk_active;
633 void Con_DrawOSK(void) {
634 if (scr_osk_active) {
635 M_OSK_Draw();
640 ==================
641 Con_NotifyBox
642 ==================
644 void Con_NotifyBox (char *text)
646 double t1, t2;
648 // during startup for sound / cd warnings
649 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");
651 Con_Printf (text);
653 Con_Printf ("Press a key.\n");
654 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");
656 key_count = -2; // wait for a key down and up
657 key_dest = key_console;
661 t1 = Sys_FloatTime ();
662 SCR_UpdateScreen ();
663 Sys_SendKeyEvents ();
664 t2 = Sys_FloatTime ();
665 realtime += t2-t1; // make the cursor blink
666 } while (key_count < 0);
668 Con_Printf ("\n");
669 key_dest = key_game;
670 realtime = 0; // put the cursor back to invisible