tReplace lots of nasty "magic" numbers when printing to the prompt line or user interface area in the curses client with functions; provide a general function display_select_list that displays a list of strings in columns (e.g. for drugs, guns, logged on players, or locations to jet to). - 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 b23da53b00549c97cfb60fb8bcea0eee0ec06ef4 (DIR) parent 7c08b5b23e28bd8a8f0a9f298b4196a4cd0acd34 (HTM) Author: Ben Webb <ben@salilab.org> Date: Mon, 20 Jan 2003 13:04:52 +0000 Replace lots of nasty "magic" numbers when printing to the prompt line or user interface area in the curses client with functions; provide a general function display_select_list that displays a list of strings in columns (e.g. for drugs, guns, logged on players, or locations to jet to). Diffstat: M ChangeLog | 2 ++ M src/curses_client/curses_client.c | 415 +++++++++++++++++++------------ 2 files changed, 254 insertions(+), 163 deletions(-) --- (DIR) diff --git a/ChangeLog b/ChangeLog t@@ -1,6 +1,8 @@ cvs - The messages window in the curses client can now be scrolled with the + and - keys + - The curses client now makes better use of space with screen sizes + larger than 80x24 1.5.8 21-10-2002 - Options dialog now allows sounds for all supported game events to be set (DIR) diff --git a/src/curses_client/curses_client.c b/src/curses_client/curses_client.c t@@ -1,4 +1,5 @@ /************************************************************************ + * * curses_client.c dopewars client using the (n)curses console library * * Copyright (C) 1998-2003 Ben Webb * * Email: ben@bellatrix.pcl.ox.ac.uk * t@@ -150,6 +151,37 @@ void ResizeHandle(int sig) ResizedFlag = 1; } +/* + * 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; +} + +static int get_ui_area_top(void) +{ + return 16; +} + +static int get_ui_area_bottom(void) +{ + return Depth; +} + +static int get_prompt_line(void) +{ + return Depth - 2; +} + /* * Checks to see if the curses window needs to be resized - i.e. if a * SIGWINCH signal has been received. t@@ -195,7 +227,7 @@ static void mvaddcentstr(const int row, const gchar *str) guint col, len; len = strlen(str); - col = (len > Width ? 0 : (Width - len) / 2); + col = (len > (guint)Width ? 0 : ((guint)Width - len) / 2); mvaddstr(row, col, str); } t@@ -286,20 +318,21 @@ void display_intro(void) static void SelectServerManually(void) { gchar *text, *PortText; + int top = get_ui_area_top(); if (ServerName[0] == '(') AssignName(&ServerName, "localhost"); attrset(TextAttr); clear_bottom(); - mvaddstr(17, 1, + mvaddstr(top + 1, 1, /* Prompts for hostname and port when selecting a server * manually */ _("Please enter the hostname and port of a dopewars server:-")); - text = nice_input(_("Hostname: "), 18, 1, FALSE, ServerName, '\0'); + text = nice_input(_("Hostname: "), top + 2, 1, FALSE, ServerName, '\0'); AssignName(&ServerName, text); g_free(text); PortText = g_strdup_printf("%d", Port); - text = nice_input(_("Port: "), 19, 1, TRUE, PortText, '\0'); + text = nice_input(_("Port: "), top + 3, 1, TRUE, PortText, '\0'); Port = atoi(text); g_free(text); g_free(PortText); t@@ -322,10 +355,11 @@ static gboolean SelectServerFromMetaServer(Player *Play, GString *errstr) int maxsock; gboolean DoneOK; HttpConnection *MetaConn; + int top = get_ui_area_top(); attrset(TextAttr); clear_bottom(); - mvaddstr(17, 1, _("Please wait... attempting to contact metaserver...")); + mvaddstr(top + 1, 1, _("Please wait... attempting to contact metaserver...")); refresh(); if (OpenMetaHttpConnection(&MetaConn)) { t@@ -384,11 +418,11 @@ static gboolean SelectServerFromMetaServer(Player *Play, GString *errstr) clear_bottom(); /* Printout of metaserver information in curses client */ g_string_sprintf(text, _("Server : %s"), ThisServer->Name); - mvaddstr(17, 1, text->str); + mvaddstr(top + 1, 1, text->str); g_string_sprintf(text, _("Port : %d"), ThisServer->Port); - mvaddstr(18, 1, text->str); + mvaddstr(top + 2, 1, text->str); g_string_sprintf(text, _("Version : %s"), ThisServer->Version); - mvaddstr(18, 40, text->str); + mvaddstr(top + 2, 40, text->str); if (ThisServer->CurPlayers == -1) { g_string_sprintf(text, _("Players: -unknown- (maximum %d)"), ThisServer->MaxPlayers); t@@ -396,13 +430,13 @@ static gboolean SelectServerFromMetaServer(Player *Play, GString *errstr) g_string_sprintf(text, _("Players: %d (maximum %d)"), ThisServer->CurPlayers, ThisServer->MaxPlayers); } - mvaddstr(19, 1, text->str); + mvaddstr(top + 3, 1, text->str); g_string_sprintf(text, _("Up since : %s"), ThisServer->UpSince); - mvaddstr(19, 40, text->str); + mvaddstr(top + 3, 40, text->str); g_string_sprintf(text, _("Comment: %s"), ThisServer->Comment); - mvaddstr(20, 1, text->str); + mvaddstr(top + 4, 1, text->str); attrset(PromptAttr); - mvaddstr(23, 1, + mvaddstr(get_prompt_line() + 1, 1, _("N>ext server; P>revious server; S>elect this server... ")); /* The three keys that are valid responses to the previous question - t@@ -434,7 +468,7 @@ static gboolean SelectServerFromMetaServer(Player *Play, GString *errstr) g_string_assign(errstr, "No servers listed on metaserver"); return FALSE; } - clear_line(17); + clear_line(top + 1); refresh(); g_string_free(text, TRUE); return TRUE; t@@ -594,7 +628,7 @@ static gboolean ConnectToServer(Player *Play) gboolean MetaOK = TRUE, NetOK = TRUE, firstrun = FALSE; GString *errstr; gchar *text; - int c; + int c, top = get_ui_area_top(); errstr = g_string_new(""); t@@ -617,41 +651,41 @@ static gboolean ConnectToServer(Player *Play) attrset(TextAttr); clear_bottom(); if (MetaOK && !firstrun) { - mvaddstr(17, 1, _("Please wait... attempting to contact " - "dopewars server...")); + mvaddstr(top + 1, 1, _("Please wait... attempting to contact " + "dopewars server...")); refresh(); NetOK = DoConnect(Play, errstr); } if (!NetOK || !MetaOK || firstrun) { firstrun = FALSE; - clear_line(16); - clear_line(17); + clear_line(top); + clear_line(top + 1); if (!MetaOK) { /* Display of an error while contacting the metaserver */ - mvaddstr(16, 1, _("Cannot get metaserver details")); + mvaddstr(top, 1, _("Cannot get metaserver details")); text = g_strdup_printf(" (%s)", errstr->str); - mvaddstr(17, 1, text); + mvaddstr(top + 1, 1, text); g_free(text); } else if (!NetOK) { /* Display of an error message while trying to contact a dopewars * server (the error message itself is displayed on the next * screen line) */ - mvaddstr(16, 1, _("Could not start multiplayer dopewars")); + mvaddstr(top, 1, _("Could not start multiplayer dopewars")); text = g_strdup_printf(" (%s)", errstr->str); - mvaddstr(17, 1, text); + mvaddstr(top + 1, 1, text); g_free(text); } MetaOK = NetOK = TRUE; attrset(PromptAttr); - mvaddstr(18, 1, + mvaddstr(top + 2, 1, _("Will you... C>onnect to a named dopewars server")); - mvaddstr(19, 1, + mvaddstr(top + 3, 1, _(" L>ist the servers on the metaserver, and " "select one")); - mvaddstr(20, 1, + mvaddstr(top + 4, 1, _(" Q>uit (where you can start a server " "by typing \"dopewars -s\")")); - mvaddstr(21, 1, _(" or P>lay single-player ? ")); + mvaddstr(top + 5, 1, _(" or P>lay single-player ? ")); attrset(TextAttr); /* Translate these 4 keys in line with the above options, keeping t@@ -680,6 +714,52 @@ static gboolean ConnectToServer(Player *Play) } #endif /* NETWORKING */ +/* + * Displays the list of null-terminated names given by the "names" + * parameter in the bottom part of the screen. The names are spaced + * in columns so as to attempt to make best use of the available space. + * After displaying the names, the list is freed. + */ +void display_select_list(GSList *names) +{ + int top = get_ui_area_top() + 1, maxrows; + guint maxlen = 0; + int numcols, numrows, xoff, count, numlist; + GSList *listpt; + + maxrows = get_prompt_line() - top; + + for (listpt = names, numlist = 0; listpt; + listpt = g_slist_next(listpt), numlist++) { + maxlen = MAX(maxlen, strlen(listpt->data)); + } + + maxlen += 3; + numcols = Width / maxlen; + numcols = MAX(numcols, 1); + + /* Try and make the list reasonably "square" */ + while(numcols > 1) { + numrows = (numlist + numcols - 2) / (numcols - 1); + if (numrows <= maxrows && numrows <= numcols && numcols > 1) { + numcols--; + } else { + break; + } + } + + xoff = (Width - numcols * maxlen + 3) / 2; + xoff = MAX(xoff, 0); + + count = 0; + for (listpt = names; listpt; listpt = g_slist_next(listpt), count++) { + mvaddstr(top + count / numcols, xoff + maxlen * (count % numcols), + listpt->data); + g_free(listpt->data); + } + g_slist_free(names); +} + /* * Displays the list of locations and prompts the user to select one. * If "AllowReturn" is TRUE, then if the current location is selected t@@ -694,32 +774,35 @@ static gboolean ConnectToServer(Player *Play) static gboolean jet(Player *Play, gboolean AllowReturn) { int i, c; - GString *text; + GSList *names = NULL; + GString *str; - text = g_string_new(""); + str = g_string_new(""); attrset(TextAttr); clear_bottom(); for (i = 0; i < NumLocation; i++) { + gchar *text; /* Display of shortcut keys and locations to jet to */ - dpg_string_sprintf(text, _("%d. %tde"), i + 1, Location[i].Name); - mvaddstr(17 + i / 3, (i % 3) * 20 + 12, text->str); + text = dpg_strdup_printf(_("%d. %tde"), i + 1, Location[i].Name); + names = g_slist_append(names, text); } + display_select_list(names); attrset(PromptAttr); /* Prompt when the player chooses to "jet" to a new location */ - mvaddstr(22, 22, _("Where to, dude ? ")); + mvaddstr(get_prompt_line(), 22, _("Where to, dude ? ")); attrset(TextAttr); curs_set(1); do { c = bgetch(); if (c >= '1' && c < '1' + NumLocation) { - dpg_string_sprintf(text, _("%/Location display/%tde"), + dpg_string_sprintf(str, _("%/Location display/%tde"), Location[c - '1'].Name); - addstr(text->str); + addstr(str->str); if (Play->IsAt != c - '1') { - g_string_sprintf(text, "%d", c - '1'); + g_string_sprintf(str, "%d", c - '1'); DisplayMode = DM_NONE; - SendClientMessage(Play, C_NONE, C_REQUESTJET, NULL, text->str); + SendClientMessage(Play, C_NONE, C_REQUESTJET, NULL, str->str); } else { c = 0; } t@@ -729,7 +812,7 @@ static gboolean jet(Player *Play, gboolean AllowReturn) } while (c == 0 && !AllowReturn); curs_set(0); - g_string_free(text, TRUE); + g_string_free(str, TRUE); return (c != 0); } t@@ -739,7 +822,7 @@ static gboolean jet(Player *Play, gboolean AllowReturn) */ static void DropDrugs(Player *Play) { - int i, c, num, NumDrugs; + int i, c, num, NumDrugs, top = get_ui_area_top(); GString *text; gchar *buf; t@@ -751,18 +834,18 @@ static void DropDrugs(Player *Play) * default) */ _("You can\'t get any cash for the following " "carried %tde :"), Names.Drugs); - mvaddstr(16, 1, text->str); + mvaddstr(top, 1, text->str); NumDrugs = 0; for (i = 0; i < NumDrug; i++) { if (Play->Drugs[i].Carried > 0 && Play->Drugs[i].Price == 0) { g_string_sprintf(text, "%c. %-10s %-8d", NumDrugs + 'A', Drug[i].Name, Play->Drugs[i].Carried); - mvaddstr(17 + NumDrugs / 3, (NumDrugs % 3) * 25 + 4, text->str); + mvaddstr(top + NumDrugs / 3, (NumDrugs % 3) * 25 + 4, text->str); NumDrugs++; } } attrset(PromptAttr); - mvaddstr(22, 20, _("What do you want to drop? ")); + mvaddstr(get_prompt_line(), 20, _("What do you want to drop? ")); curs_set(1); attrset(TextAttr); c = bgetch(); t@@ -772,9 +855,8 @@ static void DropDrugs(Player *Play) c--; if (c < 'A') { addstr(Drug[i].Name); - buf = - nice_input(_("How many do you drop? "), 23, 8, TRUE, NULL, - '\0'); + buf = nice_input(_("How many do you drop? "), get_prompt_line() + 1, + 8, TRUE, NULL, '\0'); num = atoi(buf); g_free(buf); if (num > 0) { t@@ -805,13 +887,13 @@ static void DealDrugs(Player *Play, gboolean Buy) if (Play->Drugs[c].Price > 0) NumDrugsHere++; - clear_line(22); + clear_line(get_prompt_line()); attrset(PromptAttr); if (Buy) { /* Buy and sell prompts for dealing drugs or guns */ - mvaddstr(22, 20, _("What do you wish to buy? ")); + mvaddstr(get_prompt_line(), 20, _("What do you wish to buy? ")); } else { - mvaddstr(22, 20, _("What do you wish to sell? ")); + mvaddstr(get_prompt_line(), 20, _("What do you wish to sell? ")); } curs_set(1); attrset(TextAttr); t@@ -831,9 +913,9 @@ static void DealDrugs(Player *Play, gboolean Buy) * buying drugs */ text = g_strdup_printf(_("You can afford %d, and can carry %d. "), CanAfford, CanCarry); - mvaddstr(23, 2, text); - input = nice_input(_("How many do you buy? "), 23, 2 + strlen(text), - TRUE, NULL, '\0'); + mvaddstr(get_prompt_line() + 1, 2, text); + input = nice_input(_("How many do you buy? "), get_prompt_line() + 1, + 2 + strlen(text), TRUE, NULL, '\0'); c = atoi(input); g_free(input); g_free(text); t@@ -847,9 +929,9 @@ static void DealDrugs(Player *Play, gboolean Buy) text = g_strdup_printf(_("You have %d. "), Play->Drugs[DrugNum].Carried); - mvaddstr(23, 2, text); - input = nice_input(_("How many do you sell? "), 23, 2 + strlen(text), - TRUE, NULL, '\0'); + mvaddstr(get_prompt_line() + 1, 2, text); + input = nice_input(_("How many do you sell? "), get_prompt_line() + 1, + 2 + strlen(text), TRUE, NULL, '\0'); c = atoi(input); g_free(input); g_free(text); t@@ -876,7 +958,7 @@ static void GiveErrand(Player *Play) text = g_string_new(""); attrset(TextAttr); clear_bottom(); - y = 17; + y = get_ui_area_top() + 1; /* Prompt for sending your bitches out to spy etc. (%tde = "bitches" by * default) */ t@@ -948,9 +1030,9 @@ static void GiveErrand(Player *Play) static int want_to_quit(void) { attrset(TextAttr); - clear_line(22); + clear_line(get_prompt_line()); attrset(PromptAttr); - mvaddstr(22, 1, _("Are you sure you want to quit? ")); + mvaddstr(get_prompt_line(), 1, _("Are you sure you want to quit? ")); attrset(TextAttr); return (GetKey(_("YN"), "YN", FALSE, TRUE, FALSE) != 'N'); } t@@ -963,7 +1045,8 @@ static void change_name(Player *Play, gboolean nullname) gchar *NewName; /* Prompt for player to change his/her name */ - NewName = nice_input(_("New name: "), 23, 0, FALSE, NULL, '\0'); + NewName = nice_input(_("New name: "), get_prompt_line() + 1, 0, FALSE, + NULL, '\0'); if (NewName[0]) { StripTerminators(NewName); t@@ -1028,17 +1111,17 @@ void HandleClientMessage(char *Message, Player *Play) break; case C_PUSH: attrset(TextAttr); - clear_line(22); - mvaddstr(22, 0, _("You have been pushed from the server. " - "Reverting to single player mode.")); + clear_line(get_prompt_line()); + mvaddstr(get_prompt_line(), 0, _("You have been pushed from the server. " + "Reverting to single player mode.")); nice_wait(); SwitchToSinglePlayer(Play); print_status(Play, TRUE); break; case C_QUIT: attrset(TextAttr); - clear_line(22); - mvaddstr(22, 0, + clear_line(get_prompt_line()); + mvaddstr(get_prompt_line(), 0, _("The server has terminated. Reverting to " "single player mode.")); nice_wait(); t@@ -1077,7 +1160,7 @@ void HandleClientMessage(char *Message, Player *Play) text = g_strdup_printf(_("%s will now be known as %s."), GetPlayerName(From), Data); SetPlayerName(From, Data); - mvaddstr(22, 0, text); + mvaddstr(get_prompt_line(), 0, text); g_free(text); nice_wait(); break; t@@ -1141,18 +1224,19 @@ void HandleClientMessage(char *Message, Player *Play) } break; case C_NEWNAME: - clear_line(22); - clear_line(23); + clear_line(get_prompt_line()); + clear_line(get_prompt_line() + 1); attrset(TextAttr); - mvaddstr(22, 0, _("Unfortunately, somebody else is already " - "using \"your\" name. Please change it.")); + mvaddstr(get_prompt_line(), 0, + _("Unfortunately, somebody else is already " + "using \"your\" name. Please change it.")); change_name(Play, TRUE); break; default: if (!Handled) { text = g_strdup_printf("%s^%c^%s^%s", GetPlayerName(From), Code, GetPlayerName(Play), Data); - mvaddstr(22, 0, text); + mvaddstr(get_prompt_line(), 0, text); g_free(text); nice_wait(); } t@@ -1208,14 +1292,14 @@ void PrintMessage(const gchar *text) guint i, line; attrset(TextAttr); - clear_line(16); + clear_line(get_ui_area_top()); line = 1; for (i = 0; i < strlen(text) && (text[i] == '^' || text[i] == '\n'); i++) line++; clear_exceptfor(line); - line = 17; + line = get_ui_area_top() + 1; move(line, 1); for (i = 0; i < strlen(text); i++) { if (text[i] == '^' || text[i] == '\n') { t@@ -1231,19 +1315,19 @@ static void SellGun(Player *Play) gchar *text; gint gunind; - clear_line(22); + clear_line(get_prompt_line()); if (TotalGunsCarried(Play) == 0) { /* Error - player tried to sell guns that he/she doesn't have * (%tde="guns" by default) */ text = dpg_strdup_printf(_("You don't have any %tde to sell!"), Names.Guns); - mvaddstr(22, (Width - strlen(text)) / 2, text); + mvaddcentstr(get_prompt_line(), text); g_free(text); nice_wait(); - clear_line(23); + clear_line(get_prompt_line() + 1); } else { attrset(PromptAttr); - mvaddstr(22, 20, _("What do you wish to sell? ")); + mvaddstr(get_prompt_line(), 20, _("What do you wish to sell? ")); curs_set(1); attrset(TextAttr); gunind = bgetch(); t@@ -1252,11 +1336,11 @@ static void SellGun(Player *Play) gunind -= 'A'; addstr(Gun[gunind].Name); if (Play->Guns[gunind].Carried == 0) { - clear_line(22); + clear_line(get_prompt_line()); /* Error - player tried to sell some guns that he/she doesn't have */ - mvaddstr(22, 10, _("You don't have any to sell!")); + mvaddstr(get_prompt_line(), 10, _("You don't have any to sell!")); nice_wait(); - clear_line(23); + clear_line(get_prompt_line() + 1); } else { Play->Cash += Gun[gunind].Price; Play->CoatSize += Gun[gunind].Space; t@@ -1275,7 +1359,7 @@ static void BuyGun(Player *Play) gchar *text; gint gunind; - clear_line(22); + clear_line(get_prompt_line()); if (TotalGunsCarried(Play) >= Play->Bitches.Carried + 2) { text = dpg_strdup_printf( /* Error - player tried to buy more guns t@@ -1285,13 +1369,13 @@ static void BuyGun(Player *Play) _("You'll need more %tde to carry " "any more %tde!"), Names.Bitches, Names.Guns); - mvaddstr(22, (Width - strlen(text)) / 2, text); + mvaddcentstr(get_prompt_line(), text); g_free(text); nice_wait(); - clear_line(23); + clear_line(get_prompt_line() + 1); } else { attrset(PromptAttr); - mvaddstr(22, 20, _("What do you wish to buy? ")); + mvaddstr(get_prompt_line(), 20, _("What do you wish to buy? ")); curs_set(1); attrset(TextAttr); gunind = bgetch(); t@@ -1300,25 +1384,25 @@ static void BuyGun(Player *Play) gunind -= 'A'; addstr(Gun[gunind].Name); if (Gun[gunind].Space > Play->CoatSize) { - clear_line(22); + clear_line(get_prompt_line()); /* Error - player tried to buy a gun that he/she doesn't have * space for (%tde="gun" by default) */ text = dpg_strdup_printf(_("You don't have enough space to " "carry that %tde!"), Names.Gun); - mvaddstr(22, (Width - strlen(text)) / 2, text); + mvaddcentstr(get_prompt_line(), text); g_free(text); nice_wait(); - clear_line(23); + clear_line(get_prompt_line() + 1); } else if (Gun[gunind].Price > Play->Cash) { - clear_line(22); + clear_line(get_prompt_line()); /* Error - player tried to buy a gun that he/she can't afford * (%tde="gun" by default) */ text = dpg_strdup_printf(_("You don't have enough cash to buy " "that %tde!"), Names.Gun); - mvaddstr(22, (Width - strlen(text)) / 2, text); + mvaddcentstr(get_prompt_line(), text); g_free(text); nice_wait(); - clear_line(23); + clear_line(get_prompt_line() + 1); } else { Play->Cash -= Gun[gunind].Price; Play->CoatSize -= Gun[gunind].Space; t@@ -1339,24 +1423,24 @@ static void BuyGun(Player *Play) void GunShop(Player *Play) { int i, action; + GSList *names = NULL; gchar *text; print_status(Play, FALSE); attrset(TextAttr); clear_bottom(); for (i = 0; i < NumGun; i++) { - text = - dpg_strdup_printf("%c. %-22tde %12P", 'A' + i, Gun[i].Name, - Gun[i].Price); - mvaddstr(17 + i / 2, (i % 2) * 40 + 1, text); - g_free(text); + text = dpg_strdup_printf("%c. %-22tde %12P", 'A' + i, Gun[i].Name, + Gun[i].Price); + names = g_slist_append(names, text); } + display_select_list(names); do { /* Prompt for actions in the gun shop */ text = _("Will you B>uy, S>ell, or L>eave? "); attrset(PromptAttr); - clear_line(22); - mvaddcentstr(22, text); + clear_line(get_prompt_line()); + mvaddcentstr(get_prompt_line(), text); attrset(TextAttr); /* Translate these three keys in line with the above options, keeping t@@ -1552,38 +1636,41 @@ void clear_line(int line) } /* - * Clears the bottom of the screen (i.e. from line 16 to line 23) + * Clears the bottom of the screen (the user interface) * except for the top "skip" lines. */ void clear_exceptfor(int skip) { - int i; + int i, from = get_ui_area_top() + skip, to = get_ui_area_bottom(); - for (i = 16 + skip; i <= 23; i++) + for (i = from; i <= to; i++) { clear_line(i); + } } /* - * Clears screen lines 16 to 23. + * Clears the bottom part of the screen (the user interface) */ void clear_bottom(void) { - int i; + int i, from = get_ui_area_top(), to = get_ui_area_bottom(); - for (i = 16; i <= 23; i++) + for (i = from; i <= to; i++) { clear_line(i); + } } /* - * Clears the entire screen; 24 lines of 80 characters each. + * Clears the entire screen */ void clear_screen(void) { int i; - for (i = 0; i < Depth; i++) + for (i = 0; i < Depth; i++) { clear_line(i); + } } /* t@@ -1593,7 +1680,7 @@ void clear_screen(void) void nice_wait() { attrset(PromptAttr); - mvaddcentstr(23, _("Press any key...")); + mvaddcentstr(get_prompt_line() + 1, _("Press any key...")); bgetch(); attrset(TextAttr); } t@@ -1655,22 +1742,6 @@ 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; -} - /* Number of lines that the message window is scrolled back by */ static int scrollpos = 0; t@@ -2017,37 +2088,39 @@ Player *ListPlayers(Player *Play, gboolean Select, char *Prompt) { Player *tmp = NULL; GSList *list; - int i, c; + int i, c, top = get_ui_area_top(), bottom = get_ui_area_bottom(); gchar *text; + GSList *names = NULL; attrset(TextAttr); clear_bottom(); if (!FirstClient || (!g_slist_next(FirstClient) && FirstClient->data == Play)) { text = _("No other players are currently logged on!"); - mvaddstr(18, (Width - strlen(text)) / 2, text); + mvaddcentstr((top + bottom) / 2, text); nice_wait(); return 0; } - mvaddstr(16, 1, _("Players currently logged on:-")); + mvaddstr(top, 1, _("Players currently logged on:-")); i = 0; for (list = FirstClient; list; list = g_slist_next(list)) { tmp = (Player *)list->data; if (strcmp(GetPlayerName(tmp), GetPlayerName(Play)) == 0) continue; - if (Select) + if (Select) { text = g_strdup_printf("%c. %s", 'A' + i, GetPlayerName(tmp)); - else + } else { text = g_strdup(GetPlayerName(tmp)); - mvaddstr(17 + i / 2, (i % 2) * 40 + 1, text); - g_free(text); + } + names = g_slist_append(names, text); i++; } + display_select_list(names); if (Prompt) { attrset(PromptAttr); - mvaddstr(22, 10, Prompt); + mvaddstr(get_prompt_line(), 10, Prompt); attrset(TextAttr); } if (Select) { t@@ -2163,6 +2236,38 @@ char *nice_input(char *prompt, int sy, int sx, gboolean digitsonly, return ReturnString; } +static void DisplayDrugsHere(Player *Play) +{ + int NumDrugsHere, i, c; + gchar *text; + GSList *names = NULL; + + attrset(TextAttr); + NumDrugsHere = 0; + for (i = 0; i < NumDrug; i++) { + if (Play->Drugs[i].Price > 0) { + NumDrugsHere++; + } + } + clear_bottom(); + /* Display of drug prices (%tde="drugs" by default) */ + text = dpg_strdup_printf(_("Hey dude, the prices of %tde here are:"), + Names.Drugs); + mvaddstr(get_ui_area_top(), 1, text); + g_free(text); + for (c = 0, i = GetNextDrugIndex(-1, Play); + c < NumDrugsHere && i != -1; + c++, i = GetNextDrugIndex(i, Play)) { + /* List of individual drug names for selection (%tde="Opium" etc. + * by default) */ + text = dpg_strdup_printf( _("%c. %-10tde %8P"), 'A' + c, + Drug[i].Name, Play->Drugs[i].Price); + names = g_slist_append(names, text); + } + display_select_list(names); + attrset(PromptAttr); +} + /* * Loop which handles the user playing an interactive game (i.e. "Play" * is a client connected to a server, either locally or remotely) t@@ -2186,7 +2291,6 @@ static void Curses_DoGame(Player *Play) gchar *pt; gboolean justconnected = FALSE; #endif - int NumDrugsHere; int MaxSock; char HaveWorthless; Player *tmp; t@@ -2214,9 +2318,8 @@ static void Curses_DoGame(Player *Play) buf = NULL; do { g_free(buf); - buf = - nice_input(_("Hey dude, what's your name? "), 17, 1, FALSE, - OldName, '\0'); + buf = nice_input(_("Hey dude, what's your name? "), get_ui_area_top() + 1, + 1, FALSE, OldName, '\0'); } while (buf[0] == 0); #if NETWORKING if (WantNetwork) { t@@ -2249,32 +2352,14 @@ static void Curses_DoGame(Player *Play) for (i = 0; i < NumDrug; i++) { if (Play->Drugs[i].Carried > 0) { IsCarrying = 1; - if (Play->Drugs[i].Price == 0) + if (Play->Drugs[i].Price == 0) { HaveWorthless = 1; + } } } switch (DisplayMode) { case DM_STREET: - attrset(TextAttr); - NumDrugsHere = 0; - for (i = 0; i < NumDrug; i++) - if (Play->Drugs[i].Price > 0) - NumDrugsHere++; - clear_bottom(); - /* Display of drug prices (%tde="drugs" by default) */ - dpg_string_sprintf(text, _("Hey dude, the prices of %tde here are:"), - Names.Drugs); - mvaddstr(16, 1, text->str); - for (c = 0, i = GetNextDrugIndex(-1, Play); - c < NumDrugsHere && i != -1; - c++, i = GetNextDrugIndex(i, Play)) { - /* List of individual drug names for selection (%tde="Opium" etc. - * by default) */ - dpg_string_sprintf(text, _("%c. %-10tde %8P"), 'A' + c, - Drug[i].Name, Play->Drugs[i].Price); - mvaddstr(17 + c / 3, (c % 3) * 25 + 4, text->str); - } - attrset(PromptAttr); + DisplayDrugsHere(Play); /* Prompts for "normal" actions in curses client */ g_string_assign(text, _("Will you B>uy")); if (IsCarrying) t@@ -2294,7 +2379,7 @@ static void Curses_DoGame(Player *Play) g_string_append(text, _(", J>et")); } g_string_append(text, _(", or Q>uit? ")); - mvaddcentstr(22, text->str); + mvaddcentstr(get_prompt_line(), text->str); attrset(TextAttr); curs_set(1); break; t@@ -2316,7 +2401,7 @@ static void Curses_DoGame(Player *Play) /* (%tde = "drugs" by default here) */ dpg_string_sprintfa(text, _("D>eal %tde, "), Names.Drugs); g_string_append(text, _("or Q>uit? ")); - mvaddcentstr(22, text->str); + mvaddcentstr(get_prompt_line(), text->str); attrset(TextAttr); curs_set(1); break; t@@ -2329,7 +2414,7 @@ static void Curses_DoGame(Player *Play) g_string_append(text, Names.Drugs); g_string_append(text, ", or Q>uit? "); attrset(PromptAttr); - mvaddcentstr(22, text->str); + mvaddcentstr(get_prompt_line(), text->str); attrset(TextAttr); curs_set(1); break; t@@ -2378,9 +2463,10 @@ static void Curses_DoGame(Player *Play) } if (!DoneOK) { attrset(TextAttr); - clear_line(22); - mvaddstr(22, 0, _("Connection to server lost! " - "Reverting to single player mode")); + clear_line(get_prompt_line()); + mvaddstr(get_prompt_line(), 0, + _("Connection to server lost! " + "Reverting to single player mode")); nice_wait(); SwitchToSinglePlayer(Play); print_status(Play, TRUE); t@@ -2441,7 +2527,8 @@ static void Curses_DoGame(Player *Play) } else if (c == 'L') { if (Network) { attrset(PromptAttr); - mvaddstr(23, 20, _("List what? P>layers or S>cores? ")); + mvaddstr(get_prompt_line() + 1, 20, + _("List what? P>layers or S>cores? ")); /* P>layers, S>cores */ i = GetKey(_("PS"), "PS", TRUE, FALSE, FALSE); if (i == 'P') { t@@ -2460,9 +2547,10 @@ static void Curses_DoGame(Player *Play) "(talk privately to) ? ")); if (tmp) { attrset(TextAttr); - clear_line(22); + clear_line(get_prompt_line()); /* Prompt for sending player-player messages */ - TalkMsg = nice_input(_("Talk: "), 22, 0, FALSE, NULL, '\0'); + TalkMsg = nice_input(_("Talk: "), get_prompt_line(), 0, FALSE, + NULL, '\0'); if (TalkMsg[0]) { SendClientMessage(Play, C_NONE, C_MSGTO, tmp, TalkMsg); buf = g_strdup_printf("%s->%s: %s", GetPlayerName(Play), t@@ -2474,8 +2562,9 @@ static void Curses_DoGame(Player *Play) } } else if (c == 'T' && Client) { attrset(TextAttr); - clear_line(22); - TalkMsg = nice_input(_("Talk: "), 22, 0, FALSE, NULL, '\0'); + clear_line(get_prompt_line()); + TalkMsg = nice_input(_("Talk: "), get_prompt_line(), 0, + FALSE, NULL, '\0'); if (TalkMsg[0]) { SendClientMessage(Play, C_NONE, C_MSG, NULL, TalkMsg); buf = g_strdup_printf("%s: %s", GetPlayerName(Play), TalkMsg); t@@ -2587,7 +2676,7 @@ void CursesLoop(struct CMDLINE *cmdline) CleanUpServer(); RestoreConfig(); attrset(TextAttr); - mvaddstr(23, 20, _("Play again? ")); + mvaddstr(get_prompt_line() + 1, 20, _("Play again? ")); c = GetKey(_("YN"), "YN", TRUE, TRUE, FALSE); } while (c == 'Y'); FirstClient = RemovePlayer(Play, FirstClient);