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 	extern "C" short glyph2tile[];
10 }
11 
12 #include "vulture_gra.h"
13 #include "vulture_gfl.h"
14 #include "vulture_win.h"
15 #include "vulture_txt.h"
16 #include "vulture_mou.h"
17 #include "vulture_tile.h"
18 
19 #include "map.h"
20 #include "hotspot.h"
21 #include "levelwin.h"
22 #include "textwin.h"
23 #include "mapdata.h"
24 
25 #define SYMBOL_WIDTH   7
26 #define SYMBOL_HEIGHT 14
27 
28 window *mapwin = NULL;
29 
30 
map(levelwin * p,mapdata * data)31 map::map(levelwin *p, mapdata *data) : window(p), map_data(data)
32 {
33 	int i;
34 	SDL_Surface *image;
35 
36 	v_type = V_WINTYPE_MAP;
37 	autobg = 1;
38 	need_redraw = 1;
39 	w = 640;
40 	h = 480;
41 	x = (parent->w - w) / 2;
42 	y = (parent->h - h) / 2;
43 	abs_x = parent->abs_x + x;
44 	abs_y = parent->abs_y + y;
45 
46 	/* Load map parchment */
47 	mapbg = vulture_load_graphic(V_FILENAME_MAP_PARCHMENT);
48 
49 	/* level title */
50 	textwin *txt = new textwin(this, "");
51 	txt->x = w/2;
52 	txt->y = 48;
53 
54 	/* close button */
55 	hotspot *close = new hotspot(this, 598, 11, 28, 24, 1, "Close map");
56 	close->abs_x = abs_x + close->x;
57 	close->abs_y = abs_y + close->y;
58 
59 	/* Load map symbols */
60 	image = vulture_load_graphic(V_FILENAME_MAP_SYMBOLS);
61 	if (image == NULL)
62 		return;
63 	else {
64 		for (i = 0; i < V_MAX_MAP_SYMBOLS; i++)
65 			map_symbols[i] = vulture_get_img_src(
66 				(i%40)*SYMBOL_WIDTH,
67 				(i/40)*SYMBOL_HEIGHT,
68 				(i%40)*SYMBOL_WIDTH + (SYMBOL_WIDTH - 1),
69 				(i/40)*SYMBOL_HEIGHT+ (SYMBOL_HEIGHT - 1),
70 				image);
71 		SDL_FreeSurface(image);
72 	}
73 }
74 
~map()75 map::~map()
76 {
77 	int i;
78 
79 	/* free the map symbols */
80 	for (i = 0; i < V_MAX_MAP_SYMBOLS; i++)
81 		SDL_FreeSurface(map_symbols[i]);
82 
83 	SDL_FreeSurface(mapbg);
84 }
85 
draw()86 bool map::draw()
87 {
88 	int map_x, map_y;
89 	int i, j;
90 	window * txt = first_child;
91 	char buffer[256];
92 
93 	/* Draw parchment */
94 	vulture_put_img(abs_x, abs_y, mapbg);
95 
96 	/* Draw the level name */
97 #ifdef VULTURE_SLASHEM
98 	describe_level(buffer, TRUE);
99 #else
100 	if (!describe_level(buffer))
101 		sprintf(buffer, "%s, level %d ", dungeons[u.uz.dnum].dname, depth(&u.uz));
102 #endif
103 	txt->set_caption(buffer);
104 	txt->x = (w - vulture_text_length(V_FONT_HEADLINE, txt->caption)) / 2;
105 	txt->abs_x = abs_x + txt->x;
106 	txt->abs_y = abs_y + txt->y;
107 	vulture_put_text_shadow(V_FONT_HEADLINE, txt->caption, vulture_screen,
108 	                      txt->abs_x, txt->abs_y, CLR32_BROWN, CLR32_BLACK_A50);
109 
110 	/* Find upper left corner of map on parchment */
111 	map_x = abs_x + 39;
112 	map_y = abs_y + 91;
113 
114 	/* Draw map on parchment, and create hotspots */
115 	for (i = 0; i < ROWNO; i++)
116 		for (j = 1; j < COLNO; j++) {
117 			int map_glyph = map_data->get_glyph(MAP_GLYPH, j, i);
118 			bool is_dark = (map_data->get_glyph(MAP_DARKNESS, j, i) == 2);
119 
120 			if (map_glyph != NO_GLYPH &&
121 				(map_glyph != cmap_to_glyph(S_stone) ||
122 				(level.locations[j][i].seenv && is_dark))) {
123 				vulture_put_img(
124 						map_x + SYMBOL_WIDTH*j,
125 						map_y + SYMBOL_HEIGHT*i,
126 						map_symbols[glyph2tile[map_glyph]]);
127 			}
128 		}
129 
130 	vulture_invalidate_region(abs_x, abs_y, w, h);
131 
132 	return false;
133 }
134 
135 
toggle(void)136 void map::toggle(void)
137 {
138 	if (!mapwin) {
139 		mapwin = new map(levwin, ::map_data);
140 
141 		mapwin->x = (mapwin->parent->w - mapwin->w) / 2;
142 		mapwin->y = (mapwin->parent->h - mapwin->h) / 2;
143 	}
144 	else {
145 		mapwin->hide();
146 		delete mapwin;
147 		mapwin = NULL;
148 	}
149 }
150 
151 
handle_timer_event(window * target,void * result,int time)152 eventresult map::handle_timer_event(window* target, void* result, int time)
153 {
154   std::string ttext;
155 	point mappos = get_mouse_mappos();
156 
157 	if (time < HOVERTIMEOUT)
158 		return V_EVENT_HANDLED_NOREDRAW;
159 
160 	/* draw the tooltip for the close button */
161 	if (this != target && target->menu_id == 1)
162 		vulture_mouse_set_tooltip(target->caption);
163 	/* draw a tooltip for the map location */
164 	else if (mappos.x != -1) {
165 		ttext = map_data->map_square_description(mappos, 1);
166 		if(!ttext.empty())
167 			vulture_mouse_set_tooltip(ttext);
168 	}
169 
170 	return V_EVENT_HANDLED_NOREDRAW;
171 }
172 
173 
handle_mousemotion_event(window * target,void * result,int xrel,int yrel,int state)174 eventresult map::handle_mousemotion_event(window* target, void* result, int xrel,
175                                              int yrel, int state)
176 {
177 	vulture_set_mcursor(V_CURSOR_NORMAL);
178 	return V_EVENT_HANDLED_NOREDRAW;
179 }
180 
181 
handle_mousebuttonup_event(window * target,void * result,int mouse_x,int mouse_y,int button,int state)182 eventresult map::handle_mousebuttonup_event(window* target, void* result,
183                                             int mouse_x, int mouse_y, int button, int state)
184 {
185 	point mappos = get_mouse_mappos();
186 
187 	/* handler != target if the user clicked on the X in the upper right corner */
188 	if (this != target && target->menu_id == 1) {
189 		toggle();
190 		vulture_mouse_invalidate_tooltip(1);
191 		return V_EVENT_HANDLED_REDRAW;
192 	}
193 
194 	/* only handle clicks on valid map locations */
195 	if (mappos.x != -1)
196 		return map_data->handle_click(result, button, mappos);
197 
198 	return V_EVENT_HANDLED_NOREDRAW;
199 }
200 
201 
handle_resize_event(window * target,void * result,int res_w,int res_h)202 eventresult map::handle_resize_event(window* target, void* result, int res_w, int res_h)
203 {
204 	x = (parent->w - w) / 2;
205 	y = (parent->h - h) / 2;
206 	return V_EVENT_HANDLED_NOREDRAW;
207 }
208 
209 
get_mouse_mappos(void)210 point map::get_mouse_mappos(void)
211 {
212 	point mouse, mappos;
213 
214 	mouse = vulture_get_mouse_pos();
215 	mappos.x = (mouse.x - abs_x - 39) / SYMBOL_WIDTH;
216 	mappos.y = (mouse.y - abs_y - 91) / SYMBOL_HEIGHT;
217 
218 	if (mappos.x < 1 || mappos.x >= COLNO ||
219 		mappos.y < 0 || mappos.y >= ROWNO) {
220 		mappos.x = -1;
221 		mappos.y = -1;
222 	}
223 
224 	return mappos;
225 }
226