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