vkQuake2 doxygen  1.0 dev
console.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 Copyright (C) 2018-2019 Krzysztof Kondrak
4 
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 
14 See the GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 
20 */
21 // console.c
22 
23 #include "client.h"
24 
26 
28 extern cvar_t *vid_hudscale;
29 
30 
31 #define MAXCMDLINE 256
32 extern char key_lines[128][MAXCMDLINE];
33 extern int edit_line;
34 extern int key_linepos;
35 
36 void DrawString (int x, int y, char *s)
37 {
38  while (*s)
39  {
40  re.DrawChar (x, y, *s);
41  x+=8*vid_hudscale->value;
42  s++;
43  }
44 }
45 
46 void DrawAltString (int x, int y, char *s)
47 {
48  while (*s)
49  {
50  re.DrawChar (x, y, *s ^ 0x80);
51  x+=8*vid_hudscale->value;
52  s++;
53  }
54 }
55 
56 
57 void Key_ClearTyping (void)
58 {
59  key_lines[edit_line][1] = 0; // clear any typing
60  key_linepos = 1;
61 }
62 
63 /*
64 ================
65 Con_ToggleConsole_f
66 ================
67 */
69 {
70  SCR_EndLoadingPlaque (); // get rid of loading plaque
71 
72  if (cl.attractloop)
73  {
74  Cbuf_AddText ("killserver\n");
75  return;
76  }
77 
78  if (cls.state == ca_disconnected)
79  { // start the demo loop again
80  Cbuf_AddText ("d1\n");
81  return;
82  }
83 
84  Key_ClearTyping ();
85  Con_ClearNotify ();
86 
87  if (cls.key_dest == key_console)
88  {
89  M_ForceMenuOff ();
90  Cvar_Set ("paused", "0");
91  }
92  else
93  {
94  M_ForceMenuOff ();
96 
97  if (Cvar_VariableValue ("maxclients") == 1
98  && Com_ServerState ())
99  Cvar_Set ("paused", "1");
100  }
101 }
102 
103 /*
104 ================
105 Con_ToggleChat_f
106 ================
107 */
108 void Con_ToggleChat_f (void)
109 {
110  Key_ClearTyping ();
111 
112  if (cls.key_dest == key_console)
113  {
114  if (cls.state == ca_active)
115  {
116  M_ForceMenuOff ();
118  }
119  }
120  else
122 
123  Con_ClearNotify ();
124 }
125 
126 /*
127 ================
128 Con_Clear_f
129 ================
130 */
131 void Con_Clear_f (void)
132 {
133  memset (con.text, ' ', CON_TEXTSIZE);
134 }
135 
136 
137 /*
138 ================
139 Con_Dump_f
140 
141 Save the console contents out to a file
142 ================
143 */
144 void Con_Dump_f (void)
145 {
146  int l, x;
147  char *line;
148  FILE *f;
149  char buffer[1024];
150  char name[MAX_OSPATH];
151 
152  if (Cmd_Argc() != 2)
153  {
154  Com_Printf ("usage: condump <filename>\n");
155  return;
156  }
157 
158  Com_sprintf (name, sizeof(name), "%s/%s.txt", FS_Gamedir(), Cmd_Argv(1));
159 
160  Com_Printf ("Dumped console text to %s.\n", name);
162  f = fopen (name, "w");
163  if (!f)
164  {
165  Com_Printf ("ERROR: couldn't open.\n");
166  return;
167  }
168 
169  // skip empty lines
170  for (l = con.current - con.totallines + 1 ; l <= con.current ; l++)
171  {
172  line = con.text + (l%con.totallines)*con.linewidth;
173  for (x=0 ; x<con.linewidth ; x++)
174  if (line[x] != ' ')
175  break;
176  if (x != con.linewidth)
177  break;
178  }
179 
180  // write the remaining lines
181  buffer[con.linewidth] = 0;
182  for ( ; l <= con.current ; l++)
183  {
184  line = con.text + (l%con.totallines)*con.linewidth;
185  strncpy (buffer, line, con.linewidth);
186  for (x=con.linewidth-1 ; x>=0 ; x--)
187  {
188  if (buffer[x] == ' ')
189  buffer[x] = 0;
190  else
191  break;
192  }
193  for (x=0; buffer[x]; x++)
194  buffer[x] &= 0x7f;
195 
196  fprintf (f, "%s\n", buffer);
197  }
198 
199  fclose (f);
200 }
201 
202 
203 /*
204 ================
205 Con_ClearNotify
206 ================
207 */
208 void Con_ClearNotify (void)
209 {
210  int i;
211 
212  for (i=0 ; i<NUM_CON_TIMES ; i++)
213  con.times[i] = 0;
214 }
215 
216 
217 /*
218 ================
219 Con_MessageMode_f
220 ================
221 */
222 void Con_MessageMode_f (void)
223 {
224  chat_team = false;
226 }
227 
228 /*
229 ================
230 Con_MessageMode2_f
231 ================
232 */
234 {
235  chat_team = true;
237 }
238 
239 /*
240 ================
241 Con_CheckResize
242 
243 If the line width has changed, reformat the buffer.
244 ================
245 */
246 void Con_CheckResize (void)
247 {
248  int i, j, width, oldwidth, oldtotallines, numlines, numchars;
249  char tbuf[CON_TEXTSIZE];
250 
251  width = (viddef.width >> 3) - 2;
252 
253  if (width == con.linewidth)
254  return;
255 
256  if (width < 1) // video hasn't been initialized yet
257  {
258  width = 38;
259  con.linewidth = width;
261  memset (con.text, ' ', CON_TEXTSIZE);
262  }
263  else
264  {
265  oldwidth = con.linewidth;
266  con.linewidth = width;
267  oldtotallines = con.totallines;
269  numlines = oldtotallines;
270 
271  if (con.totallines < numlines)
272  numlines = con.totallines;
273 
274  numchars = oldwidth;
275 
276  if (con.linewidth < numchars)
277  numchars = con.linewidth;
278 
279  memcpy (tbuf, con.text, CON_TEXTSIZE);
280  memset (con.text, ' ', CON_TEXTSIZE);
281 
282  for (i=0 ; i<numlines ; i++)
283  {
284  for (j=0 ; j<numchars ; j++)
285  {
286  con.text[(con.totallines - 1 - i) * con.linewidth + j] =
287  tbuf[((con.current - i + oldtotallines) %
288  oldtotallines) * oldwidth + j];
289  }
290  }
291 
292  Con_ClearNotify ();
293  }
294 
295  con.current = con.totallines - 1;
297 }
298 
299 
300 /*
301 ================
302 Con_Init
303 ================
304 */
305 void Con_Init (void)
306 {
307  con.linewidth = -1;
308 
309  Con_CheckResize ();
310 
311  Com_Printf ("Console initialized.\n");
312 
313 //
314 // register our commands
315 //
316  con_notifytime = Cvar_Get ("con_notifytime", "3", 0);
317 
318  Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
319  Cmd_AddCommand ("togglechat", Con_ToggleChat_f);
320  Cmd_AddCommand ("messagemode", Con_MessageMode_f);
321  Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
322  Cmd_AddCommand ("clear", Con_Clear_f);
323  Cmd_AddCommand ("condump", Con_Dump_f);
324  con.initialized = true;
325 }
326 
327 
328 /*
329 ===============
330 Con_Linefeed
331 ===============
332 */
333 void Con_Linefeed (void)
334 {
335  con.x = 0;
336  if (con.display == con.current)
337  con.display++;
338  con.current++;
340  , ' ', con.linewidth);
341 }
342 
343 /*
344 ================
345 Con_Print
346 
347 Handles cursor positioning, line wrapping, etc
348 All console printing must go through this in order to be logged to disk
349 If no console is visible, the text will appear at the top of the game window
350 ================
351 */
352 void Con_Print (char *txt)
353 {
354  int y;
355  int c, l;
356  static int cr;
357  int mask;
358 
359  if (!con.initialized)
360  return;
361 
362  if (txt[0] == 1 || txt[0] == 2)
363  {
364  mask = 128; // go to colored text
365  txt++;
366  }
367  else
368  mask = 0;
369 
370 
371  while ( (c = *txt) )
372  {
373  // count word length
374  for (l=0 ; l< con.linewidth ; l++)
375  if ( txt[l] <= ' ')
376  break;
377 
378  // word wrap
379  if (l != con.linewidth && (con.x + l > con.linewidth) )
380  con.x = 0;
381 
382  txt++;
383 
384  if (cr)
385  {
386  con.current--;
387  cr = false;
388  }
389 
390 
391  if (!con.x)
392  {
393  Con_Linefeed ();
394  // mark time for transparent overlay
395  if (con.current >= 0)
397  }
398 
399  switch (c)
400  {
401  case '\n':
402  con.x = 0;
403  break;
404 
405  case '\r':
406  con.x = 0;
407  cr = 1;
408  break;
409 
410  default: // display character and advance
411  y = con.current % con.totallines;
412  con.text[y*con.linewidth+con.x] = c | mask | con.ormask;
413  con.x++;
414  if (con.x >= con.linewidth)
415  con.x = 0;
416  break;
417  }
418 
419  }
420 }
421 
422 
423 /*
424 ==============
425 Con_CenteredPrint
426 ==============
427 */
428 void Con_CenteredPrint (char *text)
429 {
430  int l;
431  char buffer[1024];
432 
433  l = (int)strlen(text);
434  l = (con.linewidth-l)/2;
435  if (l < 0)
436  l = 0;
437  memset (buffer, ' ', l);
438  strcpy (buffer+l, text);
439  strcat (buffer, "\n");
440  Con_Print (buffer);
441 }
442 
443 /*
444 ==============================================================================
445 
446 DRAWING
447 
448 ==============================================================================
449 */
450 
451 
452 /*
453 ================
454 Con_DrawInput
455 
456 The input line scrolls horizontally if typing goes beyond the right edge
457 ================
458 */
459 void Con_DrawInput (void)
460 {
461  int y;
462  int i;
463  char *text;
464 
465  if (cls.key_dest == key_menu)
466  return;
467  if (cls.key_dest != key_console && cls.state == ca_active)
468  return; // don't draw anything (always draw if not active)
469 
470  text = key_lines[edit_line];
471 
472 // add the cursor frame
473  text[key_linepos] = 10+((int)(cls.realtime>>8)&1);
474 
475 // fill out remainder with spaces
476  for (i=key_linepos+1 ; i< con.linewidth ; i++)
477  text[i] = ' ';
478 
479 // prestep if horizontally scrolling
480  if (key_linepos >= con.linewidth)
481  text += 1 + key_linepos - con.linewidth;
482 
483 // draw it
484  y = con.vislines-16;
485 
486  for (i=0 ; i<con.linewidth ; i++)
487  re.DrawChar ( ((i+1)<<3)*vid_hudscale->value, con.vislines - 22*vid_hudscale->value, text[i]);
488 
489 // remove cursor
491 }
492 
493 
494 /*
495 ================
496 Con_DrawNotify
497 
498 Draws the last few lines of output transparently over the game top
499 ================
500 */
501 void Con_DrawNotify (void)
502 {
503  int x, v;
504  char *text;
505  int i;
506  int time;
507  char *s;
508  int skip;
509 
510  v = 0;
511  for (i= con.current-NUM_CON_TIMES+1 ; i<=con.current ; i++)
512  {
513  if (i < 0)
514  continue;
515  time = con.times[i % NUM_CON_TIMES];
516  if (time == 0)
517  continue;
518  time = cls.realtime - time;
519  if (time > con_notifytime->value*1000)
520  continue;
521  text = con.text + (i % con.totallines)*con.linewidth;
522 
523  for (x = 0 ; x < con.linewidth ; x++)
524  re.DrawChar ( ((x+1)<<3)*vid_hudscale->value, v*vid_hudscale->value, text[x]);
525 
526  v += 8;
527  }
528 
529 
530  if (cls.key_dest == key_message)
531  {
532  if (chat_team)
533  {
534  DrawString (8, v*vid_hudscale->value, "say_team:");
535  skip = 11;
536  }
537  else
538  {
539  DrawString (8, v*vid_hudscale->value, "say:");
540  skip = 5;
541  }
542 
543  s = chat_buffer;
544  if (chat_bufferlen > (viddef.width>>3)-(skip+1))
545  s += chat_bufferlen - ((viddef.width>>3)-(skip+1));
546  x = 0;
547  while(s[x])
548  {
550  x++;
551  }
552  re.DrawChar ( ((x+skip)<<3)*vid_hudscale->value, v*vid_hudscale->value, 10+((cls.realtime>>8)&1));
553  v += 8;
554  }
555 
556  if (v)
557  {
558  SCR_AddDirtyPoint (0,0);
560  }
561 }
562 
563 /*
564 ================
565 Con_DrawConsole
566 
567 Draws the console with the solid background
568 ================
569 */
570 void Con_DrawConsole (float frac)
571 {
572  int i, j, x, y, n;
573  int rows;
574  char *text;
575  int row;
576  int lines;
577  char version[64];
578  char dlbar[1024];
579 
580  lines = viddef.height * frac;
581  if (lines <= 0)
582  return;
583 
584  if (lines > viddef.height)
585  lines = viddef.height;
586 
587 // draw the background
588  re.DrawStretchPic (0, lines-viddef.height, viddef.width, viddef.height, "conback");
589  SCR_AddDirtyPoint (0,0);
590  SCR_AddDirtyPoint (viddef.width-1,lines-1);
591 
592  Com_sprintf (version, sizeof(version), "v%4.2f", VERSION);
593 
594  for (x=0 ; x<5 ; x++)
595  re.DrawChar (viddef.width-44*vid_hudscale->value+x*8*vid_hudscale->value, lines-12*vid_hudscale->value, 128 + version[x] );
596 
597 // draw the text
598  con.vislines = lines;
599 
600  rows = (lines-22)>>3; // rows of text to draw
601  y = (lines - 30 * vid_hudscale->value)/vid_hudscale->value;
602 
603 // draw from the bottom up
604  if (con.display != con.current)
605  {
606  // draw arrows to show the buffer is backscrolled
607  for (x=0 ; x<con.linewidth ; x+=4)
608  re.DrawChar ( ((x+1)<<3)*vid_hudscale->value, y*vid_hudscale->value, '^');
609 
610  y -= 8;
611  rows--;
612  }
613 
614  row = con.display;
615  for (i=0 ; i<rows ; i++, y-=8, row--)
616  {
617  if (row < 0)
618  break;
619  if (con.current - row >= con.totallines)
620  break; // past scrollback wrap point
621 
622  text = con.text + (row % con.totallines)*con.linewidth;
623 
624  for (x=0 ; x<con.linewidth ; x++)
625  re.DrawChar ( ((x+1)<<3)*vid_hudscale->value, y*vid_hudscale->value, text[x]);
626  }
627 
628 //ZOID
629  // draw the download bar
630  // figure out width
631  if (cls.download) {
632  if ((text = strrchr(cls.downloadname, '/')) != NULL)
633  text++;
634  else
635  text = cls.downloadname;
636 
637  x = con.linewidth - ((con.linewidth * 7) / 40);
638  y = (x - (int)strlen(text) - 8) / vid_hudscale->value;
639  i = con.linewidth/3;
640  if (strlen(text) > i) {
641  y = x - i - 11;
642  strncpy(dlbar, text, i);
643  dlbar[i] = 0;
644  strcat(dlbar, "...");
645  } else
646  strcpy(dlbar, text);
647  strcat(dlbar, ": ");
648  i = (int)strlen(dlbar);
649  dlbar[i++] = '\x80';
650  // where's the dot go?
651  if (cls.downloadpercent == 0)
652  n = 0;
653  else
654  n = y * cls.downloadpercent / 100;
655 
656  for (j = 0; j < y; j++)
657  if (j == n)
658  dlbar[i++] = '\x83';
659  else
660  dlbar[i++] = '\x81';
661  dlbar[i++] = '\x82';
662  dlbar[i] = 0;
663 
664  sprintf(dlbar + strlen(dlbar), " %02d%%", cls.downloadpercent);
665 
666  // draw it
668  for (i = 0; i < strlen(dlbar); i++)
669  re.DrawChar ( ((i+1)<<3)*vid_hudscale->value, y, dlbar[i]);
670  }
671 //ZOID
672 
673 // draw the input prompt, user text, and cursor if desired
674  Con_DrawInput ();
675 }
676 
677 
SCR_EndLoadingPlaque
void SCR_EndLoadingPlaque(void)
Definition: cl_scrn.c:590
Con_DrawInput
void Con_DrawInput(void)
Definition: console.c:459
int
CONST PIXELFORMATDESCRIPTOR int
Definition: qgl_win.c:35
client_state_t::attractloop
qboolean attractloop
Definition: client.h:153
DrawAltString
void DrawAltString(int x, int y, char *s)
Definition: console.c:46
chat_buffer
char chat_buffer[MAXCMDLINE]
Definition: keys.c:392
Con_ToggleChat_f
void Con_ToggleChat_f(void)
Definition: console.c:108
ca_disconnected
@ ca_disconnected
Definition: client.h:186
MAXCMDLINE
#define MAXCMDLINE
Definition: console.c:31
v
GLdouble v
Definition: qgl_win.c:143
x
GLint GLenum GLint x
Definition: qgl_win.c:116
i
int i
Definition: q_shared.c:305
ca_active
@ ca_active
Definition: client.h:189
Con_ToggleConsole_f
void Con_ToggleConsole_f(void)
Definition: console.c:68
buffer
GLenum GLfloat * buffer
Definition: qgl_win.c:151
VERSION
#define VERSION
Definition: qcommon.h:26
width
GLint GLsizei width
Definition: qgl_win.c:115
Con_Clear_f
void Con_Clear_f(void)
Definition: console.c:131
vid_hudscale
cvar_t * vid_hudscale
Definition: vid_dll.c:48
Con_DrawConsole
void Con_DrawConsole(float frac)
Definition: console.c:570
edit_line
int edit_line
Definition: keys.c:36
Cvar_Get
cvar_t * Cvar_Get(char *var_name, char *var_value, int flags)
Definition: cvar.c:127
FS_CreatePath
void FS_CreatePath(char *path)
Definition: files.c:125
chat_bufferlen
int chat_bufferlen
Definition: keys.c:393
skip
static void skip(vorb *z, int n)
Definition: stb_vorbis.c:1336
cvar_s
Definition: q_shared.h:324
key_menu
@ key_menu
Definition: client.h:200
console_t::vislines
int vislines
Definition: console.h:44
viddef
viddef_t viddef
Definition: vid_dll.c:54
j
GLint j
Definition: qgl_win.c:150
Cmd_Argv
char * Cmd_Argv(int arg)
Definition: cmd.c:517
Cmd_Argc
int Cmd_Argc(void)
Definition: cmd.c:507
Con_MessageMode_f
void Con_MessageMode_f(void)
Definition: console.c:222
console_t::linewidth
int linewidth
Definition: console.h:39
viddef_t::width
unsigned width
Definition: vid.h:29
console_t::current
int current
Definition: console.h:33
Cmd_AddCommand
void Cmd_AddCommand(char *cmd_name, xcommand_t function)
Definition: cmd.c:691
key_game
@ key_game
Definition: client.h:200
viddef_t::height
unsigned height
Definition: vid.h:29
CON_TEXTSIZE
#define CON_TEXTSIZE
Definition: console.h:27
Con_CheckResize
void Con_CheckResize(void)
Definition: console.c:246
Cbuf_AddText
void Cbuf_AddText(char *text)
Definition: cmd.c:90
cvar_s::value
float value
Definition: q_shared.h:331
console_t::text
char text[CON_TEXTSIZE]
Definition: console.h:32
MAX_OSPATH
#define MAX_OSPATH
Definition: q_shared.h:81
con
console_t con
Definition: console.c:25
key_console
@ key_console
Definition: client.h:200
NULL
#define NULL
Definition: q_shared.h:67
key_lines
char key_lines[128][MAXCMDLINE]
Definition: keys.c:31
Con_ClearNotify
void Con_ClearNotify(void)
Definition: console.c:208
chat_team
qboolean chat_team
Definition: keys.c:391
DrawString
void DrawString(int x, int y, char *s)
Definition: console.c:36
name
cvar_t * name
Definition: cl_main.c:79
console_t::totallines
int totallines
Definition: console.h:40
s
static fixed16_t s
Definition: r_scan.c:30
SCR_AddDirtyPoint
void SCR_AddDirtyPoint(int x, int y)
Definition: cl_scrn.c:669
Con_Init
void Con_Init(void)
Definition: console.c:305
y
GLint y
Definition: qgl_win.c:115
console_t
Definition: console.h:28
re
refexport_t re
Definition: vid_dll.c:32
console_t::x
int x
Definition: console.h:34
Key_ClearTyping
void Key_ClearTyping(void)
Definition: console.c:57
client_static_t::download
FILE * download
Definition: client.h:229
Con_Linefeed
void Con_Linefeed(void)
Definition: console.c:333
NUM_CON_TIMES
#define NUM_CON_TIMES
Definition: console.h:25
Con_DrawNotify
void Con_DrawNotify(void)
Definition: console.c:501
console_t::times
float times[NUM_CON_TIMES]
Definition: console.h:46
client_static_t::state
connstate_t state
Definition: client.h:204
key_linepos
int key_linepos
Definition: keys.c:32
FS_Gamedir
char * FS_Gamedir(void)
Definition: files.c:559
Con_CenteredPrint
void Con_CenteredPrint(char *text)
Definition: console.c:428
Com_ServerState
int Com_ServerState(void)
Definition: common.c:256
Con_Dump_f
void Con_Dump_f(void)
Definition: console.c:144
console_t::display
int display
Definition: console.h:35
refexport_t::DrawStretchPic
void(* DrawStretchPic)(int x, int y, int w, int h, char *name)
Definition: ref.h:168
Cvar_Set
cvar_t * Cvar_Set(char *var_name, char *value)
Definition: cvar.c:278
console_t::ormask
int ormask
Definition: console.h:37
Con_Print
void Con_Print(char *txt)
Definition: console.c:352
client_static_t::key_dest
keydest_t key_dest
Definition: client.h:205
client_static_t::downloadname
char downloadname[MAX_OSPATH]
Definition: client.h:231
refexport_t::DrawChar
void(* DrawChar)(int x, int y, int c)
Definition: ref.h:169
Com_Printf
void Com_Printf(char *fmt,...)
Definition: common.c:104
con_notifytime
cvar_t * con_notifytime
Definition: console.c:27
cls
client_static_t cls
Definition: cl_main.c:90
mask
GLint GLuint mask
Definition: qgl_win.c:317
key_message
@ key_message
Definition: client.h:200
cl
client_state_t cl
Definition: cl_main.c:91
M_ForceMenuOff
void M_ForceMenuOff(void)
Definition: menu.c:123
Com_sprintf
void Com_sprintf(char *dest, int size, char *fmt,...)
Definition: q_shared.c:1223
client.h
console_t::initialized
qboolean initialized
Definition: console.h:30
client_static_t::realtime
int realtime
Definition: client.h:208
client_static_t::downloadpercent
int downloadpercent
Definition: client.h:234
Cvar_VariableValue
float Cvar_VariableValue(char *var_name)
Definition: cvar.c:63
Con_MessageMode2_f
void Con_MessageMode2_f(void)
Definition: console.c:233