tReplaced display_message routine with one that is more flexible - i.e. it deals with changes in screen width properly, and stores every message received (e.g. for later scrollback). - vaccinewars - be a doctor and try to vaccinate the world
(HTM) git clone git://src.adamsgaard.dk/vaccinewars
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit 2e5bdc847b60ceaa12ec1c168aff50c4bd4bc49a
(DIR) parent d9165a1d152ddf528121bca6aca28c91f09af603
(HTM) Author: Ben Webb <ben@salilab.org>
Date: Sat, 4 Jan 2003 19:37:55 +0000
Replaced display_message routine with one that is more flexible - i.e. it
deals with changes in screen width properly, and stores every message
received (e.g. for later scrollback).
Diffstat:
M src/curses_client/curses_client.c | 142 ++++++++++++++++++++++++-------
1 file changed, 113 insertions(+), 29 deletions(-)
---
(DIR) diff --git a/src/curses_client/curses_client.c b/src/curses_client/curses_client.c
t@@ -60,6 +60,9 @@ static SCREEN *cur_screen;
/* Current size of the screen */
static int Width, Depth;
+/* Maximum number of messages to store (for scrollback etc.) */
+const static int MaxMessages = 1000;
+
#ifdef NETWORKING
static enum {
CM_SERVER, CM_PROMPT, CM_META, CM_SINGLE
t@@ -81,7 +84,7 @@ static void clear_line(int line), clear_exceptfor(int skip);
static void nice_wait(void);
static void DisplayFightMessage(Player *Play, char *text);
static void DisplaySpyReports(char *Data, Player *From, Player *To);
-static void display_message(char *buf);
+static void display_message(const char *buf);
static void print_location(char *text);
static void print_status(Player *Play, gboolean DispDrug);
static char *nice_input(char *prompt, int sy, int sx, gboolean digitsonly,
t@@ -194,6 +197,27 @@ static void mvaddcentstr(const int row, const gchar *str)
mvaddstr(row, col, str);
}
+/*
+ * Displays a string at the given coordinates and with the given
+ * attributes. If the string is longer than "wid", it is truncated, and
+ * if shorter, it is padded with spaces.
+ */
+static void mvaddfixwidstr(const int row, const int col, const int wid,
+ const gchar *str, const int attrs)
+{
+ int strwid = str ? strlen(str) : 0;
+ int strind;
+
+ strwid = MIN(strwid, wid);
+
+ for (strind = 0; strind < strwid; ++strind) {
+ mvaddch(row, col + strind, (guchar)str[strind] | attrs);
+ }
+ for (strind = strwid; strind < wid; ++strind) {
+ mvaddch(row, col + strind, (guchar)' ' | attrs);
+ }
+}
+
/*
* Displays a dopewars introduction screen.
*/
t@@ -1623,49 +1647,109 @@ void DisplayFightMessage(Player *Play, char *text)
}
}
+/*
+ * Returns the topmost row of the message area
+ */
+static int get_msg_area_top(void)
+{
+ return 10;
+}
+
+/*
+ * Returns the bottommost row of the message area
+ */
+static int get_msg_area_bottom(void)
+{
+ return 14;
+}
+
/*
- * Displays a network message "buf" in the message area (lines
- * 10 to 14) scrolling previous messages up.
+ * Displays a network message "buf" in the message area
+ * scrolling previous messages up.
* If "buf" is NULL, clears the message area
* If "buf" is a blank string, redisplays the message area
*/
-void display_message(char *buf)
+void display_message(const char *buf)
{
- guint x, y;
+ guint y, top, depth;
guint wid;
- static gchar Messages[5][200];
- gchar *bufpt;
+ static GList *msgs = NULL;
+ static int num_msgs = 0;
- if (Width <= 4)
- return;
+ top = get_msg_area_top();
+ depth = get_msg_area_bottom() - top + 1;
+ wid = Width - 4;
- wid = MIN(Width - 4, 200);
+ if (wid < 0 || depth < 0) {
+ return;
+ }
if (!buf) {
- for (y = 0; y < 5; y++) {
- memset(Messages[y], ' ', 200);
- if (Network) {
- mvaddch(y + 10, 0, ' ' | TextAttr);
- addch(ACS_VLINE | StatsAttr);
- for (x = 0; x < wid; x++)
- addch(' ' | StatsAttr);
- addch(ACS_VLINE | StatsAttr);
- addch(' ' | TextAttr);
+ GList *pt;
+ for (pt = msgs; pt; pt = g_list_next(pt)) {
+ g_free(pt->data);
+ }
+ g_list_free(msgs);
+ msgs = NULL;
+ num_msgs = 0;
+ /* Display a blank message area */
+ if (Network) {
+ for (y = 0; y < depth; y++) {
+ mvaddfixwidstr(y + top, 2, wid, NULL, StatsAttr);
}
}
} else if (Network) {
- bufpt = buf;
- while (bufpt[0] != 0) {
- memmove(Messages[0], Messages[1], 200 * 4);
- memset(Messages[4], ' ', 200);
- memcpy(Messages[4], bufpt,
- strlen(bufpt) > wid ? wid : strlen(bufpt));
- bufpt += MIN(strlen(bufpt), wid);
+ GList *pt, *nextpt;
+ gchar *data;
+ if (buf[0]) {
+ /* Remove the first message if we've got to the limit */
+ if (num_msgs == MaxMessages && msgs) {
+ g_free(msgs->data);
+ msgs = g_list_remove(msgs, msgs->data);
+ }
+ msgs = g_list_append(msgs, g_strdup(buf));
+ ++num_msgs;
}
- for (y = 0; y < 5; y++)
- for (x = 0; x < wid; x++) {
- mvaddch(y + 10, x + 2, (guchar)Messages[y][x] | StatsAttr);
+
+ nextpt = g_list_last(msgs);
+ pt = NULL;
+ data = NULL;
+ if (nextpt) {
+ int lines = 0, displines = depth;
+ /* Find the message to display at the top of the message area */
+ do {
+ displines -= lines;
+ pt = nextpt;
+ nextpt = g_list_previous(pt);
+ data = pt->data;
+ lines = (strlen(data) + wid - 1) / wid;
+ } while (displines > lines && nextpt);
+
+ /* Correct for the first line starting partway through a message */
+ if (displines < lines) {
+ data += wid * (lines - displines);
+ }
+ }
+
+ /* Display the relevant messages, line by line */
+ y = 0;
+ while (y < depth && pt) {
+ mvaddfixwidstr(y + top, 2, wid, data, StatsAttr);
+ ++y;
+ if (strlen(data) > wid) {
+ data += wid;
+ } else {
+ pt = g_list_next(pt);
+ if (pt) {
+ data = pt->data;
+ }
}
+ }
+
+ /* Blank out any remaining lines in the message area */
+ for (; y < depth; ++y) {
+ mvaddfixwidstr(y + top, 2, wid, NULL, StatsAttr);
+ }
refresh();
}
}