1 /* NetHack may be freely redistributed. See license for details. */
2
3 #include "vulture_sdl.h" /* XXX this must be the first include,
4 no idea why but it won't compile otherwise */
5
6 extern "C" {
7 #include "hack.h"
8 }
9
10 #include "vulture_main.h"
11 #include "vulture_win.h"
12 #include "vulture_txt.h"
13 #include "vulture_gra.h"
14 #include "vulture_opt.h"
15 #include "vulture_mou.h"
16
17 #include "messagewin.h"
18 #include "levelwin.h"
19
20
21 messagewin *msgwin;
22 static Uint32 message_colors[V_MAX_MESSAGE_COLORS];
23
24
messagewin(window * p)25 messagewin::messagewin(window *p) : window(p)
26 {
27 int i;
28 Uint32 color;
29
30 v_type = V_WINTYPE_CUSTOM;
31
32 bg_img = SDL_CreateRGBSurface(SDL_SWSURFACE, 40, 20, 32,
33 vulture_px_format->Rmask,
34 vulture_px_format->Gmask,
35 vulture_px_format->Bmask, 0);
36 SDL_FillRect(bg_img, NULL, CLR32_BLACK);
37 SDL_SetAlpha(bg_img, SDL_SRCALPHA, 128);
38
39 /* init message ring buffer */
40 memset(message_ages, 0, V_MESSAGEBUF_SIZE * sizeof(int));
41 message_top = -1;
42 message_cur = -1;
43
44 msgwin = this;
45
46 /* Set message shading */
47 for (i = 0; i < V_MAX_MESSAGE_COLORS; i++) {
48 color = 255 - (i * 11);
49 message_colors[i] = SDL_MapRGB(vulture_px_format, color, color, color);
50 }
51 }
52
53
54
~messagewin(void)55 messagewin::~messagewin(void)
56 {
57 SDL_FreeSurface(bg_img);
58 }
59
60
61
draw()62 bool messagewin::draw()
63 {
64 int age, textlen, num_messages;
65 int pos_x, pos_y, i;
66 std::string message;
67 int refresh_x, refresh_y, refresh_h, refresh_w;
68 int time_cur = moves;
69
70 if (getshown() != 0)
71 /* set time_cur to the age of the first shown message */
72 get_message(0, &time_cur);
73
74 refresh_x = refresh_y = 99999;
75 refresh_h = refresh_w = 0;
76
77 /* repaint background and free it */
78 if (background) {
79 vulture_put_img(abs_x, abs_y, background);
80 SDL_FreeSurface(background);
81 background = NULL;
82
83 /* we need these values, so that we can refresh the larger
84 * even if the window shrinks during the redraw */
85 refresh_x = abs_x;
86 refresh_y = abs_y;
87 refresh_w = w;
88 refresh_h = h;
89 }
90
91 num_messages = 0;
92 h = 0;
93 w = 0;
94
95 /* calculate height & width of new message area */
96 while(!(message = get_message(num_messages, &age)).empty() &&
97 (time_cur-age) < V_MAX_MESSAGE_COLORS && num_messages < vulture_opts.messagelines)
98 {
99 h += (vulture_get_lineheight(V_FONT_MESSAGE) + 1);
100 textlen = vulture_text_length(V_FONT_MESSAGE, message);
101 w = (w < textlen) ? textlen : w;
102 num_messages++;
103 }
104
105 /* add a bit of padding around the text */
106 h += 2;
107 w += 4;
108
109 x = (parent->w - w) / 2;
110 abs_x = parent->abs_x + x;
111 abs_y = parent->abs_y;
112
113 /* save new background */
114 background = vulture_get_img(abs_x, abs_y,
115 abs_x + w-1, abs_y + h-1);
116
117
118 /* shade the message area */
119 vulture_set_draw_region(abs_x, abs_y,
120 abs_x + w-1, abs_y + h-1);
121 pos_y = abs_y;
122 while (pos_y <= abs_y + h) {
123 pos_x = abs_x;
124
125 while (pos_x <= abs_x+w) {
126 vulture_put_img(pos_x, pos_y, bg_img);
127 pos_x += bg_img->w;
128 }
129 pos_y += bg_img->h;
130 }
131 vulture_set_draw_region(0, 0, vulture_screen->w-1, vulture_screen->h-1);
132
133
134 /* draw the messages */
135 for (i = 0; i < num_messages; i++) {
136 message = get_message(num_messages - i - 1, &age);
137
138 pos_x = abs_x + (w - vulture_text_length(V_FONT_MESSAGE, message)) / 2;
139 pos_y = abs_y + i * (vulture_get_lineheight(V_FONT_MESSAGE) + 1);
140 vulture_put_text(V_FONT_MESSAGE, message, vulture_screen,
141 pos_x, pos_y, message_colors[time_cur-age]);
142 }
143
144 refresh_w = (refresh_w > w) ? refresh_w : w;
145 refresh_h = (refresh_h > h) ? refresh_h : h;
146
147 if (refresh_x > abs_x)
148 {
149 refresh_w += refresh_x - abs_x;
150 refresh_x = abs_x;
151 }
152 refresh_y = (refresh_y < abs_y) ? refresh_y : abs_y;
153
154 vulture_invalidate_region(refresh_x, refresh_y, refresh_w, refresh_h);
155
156 return false;
157 }
158
159
handle_mousemotion_event(window * target,void * result,int xrel,int yrel,int state)160 eventresult messagewin::handle_mousemotion_event(window* target, void* result,
161 int xrel, int yrel, int state)
162 {
163 point mouse = vulture_get_mouse_pos();
164 window *new_target = levwin->get_window_from_point(mouse);
165
166 return levwin->handle_mousemotion_event(new_target, result, xrel, yrel, state);
167 }
168
169
handle_mousebuttonup_event(window * target,void * result,int mouse_x,int mouse_y,int button,int state)170 eventresult messagewin::handle_mousebuttonup_event(window* target, void* result,
171 int mouse_x, int mouse_y, int button, int state)
172 {
173 point mouse = vulture_get_mouse_pos();
174 window *new_target = levwin->get_window_from_point(mouse);
175
176 return levwin->handle_mousebuttonup_event(new_target, result, mouse_x, mouse_y, button, state);
177 }
178
179
add_message(std::string str)180 void messagewin::add_message(std::string str)
181 {
182 message_cur = message_top = (message_top + 1) % V_MESSAGEBUF_SIZE;
183 message_buf[message_top] = str;
184 message_ages[message_top] = moves;
185 }
186
187
setshown(int first)188 void messagewin::setshown(int first)
189 {
190 message_cur = (message_top - first + V_MESSAGEBUF_SIZE) % V_MESSAGEBUF_SIZE;
191 }
192
193
getshown()194 int messagewin::getshown()
195 {
196 return (message_top - message_cur + V_MESSAGEBUF_SIZE) % V_MESSAGEBUF_SIZE;
197 }
198
199
200 /* retrieve a message from the message buffer, offset messages before the current one */
get_message(int offset,int * age)201 std::string messagewin::get_message(int offset, int *age)
202 {
203 if (offset < V_MESSAGEBUF_SIZE)
204 {
205 int msg_id = (message_cur - offset + V_MESSAGEBUF_SIZE) % V_MESSAGEBUF_SIZE;
206
207 if (message_ages[msg_id])
208 {
209 *age = message_ages[msg_id];
210 return message_buf[msg_id];
211 }
212 }
213
214 *age = 0;
215 return "";
216 }
217
218
view_all(void)219 void messagewin::view_all(void)
220 {
221 int offset, time, winid;
222 std::string message;
223 char menuline[256];
224
225 winid = vulture_create_nhwindow(NHW_MENU);
226
227 offset = -getshown();
228 while ( !(message = get_message(offset, &time)).empty() )
229 {
230 sprintf(menuline, "T:%d %s", time, message.c_str());
231 vulture_putstr(winid, ATR_NONE, menuline);
232 offset++;
233 }
234
235 /* Display the messages */
236 vulture_display_nhwindow(winid, TRUE);
237
238 /* Clean up */
239 vulture_destroy_nhwindow(winid);
240 }
241
242