Rulesave saves trade.type and trade.bonus correctly.
[freeciv.git] / client / messagewin_common.c
blob3c699ebb27a222d836ce163544dc3a48e3e80ab7
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 "messagewin_common.h"
36 #include "options.h"
37 #include "update_queue.h"
39 static struct message *messages = NULL;
40 static int messages_total = 0;
41 static int messages_alloc = 0;
43 /****************************************************************************
44 Update the message dialog if needed.
45 ****************************************************************************/
46 static void meswin_dialog_update(void)
48 if (!can_client_change_view()) {
49 return;
52 if (meswin_dialog_is_open()) {
53 update_queue_add(UQ_CALLBACK(real_meswin_dialog_update), NULL);
54 } else if (0 < messages_total
55 && (!client_has_player()
56 || !client.conn.playing->ai_controlled)) {
57 meswin_dialog_popup(FALSE);
61 /****************************************************************************
62 Clear all messages.
63 ****************************************************************************/
64 void meswin_clear(void)
66 int i;
68 for (i = 0; i < messages_total; i++) {
69 free(messages[i].descr);
70 messages[i].descr = NULL;
72 text_tag_list_destroy(messages[i].tags);
73 messages[i].tags = NULL;
75 messages_total = 0;
76 meswin_dialog_update();
79 /****************************************************************************
80 Add a message.
81 ****************************************************************************/
82 void meswin_add(const char *message, const struct text_tag_list *tags,
83 struct tile *ptile, enum event_type event)
85 const size_t min_msg_len = 50;
86 size_t msg_len = strlen(message);
87 char *s = fc_malloc(MAX(msg_len, min_msg_len) + 1);
88 int i, nspc;
90 if (messages_total + 2 > messages_alloc) {
91 messages_alloc = messages_total + 32;
92 messages = fc_realloc(messages, messages_alloc * sizeof(*messages));
95 strcpy(s, message);
97 nspc = min_msg_len - strlen(s);
98 if (nspc > 0) {
99 strncat(s, " ", nspc);
102 messages[messages_total].tile = ptile;
103 messages[messages_total].event = event;
104 messages[messages_total].descr = s;
105 messages[messages_total].tags = text_tag_list_copy(tags);
106 messages[messages_total].location_ok = (ptile != NULL);
107 messages[messages_total].visited = FALSE;
108 messages_total++;
110 /* Update the city_ok fields of all messages since the city may have
111 * changed owner. */
112 for (i = 0; i < messages_total; i++) {
113 if (messages[i].location_ok) {
114 struct city *pcity = tile_city(messages[i].tile);
116 messages[i].city_ok =
117 (pcity
118 && (!client_has_player()
119 || can_player_see_city_internals(client_player(), pcity)));
120 } else {
121 messages[i].city_ok = FALSE;
125 meswin_dialog_update();
128 /****************************************************************************
129 Returns the pointer to a message. Returns NULL on error.
130 ****************************************************************************/
131 const struct message *meswin_get_message(int message_index)
133 if (message_index >= 0 && message_index < messages_total) {
134 return &messages[message_index];
135 } else {
136 /* Can happen in turn change... */
137 return NULL;
141 /****************************************************************************
142 Returns the number of message in the window.
143 ****************************************************************************/
144 int meswin_get_num_messages(void)
146 return messages_total;
149 /****************************************************************************
150 Sets the visited-state of a message
151 ****************************************************************************/
152 void meswin_set_visited_state(int message_index, bool state)
154 fc_assert_ret(0 <= message_index && message_index < messages_total);
156 messages[message_index].visited = state;
159 /****************************************************************************
160 Called from messagewin.c if the user clicks on the popup-city button.
161 ****************************************************************************/
162 void meswin_popup_city(int message_index)
164 fc_assert_ret(0 <= message_index && message_index < messages_total);
166 if (messages[message_index].city_ok) {
167 struct tile *ptile = messages[message_index].tile;
168 struct city *pcity = tile_city(ptile);
170 if (gui_options.center_when_popup_city) {
171 center_tile_mapcanvas(ptile);
174 if (pcity && can_player_see_units_in_city(client.conn.playing, pcity)) {
175 /* If the event was the city being destroyed, pcity will be NULL
176 * and we'd better not try to pop it up. It's also possible that
177 * events will happen on enemy cities; we generally don't want to pop
178 * those dialogs up either (although it's hard to be certain).
180 * In both cases, it would be better if the popup button weren't
181 * highlighted at all - this is left up to the GUI. */
182 popup_city_dialog(pcity);
187 /**************************************************************************
188 Called from messagewin.c if the user clicks on the goto button.
189 **************************************************************************/
190 void meswin_goto(int message_index)
192 fc_assert_ret(0 <= message_index && message_index < messages_total);
194 if (messages[message_index].location_ok) {
195 center_tile_mapcanvas(messages[message_index].tile);
199 /****************************************************************************
200 Called from messagewin.c if the user double clicks on a message.
201 ****************************************************************************/
202 void meswin_double_click(int message_index)
204 fc_assert_ret(0 <= message_index && message_index < messages_total);
206 if (messages[message_index].city_ok
207 && is_city_event(messages[message_index].event)) {
208 meswin_popup_city(message_index);
209 } else if (messages[message_index].location_ok) {
210 meswin_goto(message_index);