Atrinik Client  4.0
notification.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
38 #include <global.h>
39 #include <notification.h>
40 #include <toolkit/packet.h>
41 #include <toolkit/string.h>
42 
47 
52 {
53  if (!notification) {
54  return;
55  }
56 
57  if (notification->action) {
58  efree(notification->action);
59  }
60 
61  if (notification->shortcut) {
62  efree(notification->shortcut);
63  }
64 
65  efree(notification);
66  notification = NULL;
67  cur_widget[NOTIFICATION_ID]->show = 0;
68 }
69 
73 static void notification_action_do(void)
74 {
75  if (notification && notification->action) {
76  /* Macro or command? */
77  if (*notification->action == '?') {
78  keybind_process_command(notification->action);
79  } else {
80  send_command_check(notification->action);
81  }
82 
83  /* Done the action, destroy it... */
85  }
86 }
87 
95 int notification_keybind_check(const char *cmd)
96 {
97  if (notification && notification->action && notification->shortcut && !strcmp(notification->shortcut, cmd)) {
99  return 1;
100  }
101 
102  return 0;
103 }
104 
106 void socket_command_notification(uint8_t *data, size_t len, size_t pos)
107 {
108  int wd, ht;
109  char type, *cp;
110  SDL_Rect box;
111  StringBuffer *sb;
112  SDL_Color color;
113 
114  /* Destroy previous notification, if any. */
116  /* Show the widget... */
117  cur_widget[NOTIFICATION_ID]->show = 1;
118  SetPriorityWidget(cur_widget[NOTIFICATION_ID]);
119  /* Create the data structure and initialize default values. */
120  notification = ecalloc(1, sizeof(*notification));
121  notification->start_ticks = SDL_GetTicks();
122  notification->alpha = 255;
123  notification->delay = NOTIFICATION_DEFAULT_DELAY;
124  sb = stringbuffer_new();
125 
126  /* Parse the data. */
127  while (pos < len) {
128  type = packet_to_uint8(data, len, &pos);
129 
130  switch (type) {
132  {
133  char message[HUGE_BUF];
134 
135  packet_to_string(data, len, &pos, message, sizeof(message));
136  stringbuffer_append_string(sb, message);
137  break;
138  }
139 
141  {
142  char action[HUGE_BUF];
143 
144  packet_to_string(data, len, &pos, action, sizeof(action));
145  notification->action = estrdup(action);
146  break;
147  }
148 
150  {
151  char shortcut[HUGE_BUF];
152 
153  packet_to_string(data, len, &pos, shortcut, sizeof(shortcut));
154  notification->shortcut = estrdup(shortcut);
155  break;
156  }
157 
159  notification->delay = MAX(NOTIFICATION_DEFAULT_FADEOUT, packet_to_uint32(data, len, &pos));
160  break;
161 
162  default:
163  break;
164  }
165  }
166 
167  /* Shortcut specified, add the shortcut name to the notification
168  * message. */
169  if (notification->shortcut) {
170  keybind_struct *keybind = keybind_find_by_command(notification->shortcut);
171 
172  if (keybind) {
173  char key_buf[MAX_BUF];
174 
175  keybind_get_key_shortcut(keybind->key, keybind->mod, key_buf, sizeof(key_buf));
176  string_toupper(key_buf);
177  stringbuffer_append_printf(sb, " (click or [b]%s[/b])", key_buf);
178  }
179  } else if (notification->action) {
180  /* No shortcut, clicking is the best one can do... */
181  stringbuffer_append_string(sb, " (click)");
182  }
183 
184  cp = stringbuffer_finish(sb);
185 
186  /* Calculate the maximum height the text will need. */
187  box.x = 0;
188  box.y = 0;
190  box.h = 0;
192  ht = box.h;
193 
194  /* Calculate the maximum text width. */
195  box.h = 0;
197  wd = box.w;
198 
199  box.x = 0;
200  box.y = 0;
201  box.w = wd + 6;
202  box.h = ht + 6;
203 
204  /* Update the notification widget width/height. */
205  resize_widget(cur_widget[NOTIFICATION_ID], RESIZE_RIGHT, box.w);
206  resize_widget(cur_widget[NOTIFICATION_ID], RESIZE_BOTTOM, box.h);
207 
208  if (cur_widget[NOTIFICATION_ID]->surface) {
209  SDL_FreeSurface(cur_widget[NOTIFICATION_ID]->surface);
210  }
211 
212  /* Create a new surface. */
213  cur_widget[NOTIFICATION_ID]->surface = SDL_CreateRGBSurface(get_video_flags(), box.w, box.h, video_get_bpp(), 0, 0, 0, 0);
214 
215  /* Fill the surface with the background color. */
216  if (text_color_parse("e6e796", &color)) {
217  SDL_FillRect(cur_widget[NOTIFICATION_ID]->surface, &box, SDL_MapRGB(cur_widget[NOTIFICATION_ID]->surface->format, color.r, color.g, color.b));
218  }
219 
220  /* Create a border. */
221  border_create_color(cur_widget[NOTIFICATION_ID]->surface, &box, 1, "606060");
222 
223  /* Render the text. */
224  box.w = wd;
225  box.h = ht;
226  text_show(cur_widget[NOTIFICATION_ID]->surface, NOTIFICATION_DEFAULT_FONT, cp, 3, 3, COLOR_BLACK, TEXT_MARKUP | TEXT_WORD_WRAP, &box);
227 
228  efree(cp);
229 }
230 
232 static void widget_draw(widgetdata *widget)
233 {
234  SDL_Rect dst;
235 
236  /* Nothing to render... */
237  if (!notification) {
238  return;
239  }
240 
241  /* Update the widget's position to below map name. */
242  widget->x = cur_widget[MAPNAME_ID]->x;
243  widget->y = cur_widget[MAPNAME_ID]->y + cur_widget[MAPNAME_ID]->h;
244 
245  /* Check whether we should do fade out. */
246  if (SDL_GetTicks() - notification->start_ticks > notification->delay - NOTIFICATION_DEFAULT_FADEOUT) {
247  int fade;
248 
249  /* Calculate how far into the fading animation we are. */
250  fade = SDL_GetTicks() - notification->start_ticks - (notification->delay - NOTIFICATION_DEFAULT_FADEOUT);
251 
252  /* Completed the fading animation? */
253  if (fade > NOTIFICATION_DEFAULT_FADEOUT) {
255  return;
256  }
257 
258  /* Adjust the alpha value... */
259  notification->alpha = 255 * ((NOTIFICATION_DEFAULT_FADEOUT - fade) / (double) NOTIFICATION_DEFAULT_FADEOUT);
260  }
261 
262  dst.x = widget->x;
263  dst.y = widget->y;
264  SDL_SetAlpha(widget->surface, SDL_SRCALPHA, notification->alpha);
265  SDL_BlitSurface(widget->surface, NULL, ScreenSurface, &dst);
266 
267  /* Do highlight. */
268  if (widget_mouse_event.owner == widget && notification->action) {
269  filledRectAlpha(ScreenSurface, dst.x, dst.y, dst.x + widget->w, dst.y + widget->h, 0xffffff3c);
270  }
271 }
272 
274 static int widget_event(widgetdata *widget, SDL_Event *event)
275 {
276  if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_LEFT) {
278  return 1;
279  }
280 
281  return 0;
282 }
283 
288 {
289  widget->draw_func = widget_draw;
290  widget->event_func = widget_event;
291 }
#define COLOR_BLACK
Definition: text.h:323
#define TEXT_WORD_WRAP
Definition: text.h:226
int text_color_parse(const char *color_notation, SDL_Color *color)
Definition: text.c:603
void notification_destroy(void)
Definition: notification.c:51
#define CMD_NOTIFICATION_DELAY
Definition: notification.h:70
SDL_Surface * surface
Definition: widget.h:110
uint32_t get_video_flags(void)
Definition: video.c:365
#define NOTIFICATION_DEFAULT_FONT
Definition: notification.h:80
void widget_notification_init(widgetdata *widget)
Definition: notification.c:287
void text_show(SDL_Surface *surface, font_struct *font, const char *text, int x, int y, const char *color_notation, uint64_t flags, SDL_Rect *box)
Definition: text.c:1983
static void notification_action_do(void)
Definition: notification.c:73
void socket_command_notification(uint8_t *data, size_t len, size_t pos)
Definition: notification.c:106
#define CMD_NOTIFICATION_ACTION
Definition: notification.h:63
static int widget_event(widgetdata *widget, SDL_Event *event)
Definition: notification.c:274
SDL_Surface * ScreenSurface
Definition: main.c:47
#define TEXT_MARKUP
Definition: text.h:224
static notification_struct * notification
Definition: notification.c:46
int notification_keybind_check(const char *cmd)
Definition: notification.c:95
int video_get_bpp(void)
Definition: video.c:334
uint8_t show
Definition: widget.h:69
char * keybind_get_key_shortcut(SDLKey key, SDLMod mod, char *buf, size_t len)
Definition: keybind.c:336
widgetdata * cur_widget[TOTAL_SUBWIDGETS]
Definition: widget.c:75
SDLKey key
Definition: keybind.h:44
int x
Definition: widget.h:48
#define TEXT_HEIGHT
Definition: text.h:241
#define CMD_NOTIFICATION_SHORTCUT
Definition: notification.h:65
static void widget_draw(widgetdata *widget)
Definition: notification.c:232
#define NOTIFICATION_DEFAULT_DELAY
Definition: notification.h:82
int w
Definition: widget.h:54
int type
Data type.
Definition: network_graph.c:74
#define NOTIFICATION_DEFAULT_WIDTH
Definition: notification.h:78
int h
Definition: widget.h:57
keybind_struct * keybind_find_by_command(const char *cmd)
Definition: keybind.c:371
int send_command_check(const char *cmd)
Definition: menu.c:376
#define CMD_NOTIFICATION_TEXT
Definition: notification.h:61
widgetdata * owner
Definition: widget.h:360
#define NOTIFICATION_DEFAULT_FADEOUT
Definition: notification.h:84
void SetPriorityWidget(widgetdata *node)
Definition: widget.c:1788
widgetevent widget_mouse_event
Definition: widget.c:82
void border_create_color(SDL_Surface *surface, SDL_Rect *coords, int thickness, const char *color_notation)
Definition: sprite.c:1359
#define TEXT_MAX_WIDTH
Definition: text.h:277
int keybind_process_command(const char *cmd)
Definition: keybind.c:553
SDLMod mod
Definition: keybind.h:47
int y
Definition: widget.h:51