Stop sharing requirement_unit_state_ereq().
[freeciv.git] / client / messagewin_common.c
blob3d76e2084285f052b8064546115f24a4c58b001a
1 /**********************************************************************
2 Freeciv - Copyright (C) 2002 - R. Falke
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <string.h>
20 /* utility */
21 #include "fcintl.h"
22 #include "mem.h"
24 /* common */
25 #include "featured_text.h"
26 #include "map.h"
28 /* client/include */
29 #include "citydlg_g.h"
30 #include "mapview_g.h"
31 #include "messagewin_g.h"
33 /* client */
34 #include "client_main.h"
35 #include "options.h"
36 #include "update_queue.h"
38 #include "messagewin_common.h"
40 static struct message **messages = NULL;
41 static int messages_total = 0;
42 static int messages_alloc = 0;
44 /****************************************************************************
45 Update the message dialog if needed.
46 ****************************************************************************/
47 static void meswin_dialog_update(void)
49 if (!can_client_change_view()) {
50 return;
53 if (meswin_dialog_is_open()) {
54 update_queue_add(UQ_CALLBACK(real_meswin_dialog_update), NULL);
55 } else if (0 < messages_total
56 && (!client_has_player()
57 || is_human(client.conn.playing))) {
58 meswin_dialog_popup(FALSE);
62 /****************************************************************************
63 Clear all messages.
64 ****************************************************************************/
65 void meswin_clear_older(int turn, int phase)
67 int i;
68 int j = 0;
70 if (!gui_options.show_previous_turn_messages) {
71 turn = MESWIN_CLEAR_ALL;
74 for (i = 0;
75 i < messages_total
76 && (turn < 0
77 || (messages[i]->turn < turn
78 || (messages[i]->turn == turn && messages[i]->phase < phase))) ; i++) {
79 free(messages[i]->descr);
81 text_tag_list_destroy(messages[i]->tags);
82 free(messages[i]);
83 messages[i] = NULL;
86 if (i != 0) {
87 for (; i < messages_total; i++, j++) {
88 messages[j] = messages[i];
89 messages[i] = NULL;
91 messages_total = j;
94 meswin_dialog_update();
97 /****************************************************************************
98 Add a message.
99 ****************************************************************************/
100 void meswin_add(const char *message, const struct text_tag_list *tags,
101 struct tile *ptile, enum event_type event,
102 int turn, int phase)
104 const size_t min_msg_len = 50;
105 size_t msg_len = strlen(message);
106 char *s = fc_malloc(MAX(msg_len, min_msg_len) + 1);
107 int i, nspc;
108 struct message *msg;
110 if (messages_total + 2 > messages_alloc) {
111 messages_alloc = messages_total + 32;
112 messages = fc_realloc(messages, messages_alloc * sizeof(struct message *));
115 msg = fc_malloc(sizeof(struct message));
116 strcpy(s, message);
118 nspc = min_msg_len - strlen(s);
119 if (nspc > 0) {
120 strncat(s, " ", nspc);
123 msg->tile = ptile;
124 msg->event = event;
125 msg->descr = s;
126 msg->tags = text_tag_list_copy(tags);
127 msg->location_ok = (ptile != NULL);
128 msg->visited = FALSE;
129 msg->turn = turn;
130 msg->phase = phase;
131 messages[messages_total++] = msg;
133 /* Update the city_ok fields of all messages since the city may have
134 * changed owner. */
135 for (i = 0; i < messages_total; i++) {
136 if (messages[i]->location_ok) {
137 struct city *pcity = tile_city(messages[i]->tile);
139 messages[i]->city_ok =
140 (pcity
141 && (!client_has_player()
142 || can_player_see_city_internals(client_player(), pcity)));
143 } else {
144 messages[i]->city_ok = FALSE;
148 meswin_dialog_update();
151 /****************************************************************************
152 Returns the pointer to a message. Returns NULL on error.
153 ****************************************************************************/
154 const struct message *meswin_get_message(int message_index)
156 if (message_index >= 0 && message_index < messages_total) {
157 return messages[message_index];
158 } else {
159 /* Can happen in turn change... */
160 return NULL;
164 /****************************************************************************
165 Returns the number of message in the window.
166 ****************************************************************************/
167 int meswin_get_num_messages(void)
169 return messages_total;
172 /****************************************************************************
173 Sets the visited-state of a message
174 ****************************************************************************/
175 void meswin_set_visited_state(int message_index, bool state)
177 fc_assert_ret(0 <= message_index && message_index < messages_total);
179 messages[message_index]->visited = state;
182 /****************************************************************************
183 Called from messagewin.c if the user clicks on the popup-city button.
184 ****************************************************************************/
185 void meswin_popup_city(int message_index)
187 fc_assert_ret(0 <= message_index && message_index < messages_total);
189 if (messages[message_index]->city_ok) {
190 struct tile *ptile = messages[message_index]->tile;
191 struct city *pcity = tile_city(ptile);
193 if (gui_options.center_when_popup_city) {
194 center_tile_mapcanvas(ptile);
197 if (pcity && can_player_see_units_in_city(client.conn.playing, pcity)) {
198 /* If the event was the city being destroyed, pcity will be NULL
199 * and we'd better not try to pop it up. It's also possible that
200 * events will happen on enemy cities; we generally don't want to pop
201 * those dialogs up either (although it's hard to be certain).
203 * In both cases, it would be better if the popup button weren't
204 * highlighted at all - this is left up to the GUI. */
205 popup_city_dialog(pcity);
210 /**************************************************************************
211 Called from messagewin.c if the user clicks on the goto button.
212 **************************************************************************/
213 void meswin_goto(int message_index)
215 fc_assert_ret(0 <= message_index && message_index < messages_total);
217 if (messages[message_index]->location_ok) {
218 center_tile_mapcanvas(messages[message_index]->tile);
222 /****************************************************************************
223 Called from messagewin.c if the user double clicks on a message.
224 ****************************************************************************/
225 void meswin_double_click(int message_index)
227 fc_assert_ret(0 <= message_index && message_index < messages_total);
229 if (messages[message_index]->city_ok
230 && is_city_event(messages[message_index]->event)) {
231 meswin_popup_city(message_index);
232 } else if (messages[message_index]->location_ok) {
233 meswin_goto(message_index);