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)
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 ***********************************************************************/
15 #include <fc_config.h>
25 #include "featured_text.h"
29 #include "citydlg_g.h"
30 #include "mapview_g.h"
31 #include "messagewin_g.h"
34 #include "client_main.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()) {
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 /****************************************************************************
64 ****************************************************************************/
65 void meswin_clear_older(int turn
, int phase
)
70 if (!gui_options
.show_previous_turn_messages
) {
71 turn
= MESWIN_CLEAR_ALL
;
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
);
87 for (; i
< messages_total
; i
++, j
++) {
88 messages
[j
] = messages
[i
];
94 meswin_dialog_update();
97 /****************************************************************************
99 ****************************************************************************/
100 void meswin_add(const char *message
, const struct text_tag_list
*tags
,
101 struct tile
*ptile
, enum event_type event
,
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);
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
));
118 nspc
= min_msg_len
- strlen(s
);
120 strncat(s
, " ", nspc
);
126 msg
->tags
= text_tag_list_copy(tags
);
127 msg
->location_ok
= (ptile
!= NULL
);
128 msg
->visited
= FALSE
;
131 messages
[messages_total
++] = msg
;
133 /* Update the city_ok fields of all messages since the city may have
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
=
141 && (!client_has_player()
142 || can_player_see_city_internals(client_player(), pcity
)));
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
];
159 /* Can happen in turn change... */
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
);