From 2894182ec5b297cfc66ff800c61c5fcf078dd15b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Apr 2007 00:10:10 +0000 Subject: [PATCH] The status bar in the quakeworld server curses console finally does something. Currently only cpu usage, but as a proof-of-concept, it more than does its job. --- include/Makefile.am | 4 +- include/QF/plugin/console.h | 1 + include/sv_console.h | 18 +++++ libs/console/server.c | 128 +++++++++++++++++++++++++----------- qw/include/Makefile.am | 3 +- qw/include/server.h | 1 + qw/source/Makefile.am | 2 +- qw/source/sv_main.c | 3 + qw/source/sv_sbar.c | 82 +++++++++++++++++++++++ 9 files changed, 201 insertions(+), 41 deletions(-) create mode 100644 include/sv_console.h create mode 100644 qw/source/sv_sbar.c diff --git a/include/Makefile.am b/include/Makefile.am index 68d4a9650..026caa0db 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -10,8 +10,8 @@ EXTRA_DIST = asm_i386.h alsa_funcs_list.h adivtab.h anorm_dots.h anorms.h \ logos.h net_dgrm.h net_loop.h net_udp.h net_vcr.h net_wins.h netchan.h \ netmain.h old_keys.h ops.h qstring.h quakeasm.h regex.h r_cvar.h \ r_dynamic.h r_local.h r_screen.h r_shared.h rua_internal.h sbar.h \ - skin_stencil.h snd_render.h varrays.h vgamodes.h view.h vregset.h \ - winquake.h world.h \ + skin_stencil.h snd_render.h sv_console.h varrays.h vgamodes.h view.h \ + vregset.h winquake.h world.h \ \ qw/bothdefs.h qw/msg_backbuf.h qw/msg_ucmd.h qw/pmove.h qw/protocol.h \ \ diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index 32ebd8e87..0ea21d47f 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -60,6 +60,7 @@ typedef struct console_data_s { void (*quit)(void); struct cbuf_s *cbuf; struct view_s *view; + struct view_s *status_view; float lines; int (*exec_line)(void *data, const char *line); void *exec_data; diff --git a/include/sv_console.h b/include/sv_console.h new file mode 100644 index 000000000..c6584a90b --- /dev/null +++ b/include/sv_console.h @@ -0,0 +1,18 @@ +#ifndef __sv_console_h +#define __sv_console_h + +struct view_s; + +typedef struct sv_view_s { + void *win; + void *obj; + void (*draw) (struct view_s *view); + void (*setgeometry) (struct view_s *view); +} sv_view_t; + +typedef struct sv_sbar_s { + int width; + char *text; +} sv_sbar_t; + +#endif//__sv_console_h diff --git a/libs/console/server.c b/libs/console/server.c index a73d4d95f..e924a3319 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -46,6 +46,9 @@ static __attribute__ ((used)) const char rcsid[] = #ifdef HAVE_UNISTD_H # include #endif +#ifdef HAVE_MALLOC_H +# include +#endif #ifdef HAVE_SYS_IOCTL_H # include @@ -70,6 +73,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "QF/view.h" #include "compat.h" +#include "sv_console.h" static console_data_t sv_con_data; @@ -81,13 +85,6 @@ static void C_KeyEvent (knum_t key, short unicode, qboolean down); #ifdef HAVE_CURSES_H -typedef struct sv_view_s { - WINDOW *win; - void *obj; - void (*draw) (view_t *view); - void (*setgeometry) (view_t *view); -} sv_view_t; - enum { sv_resize_x = 1, sv_resize_y = 2, @@ -109,38 +106,62 @@ static int interrupted; #define MAX_LINES 1024 static int view_offset; -static chtype attr_table[4] = { +#define CP_YELLOW_BLACK (1) +#define CP_GREEN_BLACK (2) +#define CP_RED_BLACK (3) +#define CP_CYAN_BLACK (4) +#define CP_MAGENTA_BLACK (5) +#define CP_YELLOW_BLUE (6) +#define CP_GREEN_BLUE (7) +#define CP_RED_BLUE (8) +#define CP_CYAN_BLUE (9) +#define CP_MAGENTA_BLUE (10) + +static chtype attr_table[16] = { A_NORMAL, - COLOR_PAIR(1), - COLOR_PAIR(2), - COLOR_PAIR(3), + COLOR_PAIR (CP_GREEN_BLACK), + COLOR_PAIR (CP_RED_BLACK), + 0, + COLOR_PAIR (CP_YELLOW_BLACK), + COLOR_PAIR (CP_CYAN_BLACK), + COLOR_PAIR (CP_MAGENTA_BLACK), + 0, + A_NORMAL, + COLOR_PAIR (CP_GREEN_BLUE), + COLOR_PAIR (CP_RED_BLUE), + 0, + COLOR_PAIR (CP_YELLOW_BLUE), + COLOR_PAIR (CP_CYAN_BLUE), + COLOR_PAIR (CP_MAGENTA_BLUE), + 0, }; static const byte attr_map[256] = { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 3, 3, 0, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 3, 3, 0, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 6, 6, 0, 6, 6, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, }; static inline void -draw_fun_char (WINDOW *win, byte c) +draw_fun_char (WINDOW *win, byte c, int blue) { chtype ch = c; - ch = sys_char_map[ch] | attr_table[attr_map[ch]]; + int offset = blue ? 8 : 0; + ch = sys_char_map[ch] | attr_table[attr_map[ch] + offset]; waddch (win, ch); } @@ -221,7 +242,7 @@ draw_output (view_t *view) } } while (len--) - draw_fun_char (win, *text++); + draw_fun_char (win, *text++, 0); } while (cur_line < output_buffer->cur_line + view_offset); } @@ -229,8 +250,20 @@ static void draw_status (view_t *view) { sv_view_t *sv_view = view->data; - wbkgdset (sv_view->win, COLOR_PAIR(4)); - wclear (sv_view->win); + WINDOW *win = sv_view->win; + sv_sbar_t *sb = sv_view->obj; + int i; + char *old = alloca (sb->width); + + memcpy (old, sb->text, sb->width); + memset (sb->text, ' ', sb->width); + view_draw (view); + if (memcmp (old, sb->text, sb->width)) { + wbkgdset (win, COLOR_PAIR (CP_YELLOW_BLUE)); + wmove (win, 0, 0); + for (i = 0; i < sb->width; i++) + draw_fun_char (win, sb->text[i], 1); + } } static void @@ -245,7 +278,7 @@ draw_input_line (inputline_t *il) text = il->lines[il->edit_line] + il->scroll; wmove (win, 0, 0); if (il->scroll) { - waddch (win, '<' | COLOR_PAIR (5)); + waddch (win, '<' | COLOR_PAIR (CP_CYAN_BLACK)); text++; } else { waddch (win, *text++); @@ -259,7 +292,7 @@ draw_input_line (inputline_t *il) waddch (win, ' '); } if (*text) { - waddch (win, '>' | COLOR_PAIR (5)); + waddch (win, '>' | COLOR_PAIR (CP_CYAN_BLACK)); } else { waddch (win, ' '); } @@ -281,6 +314,16 @@ setgeometry_input (view_t *view) il->width = view->xlen; } +static void +setgeometry_status (view_t *view) +{ + sv_view_t *sv_view = view->data; + sv_sbar_t *sb = sv_view->obj; + sb->width = view->xlen; + sb->text = realloc (sb->text, sb->width); + memset (sb->text, 0, sb->width); // force an update +} + static void sigwinch (int sig) { @@ -437,7 +480,7 @@ print (char *txt) Con_BufferAddText (sv_view->obj, txt); if (!view_offset) { while (*txt) - draw_fun_char (sv_view->win, (byte) *txt++); + draw_fun_char (sv_view->win, (byte) *txt++, 0); sv_refresh (output); // move the cursor back to the input line sv_refresh (input); @@ -513,9 +556,10 @@ init (void) status = create_window (sv_con_data.view, 0, 1, screen_x, 1, grav_southwest, - 0, - sv_resize_x | sv_scroll, - draw_status, 0); + calloc (1, sizeof (sv_sbar_t)), + sv_resize_x, + draw_status, setgeometry_status); + sv_con_data.status_view = status; input = create_window (sv_con_data.view, 0, 0, screen_x, 1, grav_southwest, @@ -524,11 +568,17 @@ init (void) draw_input, setgeometry_input); ((inputline_t *) ((sv_view_t *) input->data)->obj)->user_data = input; - init_pair (1, COLOR_YELLOW, COLOR_BLACK); - init_pair (2, COLOR_GREEN, COLOR_BLACK); - init_pair (3, COLOR_RED, COLOR_BLACK); - init_pair (4, COLOR_YELLOW, COLOR_BLUE); - init_pair (5, COLOR_CYAN, COLOR_BLACK); + init_pair (CP_YELLOW_BLACK, COLOR_YELLOW, COLOR_BLACK); + init_pair (CP_GREEN_BLACK, COLOR_GREEN, COLOR_BLACK); + init_pair (CP_RED_BLACK, COLOR_RED, COLOR_BLACK); + init_pair (CP_CYAN_BLACK, COLOR_CYAN, COLOR_BLACK); + init_pair (CP_MAGENTA_BLACK, COLOR_MAGENTA, COLOR_BLACK); + + init_pair (CP_YELLOW_BLUE, COLOR_YELLOW, COLOR_BLUE); + init_pair (CP_GREEN_BLUE, COLOR_GREEN, COLOR_BLUE); + init_pair (CP_RED_BLUE, COLOR_RED, COLOR_BLUE); + init_pair (CP_CYAN_BLUE, COLOR_CYAN, COLOR_BLUE); + init_pair (CP_MAGENTA_BLUE, COLOR_MAGENTA, COLOR_BLUE); con_linewidth = screen_x; @@ -677,6 +727,10 @@ C_KeyEvent (knum_t key, short unicode, qboolean down) static void C_DrawConsole (void) { + // only the status bar is drawn because the inputline and output views + // take care of themselves + if (sv_con_data.status_view) + sv_con_data.status_view->draw (sv_con_data.status_view); } static void diff --git a/qw/include/Makefile.am b/qw/include/Makefile.am index 7b43e4fbe..6bee01009 100644 --- a/qw/include/Makefile.am +++ b/qw/include/Makefile.am @@ -5,4 +5,5 @@ EXTRA_DIST = \ cl_cam.h cl_chat.h cl_demo.h cl_ents.h cl_http.h cl_input.h \ cl_main.h cl_parse.h cl_pred.h cl_skin.h cl_slist.h cl_tent.h \ client.h crudefile.h game.h host.h map_cfg.h server.h sv_gib.h \ - sv_demo.h sv_pr_cmds.h sv_pr_qwe.h sv_progs.h sv_qtv.h sv_recorder.h + sv_demo.h sv_pr_cmds.h sv_pr_cpqw.h sv_pr_qwe.h sv_progs.h sv_qtv.h \ + sv_recorder.h diff --git a/qw/include/server.h b/qw/include/server.h index dd10ecb73..f39383274 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -457,6 +457,7 @@ extern struct cbuf_args_s *sv_args; // FIXME: declare exported functions in their own relevant .h void SV_Init (void); +void SV_Sbar_Init (void); void SV_Progs_Init (void); void SV_Progs_Init_Cvars (void); void SV_PR_Cmds_Init (void); diff --git a/qw/source/Makefile.am b/qw/source/Makefile.am index 14bdefedd..345531d54 100644 --- a/qw/source/Makefile.am +++ b/qw/source/Makefile.am @@ -72,7 +72,7 @@ EXTRA_DIST=sv_sys_win.c sv_sys_unix.c libqw_server_a_SOURCES= \ crudefile.c sv_ccmds.c sv_demo.c sv_ents.c sv_gib.c sv_init.c sv_main.c \ sv_move.c sv_phys.c sv_pr_cmds.c sv_pr_cpqw.c sv_pr_qwe.c sv_progs.c \ - sv_qtv.c sv_recorder.c sv_send.c sv_user.c world.c $(syssv_SRC) + sv_qtv.c sv_recorder.c sv_sbar.c sv_send.c sv_user.c world.c $(syssv_SRC) qw_server_LIBS= \ $(SERVER_PLUGIN_STATIC_LIBS) \ diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index c797628fd..6d757fc07 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2005,6 +2005,7 @@ SV_Frame (float time) svs.stats.packets = 0; svs.stats.count = 0; svs.stats.demo = 0; + Con_DrawConsole (); } Con_ProcessInput (); //XXX evil hack to get the cursor in the right place } @@ -2560,6 +2561,8 @@ SV_Init (void) Cmd_StuffCmds (sv_cbuf); Cbuf_Execute_Sets (sv_cbuf); + SV_Sbar_Init (); + Game_Init (); COM_Init (); diff --git a/qw/source/sv_sbar.c b/qw/source/sv_sbar.c new file mode 100644 index 000000000..13f30c5cb --- /dev/null +++ b/qw/source/sv_sbar.c @@ -0,0 +1,82 @@ +/* + #FILENAME# + + #DESCRIPTION# + + Copyright (C) 2007 #AUTHOR# + + Author: #AUTHOR# + Date: #DATE# + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static __attribute__ ((used)) const char rcsid[] = + "$Id: template.c 11394 2007-03-17 03:23:39Z taniwha $"; + +#include "QF/console.h" +#include "QF/plugin.h" +#include "QF/view.h" +#include "QF/va.h" + +#include "server.h" +#include "sv_console.h" + +static void +draw_cpu (view_t *view) +{ + sv_view_t *sv_view = view->data; + sv_sbar_t *sb = sv_view->obj; + double cpu; + const char *cpu_str; + const char *s; + char *d; + + cpu = (svs.stats.latched_active + svs.stats.latched_idle); + cpu = 100 * svs.stats.latched_active / cpu; + + cpu_str = va ("[CPU: %3d%%]", (int) cpu); + for (s = cpu_str, d = sb->text + view->xrel; *s; s++) + *d++ = *s; + if (cpu > 70.0) { + int i; + for (i = 6; i < 9; i++) + sb->text[view->xrel + i] |= 0x80; + } +} + +void +SV_Sbar_Init (void) +{ + view_t *status; + view_t *view; + + if (!con_module || !con_module->data->console->status_view) + return; + status = con_module->data->console->status_view; + + view = view_new (0, 0, 11, 1, grav_northwest); + view->draw = draw_cpu; + view->data = status->data; + view_add (status, view); +}