1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
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.
7
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 ***********************************************************************/
13
14 /**********************************************************************
15 messagewin.c - description
16 -------------------
17 begin : Feb 2 2003
18 copyright : (C) 2003 by Rafał Bursig
19 email : Rafał Bursig <bursig@poczta.fm>
20 **********************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 #include <fc_config.h>
24 #endif
25
26 /* SDL2 */
27 #ifdef SDL2_PLAIN_INCLUDE
28 #include <SDL.h>
29 #else /* SDL2_PLAIN_INCLUDE */
30 #include <SDL2/SDL.h>
31 #endif /* SDL2_PLAIN_INCLUDE */
32
33 /* utility */
34 #include "fcintl.h"
35 #include "log.h"
36
37 /* client */
38 #include "options.h"
39
40 /* gui-sdl2 */
41 #include "citydlg.h"
42 #include "colors.h"
43 #include "graphics.h"
44 #include "gui_id.h"
45 #include "gui_main.h"
46 #include "gui_tilespec.h"
47 #include "mapview.h"
48 #include "themespec.h"
49 #include "unistring.h"
50 #include "utf8string.h"
51 #include "widget.h"
52
53 #include "messagewin.h"
54
55
56 #ifdef SMALL_SCREEN
57 #define N_MSG_VIEW 3 /* max before scrolling happens */
58 #else
59 #define N_MSG_VIEW 6
60 #endif
61
62 #define PTSIZE_LOG_FONT adj_font(10)
63
64 static struct ADVANCED_DLG *pMsg_Dlg = NULL;
65
66 /**************************************************************************
67 Called from default clicks on a message.
68 **************************************************************************/
msg_callback(struct widget * pWidget)69 static int msg_callback(struct widget *pWidget)
70 {
71 if (PRESSED_EVENT(Main.event)) {
72 int message_index = *(int*)pWidget->data.ptr;
73
74 pWidget->string_utf8->fgcol = *get_theme_color(COLOR_THEME_MESWIN_ACTIVE_TEXT2);
75 unselect_widget_action();
76
77 meswin_double_click(message_index);
78 meswin_set_visited_state(message_index, TRUE);
79 }
80
81 return -1;
82 }
83
84 /**************************************************************************
85 Called from default clicks on a messages window.
86 **************************************************************************/
move_msg_window_callback(struct widget * pWindow)87 static int move_msg_window_callback(struct widget *pWindow)
88 {
89 if (PRESSED_EVENT(Main.event)) {
90 move_window_group(pMsg_Dlg->pBeginWidgetList, pWindow);
91 }
92
93 return -1;
94 }
95
96 /* ======================================================================
97 Public
98 ====================================================================== */
99
100 /**************************************************************************
101 Really update message window.
102 **************************************************************************/
real_meswin_dialog_update(void * unused)103 void real_meswin_dialog_update(void *unused)
104 {
105 int msg_count;
106 int current_count;
107 const struct message *pMsg = NULL;
108 struct widget *pBuf = NULL, *pWindow = NULL;
109 utf8_str *pstr = NULL;
110 SDL_Rect area = {0, 0, 0, 0};
111 bool create;
112 int label_width;
113
114 if (pMsg_Dlg == NULL) {
115 meswin_dialog_popup(TRUE);
116 }
117
118 msg_count = meswin_get_num_messages();
119 current_count = pMsg_Dlg->pScroll->count;
120
121 if (current_count > 0) {
122 undraw_group(pMsg_Dlg->pBeginActiveWidgetList, pMsg_Dlg->pEndActiveWidgetList);
123 del_group_of_widgets_from_gui_list(pMsg_Dlg->pBeginActiveWidgetList,
124 pMsg_Dlg->pEndActiveWidgetList);
125 pMsg_Dlg->pBeginActiveWidgetList = NULL;
126 pMsg_Dlg->pEndActiveWidgetList = NULL;
127 pMsg_Dlg->pActiveWidgetList = NULL;
128 /* hide scrollbar */
129 hide_scrollbar(pMsg_Dlg->pScroll);
130 pMsg_Dlg->pScroll->count = 0;
131 current_count = 0;
132 }
133 create = (current_count == 0);
134
135 pWindow = pMsg_Dlg->pEndWidgetList;
136
137 area = pWindow->area;
138
139 label_width = area.w - pMsg_Dlg->pScroll->pUp_Left_Button->size.w - adj_size(3);
140
141 if (msg_count > 0) {
142 for (; current_count < msg_count; current_count++) {
143 pMsg = meswin_get_message(current_count);
144 pstr = create_utf8_from_char(pMsg->descr, PTSIZE_LOG_FONT);
145
146 if (convert_utf8_str_to_const_surface_width(pstr, label_width - adj_size(10))) {
147 /* string must be divided to fit into the given area */
148 utf8_str *pstr2;
149 char **utf8_texts = create_new_line_utf8strs(pstr->text);
150 int count = 0;
151
152 while (utf8_texts[count]) {
153 pstr2 = create_utf8_str(utf8_texts[count],
154 strlen(utf8_texts[count]) + 1, PTSIZE_LOG_FONT);
155
156 pBuf = create_iconlabel(NULL, pWindow->dst, pstr2,
157 (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE|WF_FREE_DATA));
158
159 /* this block is duplicated in the "else" branch */
160 {
161 pBuf->string_utf8->bgcol = (SDL_Color) {0, 0, 0, 0};
162
163 pBuf->size.w = label_width;
164 pBuf->data.ptr = fc_calloc(1, sizeof(int));
165 *(int*)pBuf->data.ptr = current_count;
166 pBuf->action = msg_callback;
167 if (pMsg->tile) {
168 set_wstate(pBuf, FC_WS_NORMAL);
169 if (pMsg->visited) {
170 pBuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_MESWIN_ACTIVE_TEXT2);
171 } else {
172 pBuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_MESWIN_ACTIVE_TEXT);
173 }
174 }
175
176 pBuf->ID = ID_LABEL;
177
178 widget_set_area(pBuf, area);
179
180 /* add to widget list */
181 if (create) {
182 add_widget_to_vertical_scroll_widget_list(pMsg_Dlg, pBuf, pWindow, FALSE,
183 area.x, area.y);
184 create = FALSE;
185 } else {
186 add_widget_to_vertical_scroll_widget_list(pMsg_Dlg, pBuf,
187 pMsg_Dlg->pBeginActiveWidgetList,
188 FALSE, area.x, area.y);
189 }
190 }
191 count++;
192 } /* while */
193 FREEUTF8STR(pstr);
194 } else {
195 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
196 (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE|WF_FREE_DATA));
197
198 /* duplicated block */
199 {
200 pBuf->string_utf8->bgcol = (SDL_Color) {0, 0, 0, 0};
201
202 pBuf->size.w = label_width;
203 pBuf->data.ptr = fc_calloc(1, sizeof(int));
204 *(int*)pBuf->data.ptr = current_count;
205 pBuf->action = msg_callback;
206 if (pMsg->tile) {
207 set_wstate(pBuf, FC_WS_NORMAL);
208 if (pMsg->visited) {
209 pBuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_MESWIN_ACTIVE_TEXT2);
210 } else {
211 pBuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_MESWIN_ACTIVE_TEXT);
212 }
213 }
214
215 pBuf->ID = ID_LABEL;
216
217 widget_set_area(pBuf, area);
218
219 /* add to widget list */
220 if (create) {
221 add_widget_to_vertical_scroll_widget_list(pMsg_Dlg, pBuf,
222 pWindow, FALSE,
223 area.x, area.y);
224 create = FALSE;
225 } else {
226 add_widget_to_vertical_scroll_widget_list(pMsg_Dlg, pBuf,
227 pMsg_Dlg->pBeginActiveWidgetList,
228 FALSE, area.x, area.y);
229 }
230 }
231 } /* if */
232 } /* for */
233 } /* if */
234
235 redraw_group(pMsg_Dlg->pBeginWidgetList, pWindow, 0);
236 widget_flush(pWindow);
237 }
238
239 /**************************************************************************
240 Popup (or raise) the message dialog; typically triggered by 'F9'.
241 **************************************************************************/
meswin_dialog_popup(bool raise)242 void meswin_dialog_popup(bool raise)
243 {
244 utf8_str *pstr;
245 struct widget *pWindow = NULL;
246 SDL_Surface *pBackground;
247 SDL_Rect area;
248 SDL_Rect size;
249
250 if (pMsg_Dlg) {
251 return;
252 }
253
254 pMsg_Dlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
255
256 /* create window */
257 pstr = create_utf8_from_char(_("Messages"), adj_font(12));
258 pstr->style = TTF_STYLE_BOLD;
259
260 pWindow = create_window_skeleton(NULL, pstr, 0);
261
262 pWindow->action = move_msg_window_callback;
263 set_wstate(pWindow, FC_WS_NORMAL);
264 add_to_gui_list(ID_CHATLINE_WINDOW, pWindow);
265
266 pMsg_Dlg->pEndWidgetList = pWindow;
267 pMsg_Dlg->pBeginWidgetList = pWindow;
268
269 /* create scrollbar */
270 create_vertical_scrollbar(pMsg_Dlg, 1, N_MSG_VIEW, TRUE, TRUE);
271
272 pstr = create_utf8_from_char("sample text", PTSIZE_LOG_FONT);
273
274 /* define content area */
275 area.w = (adj_size(520) - (pWindow->size.w - pWindow->area.w));
276 utf8_str_size(pstr, &size);
277 area.h = (N_MSG_VIEW + 1) * size.h;
278
279 FREEUTF8STR(pstr);
280
281 /* create window background */
282 pBackground = theme_get_background(theme, BACKGROUND_MESSAGEWIN);
283 if (resize_window(pWindow, pBackground, NULL,
284 (pWindow->size.w - pWindow->area.w) + area.w,
285 (pWindow->size.h - pWindow->area.h) + area.h)) {
286 FREESURFACE(pBackground);
287 }
288
289 area = pWindow->area;
290
291 setup_vertical_scrollbar_area(pMsg_Dlg->pScroll,
292 area.x + area.w, area.y,
293 area.h, TRUE);
294
295 hide_scrollbar(pMsg_Dlg->pScroll);
296
297 widget_set_position(pWindow, (main_window_width() - pWindow->size.w)/2, adj_size(25));
298
299 widget_redraw(pWindow);
300
301 real_meswin_dialog_update(NULL);
302 }
303
304 /****************************************************************************
305 Popdown the messages dialog; called by void popdown_all_game_dialogs(void)
306 ****************************************************************************/
meswin_dialog_popdown(void)307 void meswin_dialog_popdown(void)
308 {
309 if (pMsg_Dlg) {
310 popdown_window_group_dialog(pMsg_Dlg->pBeginWidgetList,
311 pMsg_Dlg->pEndWidgetList);
312 FC_FREE(pMsg_Dlg->pScroll);
313 FC_FREE(pMsg_Dlg);
314 }
315 }
316
317 /**************************************************************************
318 Return whether the message dialog is open.
319 **************************************************************************/
meswin_dialog_is_open(void)320 bool meswin_dialog_is_open(void)
321 {
322 return (pMsg_Dlg != NULL);
323 }
324