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