Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 1
/*
2
Copyright (C) 1996-1997 Id Software, Inc.
3
 
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.
8
 
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.
12
 
13
See the GNU General Public License for more details.
14
 
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.
18
 
19
*/
20
// console.c
21
 
22
#ifdef NeXT
23
#include 
24
#endif
25
#ifndef _MSC_VER
26
#include 
27
#endif
28
#include 
29
#include "quakedef.h"
30
 
31
int 		con_linewidth;
32
 
33
float		con_cursorspeed = 4;
34
 
35
#define		CON_TEXTSIZE	16384
36
 
37
qboolean 	con_forcedup;		// because no entities to refresh
38
 
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;
44
 
45
cvar_t		con_notifytime = {"con_notifytime","3"};		//seconds
46
 
47
#define	NUM_CON_TIMES 4
48
float		con_times[NUM_CON_TIMES];	// realtime time the line was generated
49
								// for transparent notify lines
50
 
51
int			con_vislines;
52
 
53
qboolean	con_debuglog;
54
 
55
#define		MAXCMDLINE	256
56
extern	char	key_lines[32][MAXCMDLINE];
57
extern	int		edit_line;
58
extern	int		key_linepos;
59
 
60
 
61
qboolean	con_initialized;
62
 
63
int			con_notifylines;		// scan lines to clear for notify lines
64
 
65
extern void M_Menu_Main_f (void);
66
 
67
/*
68
================
69
Con_ToggleConsole_f
70
================
71
*/
72
void Con_ToggleConsole_f (void)
73
{
74
	if (key_dest == key_console)
75
	{
76
		if (cls.state == ca_connected)
77
		{
78
			key_dest = key_game;
79
			key_lines[edit_line][1] = 0;	// clear any typing
80
			key_linepos = 1;
81
		}
82
		else
83
		{
84
			M_Menu_Main_f ();
85
		}
86
	}
87
	else
88
		key_dest = key_console;
89
 
90
	SCR_EndLoadingPlaque ();
91
	memset (con_times, 0, sizeof(con_times));
92
}
93
 
94
/*
95
================
96
Con_Clear_f
97
================
98
*/
99
void Con_Clear_f (void)
100
{
101
	if (con_text)
102
		Q_memset (con_text, ' ', CON_TEXTSIZE);
103
}
104
 
105
 
106
/*
107
================
108
Con_ClearNotify
109
================
110
*/
111
void Con_ClearNotify (void)
112
{
113
	int		i;
114
 
115
	for (i=0 ; i
116
		con_times[i] = 0;
117
}
118
 
119
 
120
/*
121
================
122
Con_MessageMode_f
123
================
124
*/
125
extern qboolean team_message;
126
 
127
void Con_MessageMode_f (void)
128
{
129
	key_dest = key_message;
130
	team_message = false;
131
}
132
 
133
 
134
/*
135
================
136
Con_MessageMode2_f
137
================
138
*/
139
void Con_MessageMode2_f (void)
140
{
141
	key_dest = key_message;
142
	team_message = true;
143
}
144
 
145
 
146
/*
147
================
148
Con_CheckResize
149
 
150
If the line width has changed, reformat the buffer.
151
================
152
*/
153
void Con_CheckResize (void)
154
{
155
	int		i, j, width, oldwidth, oldtotallines, numlines, numchars;
156
	char	tbuf[CON_TEXTSIZE];
157
 
158
	width = (vid.width >> 3) - 2;
159
 
160
	if (width == con_linewidth)
161
		return;
162
 
163
	if (width < 1)			// video hasn't been initialized yet
164
	{
165
		width = 38;
166
		con_linewidth = width;
167
		con_totallines = CON_TEXTSIZE / con_linewidth;
168
		Q_memset (con_text, ' ', CON_TEXTSIZE);
169
	}
170
	else
171
	{
172
		oldwidth = con_linewidth;
173
		con_linewidth = width;
174
		oldtotallines = con_totallines;
175
		con_totallines = CON_TEXTSIZE / con_linewidth;
176
		numlines = oldtotallines;
177
 
178
		if (con_totallines < numlines)
179
			numlines = con_totallines;
180
 
181
		numchars = oldwidth;
182
 
183
		if (con_linewidth < numchars)
184
			numchars = con_linewidth;
185
 
186
		Q_memcpy (tbuf, con_text, CON_TEXTSIZE);
187
		Q_memset (con_text, ' ', CON_TEXTSIZE);
188
 
189
		for (i=0 ; i
190
		{
191
			for (j=0 ; j
192
			{
193
				con_text[(con_totallines - 1 - i) * con_linewidth + j] =
194
						tbuf[((con_current - i + oldtotallines) %
195
							  oldtotallines) * oldwidth + j];
196
			}
197
		}
198
 
199
		Con_ClearNotify ();
200
	}
201
 
202
	con_backscroll = 0;
203
	con_current = con_totallines - 1;
204
}
205
 
206
 
207
/*
208
================
209
Con_Init
210
================
211
*/
212
void Con_Init (void)
213
{
214
#define MAXGAMEDIRLEN	1000
215
	char	temp[MAXGAMEDIRLEN+1];
216
	char	*t2 = "/qconsole.log";
217
 
218
	con_debuglog = COM_CheckParm("-condebug");
219
 
220
	if (con_debuglog)
221
	{
222
		if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2)))
223
		{
224
			sprintf (temp, "%s%s", com_gamedir, t2);
225
			unlink (temp);
226
		}
227
	}
228
 
229
	con_text = Hunk_AllocName (CON_TEXTSIZE, "context");
230
	Q_memset (con_text, ' ', CON_TEXTSIZE);
231
	con_linewidth = -1;
232
	Con_CheckResize ();
233
 
234
	Con_Printf ("Console initialized.\n");
235
 
236
//
237
// register our commands
238
//
239
	Cvar_RegisterVariable (&con_notifytime);
240
 
241
	Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
242
	Cmd_AddCommand ("messagemode", Con_MessageMode_f);
243
	Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
244
	Cmd_AddCommand ("clear", Con_Clear_f);
245
	con_initialized = true;
246
}
247
 
248
 
249
/*
250
===============
251
Con_Linefeed
252
===============
253
*/
254
void Con_Linefeed (void)
255
{
256
	if ( ! con_initialized ) return;
257
	con_x = 0;
258
	con_current++;
259
	Q_memset (&con_text[(con_current%con_totallines)*con_linewidth]
260
	, ' ', con_linewidth);
261
}
262
 
263
/*
264
================
265
Con_Print
266
 
267
Handles cursor positioning, line wrapping, etc
268
All console printing must go through this in order to be logged to disk
269
If no console is visible, the notify window will pop up.
270
================
271
*/
272
void Con_Print (char *txt)
273
{
274
	int		y;
275
	int		c, l;
276
	static int	cr;
277
	int		mask;
278
 
279
	if ( ! con_initialized ) return;
280
	con_backscroll = 0;
281
 
282
	if (txt[0] == 1)
283
	{
284
		mask = 128;		// go to colored text
285
		S_LocalSound ("misc/talk.wav");
286
	// play talk wav
287
		txt++;
288
	}
289
	else if (txt[0] == 2)
290
	{
291
		mask = 128;		// go to colored text
292
		txt++;
293
	}
294
	else
295
		mask = 0;
296
 
297
 
298
	while ( (c = *txt) )
299
	{
300
	// count word length
301
		for (l=0 ; l< con_linewidth ; l++)
302
			if ( txt[l] <= ' ')
303
				break;
304
 
305
	// word wrap
306
		if (l != con_linewidth && (con_x + l > con_linewidth) )
307
			con_x = 0;
308
 
309
		txt++;
310
 
311
		if (cr)
312
		{
313
			con_current--;
314
			cr = false;
315
		}
316
 
317
 
318
		if (!con_x)
319
		{
320
			Con_Linefeed ();
321
		// mark time for transparent overlay
322
			if (con_current >= 0)
323
				con_times[con_current % NUM_CON_TIMES] = realtime;
324
		}
325
 
326
		switch (c)
327
		{
328
		case '\n':
329
			con_x = 0;
330
			break;
331
 
332
		case '\r':
333
			con_x = 0;
334
			cr = 1;
335
			break;
336
 
337
		default:	// display character and advance
338
			y = con_current % con_totallines;
339
			con_text[y*con_linewidth+con_x] = c | mask;
340
			con_x++;
341
			if (con_x >= con_linewidth)
342
				con_x = 0;
343
			break;
344
		}
345
 
346
	}
347
}
348
 
349
 
350
/*
351
================
352
Con_DebugLog
353
================
354
*/
355
void Con_DebugLog(char *file, char *fmt, ...)
356
{
357
    va_list argptr;
358
    static char data[1024];
359
    int fd;
360
 
361
    va_start(argptr, fmt);
362
    vsprintf(data, fmt, argptr);
363
    va_end(argptr);
364
    fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
365
    write(fd, data, strlen(data));
366
    close(fd);
367
}
368
 
369
 
370
/*
371
================
372
Con_Printf
373
 
374
Handles cursor positioning, line wrapping, etc
375
================
376
*/
377
#define	MAXPRINTMSG	4096
378
// FIXME: make a buffer size safe vsprintf?
379
void Con_Printf (char *fmt, ...)
380
{
381
	va_list		argptr;
382
	char		msg[MAXPRINTMSG];
383
	static qboolean	inupdate;
384
 
385
	va_start (argptr,fmt);
386
	vsprintf (msg,fmt,argptr);
387
	va_end (argptr);
388
 
389
// also echo to debugging console
390
	Sys_Printf ("%s", msg);	// also echo to debugging console
391
 
392
// log all messages to file
393
	if (con_debuglog)
394
		Con_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg);
395
 
396
	if (!con_initialized)
397
		return;
398
 
399
	if (cls.state == ca_dedicated)
400
		return;		// no graphics mode
401
 
402
// write it to the scrollable buffer
403
	Con_Print (msg);
404
 
405
// update the screen if the console is displayed
406
	if (cls.signon != SIGNONS && !scr_disabled_for_loading )
407
	{
408
	// protect against infinite loop if something in SCR_UpdateScreen calls
409
	// Con_Printd
410
		if (!inupdate)
411
		{
412
			inupdate = true;
413
			SCR_UpdateScreen ();
414
			inupdate = false;
415
		}
416
	}
417
}
418
 
419
/*
420
================
421
Con_DPrintf
422
 
423
A Con_Printf that only shows up if the "developer" cvar is set
424
================
425
*/
426
void Con_DPrintf (char *fmt, ...)
427
{
428
	va_list		argptr;
429
	char		msg[MAXPRINTMSG];
430
 
431
	if (!developer.value)
432
		return;			// don't confuse non-developers with techie stuff...
433
 
434
	va_start (argptr,fmt);
435
	vsprintf (msg,fmt,argptr);
436
	va_end (argptr);
437
 
438
	Con_Printf ("%s", msg);
439
}
440
 
441
 
442
/*
443
==================
444
Con_SafePrintf
445
 
446
Okay to call even when the screen can't be updated
447
==================
448
*/
449
void Con_SafePrintf (char *fmt, ...)
450
{
451
	va_list		argptr;
452
	char		msg[1024];
453
	int			temp;
454
 
455
	va_start (argptr,fmt);
456
	vsprintf (msg,fmt,argptr);
457
	va_end (argptr);
458
 
459
	temp = scr_disabled_for_loading;
460
	scr_disabled_for_loading = true;
461
	Con_Printf ("%s", msg);
462
	scr_disabled_for_loading = temp;
463
}
464
 
465
 
466
/*
467
==============================================================================
468
 
469
DRAWING
470
 
471
==============================================================================
472
*/
473
 
474
 
475
/*
476
================
477
Con_DrawInput
478
 
479
The input line scrolls horizontally if typing goes beyond the right edge
480
================
481
*/
482
void Con_DrawInput (void)
483
{
484
	int		y;
485
	int		i;
486
	char	*text;
487
 
488
	if (key_dest != key_console && !con_forcedup)
489
		return;		// don't draw anything
490
 
491
	text = key_lines[edit_line];
492
 
493
// add the cursor frame
494
	text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1);
495
 
496
// fill out remainder with spaces
497
	for (i=key_linepos+1 ; i< con_linewidth ; i++)
498
		text[i] = ' ';
499
 
500
//	prestep if horizontally scrolling
501
	if (key_linepos >= con_linewidth)
502
		text += 1 + key_linepos - con_linewidth;
503
 
504
// draw it
505
	y = con_vislines-16;
506
 
507
	for (i=0 ; i
508
		Draw_Character ( (i+1)<<3, con_vislines - 16, text[i]);
509
 
510
// remove cursor
511
	key_lines[edit_line][key_linepos] = 0;
512
}
513
 
514
 
515
/*
516
================
517
Con_DrawNotify
518
 
519
Draws the last few lines of output transparently over the game top
520
================
521
*/
522
void Con_DrawNotify (void)
523
{
524
	int		x, v;
525
	char	*text;
526
	int		i;
527
	float	time;
528
	extern char chat_buffer[];
529
 
530
	v = 0;
531
	for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
532
	{
533
		if (i < 0)
534
			continue;
535
		time = con_times[i % NUM_CON_TIMES];
536
		if (time == 0)
537
			continue;
538
		time = realtime - time;
539
		if (time > con_notifytime.value)
540
			continue;
541
		text = con_text + (i % con_totallines)*con_linewidth;
542
 
543
		clearnotify = 0;
544
		scr_copytop = 1;
545
 
546
		for (x = 0 ; x < con_linewidth ; x++)
547
			Draw_Character ( (x+1)<<3, v, text[x]);
548
 
549
		v += 8;
550
	}
551
 
552
 
553
	if (key_dest == key_message)
554
	{
555
		clearnotify = 0;
556
		scr_copytop = 1;
557
 
558
		x = 0;
559
 
560
		Draw_String (8, v, "say:");
561
		while(chat_buffer[x])
562
		{
563
			Draw_Character ( (x+5)<<3, v, chat_buffer[x]);
564
			x++;
565
		}
566
		Draw_Character ( (x+5)<<3, v, 10+((int)(realtime*con_cursorspeed)&1));
567
		v += 8;
568
	}
569
 
570
	if (v > con_notifylines)
571
		con_notifylines = v;
572
}
573
 
574
/*
575
================
576
Con_DrawConsole
577
 
578
Draws the console with the solid background
579
The typing input line at the bottom should only be drawn if typing is allowed
580
================
581
*/
582
void Con_DrawConsole (int lines, qboolean drawinput)
583
{
584
	int				i, x, y;
585
	int				rows;
586
	char			*text;
587
	int				j;
588
 
589
	if (lines <= 0)
590
		return;
591
 
592
// draw the background
593
	Draw_ConsoleBackground (lines);
594
 
595
// draw the text
596
	con_vislines = lines;
597
 
598
	rows = (lines-16)>>3;		// rows of text to draw
599
	y = lines - 16 - (rows<<3);	// may start slightly negative
600
 
601
	for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8 )
602
	{
603
		j = i - con_backscroll;
604
		if (j<0)
605
			j = 0;
606
		text = con_text + (j % con_totallines)*con_linewidth;
607
 
608
		for (x=0 ; x
609
			Draw_Character ( (x+1)<<3, y, text[x]);
610
	}
611
 
612
// draw the input prompt, user text, and cursor if desired
613
	if (drawinput)
614
		Con_DrawInput ();
615
}
616
 
617
 
618
/*
619
==================
620
Con_NotifyBox
621
==================
622
*/
623
void Con_NotifyBox (char *text)
624
{
625
	double		t1, t2;
626
 
627
// during startup for sound / cd warnings
628
	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");
629
 
630
	Con_Printf (text);
631
 
632
	Con_Printf ("Press a key.\n");
633
	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");
634
 
635
	key_count = -2;		// wait for a key down and up
636
	key_dest = key_console;
637
 
638
	do
639
	{
640
		t1 = Sys_FloatTime ();
641
		SCR_UpdateScreen ();
642
		Sys_SendKeyEvents ();
643
		t2 = Sys_FloatTime ();
644
		realtime += t2-t1;		// make the cursor blink
645
	} while (key_count < 0);
646
 
647
	Con_Printf ("\n");
648
	key_dest = key_game;
649
	realtime = 0;				// put the cursor back to invisible
650
}
651