Freeciv21
Develop your civilization from humble roots to a global empire
messagewin_common.cpp
Go to the documentation of this file.
1 /* ,%%%%%%%, ***************************************
2  ,%%/\%%%%/\%, Copyright (c) 1996-2023 Freeciv21 and Freeciv
3  ,%%%\c "" J/%%, contributors. This file is part of Freeciv21.
4  %%%%/ d b \%%% Freeciv21 is free software: you can redistribute it
5  %%%% _ |%%% and/or modify it under the terms of the GNU General
6  `%%%%(=_Y_=)%%' Public License as published by the Free Software
7  `%%%%`\7/%%%' Foundation, either version 3 of the License,
8  `%%%%%%%' or (at your option) any later version. You should
9  have received a copy of the GNU General Public License along
10  with Freeciv21. If not, see https://www.gnu.org/licenses/.
11  */
12 
13 #include <cstring>
14 
15 // utility
16 #include "fcintl.h"
17 
18 // common
19 #include "featured_text.h"
20 /* client/include */
21 #include "citydlg_g.h"
22 #include "mapview_g.h"
23 
24 // client
25 #include "client_main.h"
26 #include "messagewin.h"
27 #include "messagewin_common.h"
28 #include "options.h"
29 #include "page_game.h"
30 #include "update_queue.h"
31 #include "views/view_map.h"
32 
33 static struct message **messages = nullptr;
34 static int messages_total = 0;
35 static int messages_alloc = 0;
36 
40 static void meswin_dialog_update()
41 {
42  if (!can_client_change_view()) {
43  return;
44  }
46 }
47 
52 {
53  int i;
54  int j = 0;
55 
58  }
59 
60  for (i = 0; i < messages_total
61  && (turn < 0
62  || (messages[i]->turn < turn
63  || (messages[i]->turn == turn
64  && messages[i]->phase < phase)));
65  i++) {
66  delete[] messages[i]->descr;
67 
68  text_tag_list_destroy(messages[i]->tags);
69  delete messages[i];
70  messages[i] = nullptr;
71  }
72 
73  if (i != 0) {
74  for (; i < messages_total; i++, j++) {
75  messages[j] = messages[i];
76  messages[i] = nullptr;
77  }
78  messages_total = j;
79  }
80 
82 }
83 
87 void meswin_add(const char *message, const struct text_tag_list *tags,
88  struct tile *ptile, enum event_type event, int turn,
89  int phase)
90 {
91  const size_t min_msg_len = 50;
92  size_t msg_len = qstrlen(message);
93 
94  char *s = new char[MAX(msg_len, min_msg_len) + 1];
95  int i, nspc;
96  struct message *msg;
97 
98  if (messages_total + 2 > messages_alloc) {
100  messages = static_cast<struct message **>(
101  fc_realloc(messages, messages_alloc * sizeof(struct message *)));
102  }
103 
104  msg = new struct message();
105  qstrcpy(s, message);
106 
107  nspc = min_msg_len - qstrlen(s);
108  if (nspc > 0) {
109  strncat(s, " ", nspc);
110  }
111 
112  msg->tile = ptile;
113  msg->event = event;
114  msg->descr = s;
115  msg->tags = text_tag_list_copy(tags);
116  msg->location_ok = (ptile != nullptr);
117  msg->visited = false;
118  msg->turn = turn;
119  msg->phase = phase;
120  messages[messages_total++] = msg;
121 
122  /* Update the city_ok fields of all messages since the city may have
123  * changed owner. */
124  for (i = 0; i < messages_total; i++) {
125  if (messages[i]->location_ok) {
126  struct city *pcity = tile_city(messages[i]->tile);
127 
128  messages[i]->city_ok =
129  (pcity
130  && (!client_has_player()
132  } else {
133  messages[i]->city_ok = false;
134  }
135  }
136 
138 }
139 
143 const struct message *meswin_get_message(int message_index)
144 {
145  if (message_index >= 0 && message_index < messages_total) {
146  return messages[message_index];
147  } else {
148  // Can happen in turn change...
149  return nullptr;
150  }
151 }
152 
157 
161 void meswin_set_visited_state(int message_index, bool state)
162 {
163  fc_assert_ret(0 <= message_index && message_index < messages_total);
164 
165  messages[message_index]->visited = state;
166 }
167 
171 void meswin_popup_city(int message_index)
172 {
173  fc_assert_ret(0 <= message_index && message_index < messages_total);
174 
175  if (messages[message_index]->city_ok) {
176  struct tile *ptile = messages[message_index]->tile;
177  struct city *pcity = tile_city(ptile);
178 
180  queen()->mapview_wdg->center_on_tile(ptile);
181  }
182 
183  if (pcity && can_player_see_units_in_city(client.conn.playing, pcity)) {
184  /* If the event was the city being destroyed, pcity will be nullptr
185  * and we'd better not try to pop it up. It's also possible that
186  * events will happen on enemy cities; we generally don't want to pop
187  * those dialogs up either (although it's hard to be certain).
188  *
189  * In both cases, it would be better if the popup button weren't
190  * highlighted at all - this is left up to the GUI. */
191  popup_city_dialog(pcity);
192  }
193  }
194 }
195 
199 void meswin_goto(int message_index)
200 {
201  fc_assert_ret(0 <= message_index && message_index < messages_total);
202 
203  if (messages[message_index]->location_ok) {
204  queen()->mapview_wdg->center_on_tile(messages[message_index]->tile);
205  }
206 }
void popup_city_dialog(struct city *pcity)
void center_on_tile(tile *tile, bool animate=true)
Centers the view on a tile.
Definition: view_map.cpp:197
map_view * mapview_wdg
Definition: page_game.h:81
static update_queue * uq()
void add(uq_callback_t callback, void *data)
bool client_has_player()
Either controlling or observing.
struct player * client_player()
Either controlling or observing.
struct civclient client
bool can_client_change_view()
Return TRUE if the client can change the view; i.e.
enum event_type event
Definition: events.cpp:68
#define text_tag_list_copy(tags)
#define fc_assert_ret(condition)
Definition: log.h:112
void real_meswin_dialog_update(void *unused)
Do the work of updating (populating) the message dialog.
Definition: messagewin.cpp:196
static void meswin_dialog_update()
Update the message dialog if needed.
void meswin_popup_city(int message_index)
Called from messagewin.c if the user clicks on the popup-city button.
void meswin_goto(int message_index)
Called from messagewin.c if the user clicks on the goto button.
void meswin_clear_older(int turn, int phase)
Clear all messages.
static int messages_alloc
static int messages_total
void meswin_add(const char *message, const struct text_tag_list *tags, struct tile *ptile, enum event_type event, int turn, int phase)
Add a message.
int meswin_get_num_messages()
Returns the number of message in the window.
static struct message ** messages
const struct message * meswin_get_message(int message_index)
Returns the pointer to a message.
void meswin_set_visited_state(int message_index, bool state)
Sets the visited-state of a message.
#define MESWIN_CLEAR_ALL
client_options * gui_options
Definition: options.cpp:74
pageGame * queen()
Return game instandce.
Definition: page_game.cpp:557
bool can_player_see_units_in_city(const struct player *pplayer, const struct city *pcity)
Return TRUE iff the player can see units in the city.
Definition: player.cpp:1045
bool can_player_see_city_internals(const struct player *pplayer, const struct city *pcity)
Return TRUE iff the player can see the city's internals.
Definition: player.cpp:1060
#define MAX(x, y)
Definition: shared.h:48
Definition: city.h:291
struct connection conn
Definition: client_main.h:89
bool show_previous_turn_messages
Definition: options.h:92
bool center_when_popup_city
Definition: options.h:91
struct player * playing
Definition: connection.h:142
char * descr
enum event_type event
struct text_tag_list * tags
bool location_ok
struct tile * tile
Definition: tile.h:42
#define fc_realloc(ptr, sz)
Definition: support.h:59
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72