NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / win / gnome / gnmap.c
blob33ca130f3cdae111c3fd6ccc2cbf64b042f79058
1 /* aNetHack 0.0.1 gnmap.c $ANH-Date: 1432512806 2015/05/25 00:13:26 $ $ANH-Branch: master $:$ANH-Revision: 1.10 $ */
2 /* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
3 /* Copyright (C) 1998 by Anthony Taylor <tonyt@ptialaska.net> */
4 /* aNetHack may be freely redistributed. See license for details. */
6 #include "gnmap.h"
7 #include "gnglyph.h"
8 #include "gnsignal.h"
9 #include "hack.h"
11 #ifndef ROWNO
12 #define ROWNO 21
13 #define COLNO 80
14 #endif
16 /* globals static to this file go here */
17 struct {
18 GnomeCanvas *canvas;
19 GnomeCanvasImage *map[(ROWNO + 1) * COLNO];
20 GnomeCanvasImage *overlay[(ROWNO + 1) * COLNO];
21 double zoom;
22 GtkWidget *frame;
23 } ghack_map;
25 static GdkImlibImage *background;
26 static GdkImlibImage *petmark;
27 static GnomeCanvasGroup *myCanvasGroup;
29 /* static function declarations -- local to this file go here */
30 void ghack_map_cursor_to(GtkWidget *win, int x, int y, gpointer data);
31 void ghack_map_putstr(GtkWidget *win, int attr, const char *text,
32 gpointer data);
33 void ghack_map_print_glyph(GtkObject *win, guint x, guint y,
34 GdkImlibImage *im, gpointer data);
35 void ghack_map_clear(GtkWidget *win, gpointer data);
36 static void ghack_map_display(GtkWidget *win, boolean block, gpointer data);
37 static void ghack_map_cliparound(GtkWidget *win, int x, int y, gpointer data);
38 static void ghack_map_window_zoom(GtkAdjustment *adj, gpointer data);
40 /* The following XPM is the artwork of Warwick Allison
41 * <warwick@troll.no>. It has been borrowed from
42 * the most excellent aNetHackQt, until such time as
43 * we can come up with something better.
45 * More information about aNetHackQt can be had from:
46 * http://www.troll.no/~warwick/anethack/
49 /* XPM */
50 static char *pet_mark_xpm[] = {
51 /* width height ncolors chars_per_pixel */
52 "8 7 2 1",
53 /* colors */
54 ". c None", " c #FF0000",
55 /* pixels */
56 "........", ".. . .", ". ", ". ",
57 ".. .", "... ..", ".... ..."
60 /* NAME:
61 * ghack_init_map_window( )
63 * ARGUMENTS:
64 * NONE
66 * RETURNS:
67 * GtkWidget*
69 * PURPOSE:
70 * Create the basic map necessities. Create a canvas;
71 * give it a background. Attach all the right signals
72 * to all the right places. Generally prepare the map
73 * to behave properly.
76 GtkWidget *
77 ghack_init_map_window()
79 GtkWidget *vbox;
80 GtkWidget *hbox;
81 GtkWidget *table;
82 GtkWidget *frame;
83 GtkWidget *w;
84 GtkWidget *hSeparator;
85 GtkAdjustment *adj;
86 GnomeCanvasImage *bg;
87 double width, height, x, y;
88 int i;
90 width = COLNO * ghack_glyph_width();
91 height = ROWNO * ghack_glyph_height();
93 vbox = gtk_vbox_new(FALSE, 4);
94 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
95 gtk_widget_show(vbox);
97 /* Add in a horiz seperator */
98 hSeparator = gtk_hseparator_new();
99 gtk_box_pack_start(GTK_BOX(vbox), hSeparator, FALSE, FALSE, 2);
100 gtk_widget_show(hSeparator);
102 hbox = gtk_hbox_new(FALSE, 4);
103 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
104 gtk_widget_show(hbox);
106 /* Create the Zoom spinbutton.
108 ghack_map.zoom = 1.0;
109 w = gtk_label_new("Zoom:");
110 gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 0);
111 gtk_widget_show(w);
112 adj =
113 GTK_ADJUSTMENT(gtk_adjustment_new(1.00, 0.5, 3.00, 0.05, 0.50, 0.50));
114 w = gtk_spin_button_new(adj, 0.5, 2);
115 gtk_widget_set_usize(w, 50, 0);
116 gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 0);
117 gtk_widget_show(w);
119 /* Canvas and scrollbars
121 gtk_widget_push_visual(gdk_imlib_get_visual());
122 gtk_widget_push_colormap(gdk_imlib_get_colormap());
123 ghack_map.canvas = GNOME_CANVAS(gnome_canvas_new());
124 // gtk_widget_push_visual(gdk_rgb_get_visual());
125 // gtk_widget_push_colormap(gdk_rgb_get_cmap());
126 // ghack_map.canvas = GNOME_CANVAS (gnome_canvas_new_aa());
128 gtk_widget_pop_colormap();
129 gtk_widget_pop_visual();
130 gtk_widget_show(GTK_WIDGET(ghack_map.canvas));
132 table = gtk_table_new(2, 2, FALSE);
133 gtk_table_set_row_spacings(GTK_TABLE(table), 4);
134 gtk_table_set_col_spacings(GTK_TABLE(table), 4);
135 gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
136 gtk_widget_show(table);
138 frame = gtk_frame_new(NULL);
139 ghack_map.frame = frame;
140 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
141 gtk_table_attach(GTK_TABLE(table), frame, 0, 1, 0, 1,
142 GTK_EXPAND | GTK_FILL | GTK_SHRINK,
143 GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
144 gtk_widget_show(frame);
146 gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(ghack_map.canvas));
147 gnome_canvas_set_scroll_region(GNOME_CANVAS(ghack_map.canvas), 0, 0,
148 width + 2 * ghack_glyph_width(),
149 height + 2 * ghack_glyph_height());
151 gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(ghack_map.canvas), 1.0);
153 w = gtk_hscrollbar_new(GTK_LAYOUT(ghack_map.canvas)->hadjustment);
154 gtk_table_attach(GTK_TABLE(table), w, 0, 1, 1, 2,
155 GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 0, 0);
156 gtk_widget_show(w);
158 w = gtk_vscrollbar_new(GTK_LAYOUT(ghack_map.canvas)->vadjustment);
159 gtk_table_attach(GTK_TABLE(table), w, 1, 2, 0, 1, GTK_FILL,
160 GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
161 gtk_widget_show(w);
163 myCanvasGroup = GNOME_CANVAS_GROUP(gnome_canvas_item_new(
164 gnome_canvas_root(GNOME_CANVAS(ghack_map.canvas)),
165 gnome_canvas_group_get_type(), "x", 0.0, "y", 0.0, NULL));
167 /* Tile the map background with a pretty image */
168 background = gdk_imlib_load_image((char *) "mapbg.xpm");
169 if (background == NULL) {
170 g_warning(
171 "Bummer! Failed to load the map background image (mapbg.xpm)!");
172 } else {
173 gdk_imlib_render(background, background->rgb_width,
174 background->rgb_height);
176 /* Tile the map background */
177 for (y = 0; y < height + background->rgb_height;
178 y += background->rgb_height) {
179 for (x = 0; x < width + background->rgb_width;
180 x += background->rgb_width) {
181 bg = GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
182 myCanvasGroup, gnome_canvas_image_get_type(), "x",
183 (double) x, "y", (double) y, "width",
184 (double) background->rgb_width, "height",
185 (double) background->rgb_height, "image", background,
186 "anchor", (GtkAnchorType) GTK_ANCHOR_CENTER, NULL));
187 gnome_canvas_item_lower_to_bottom(GNOME_CANVAS_ITEM(bg));
192 /* ghack_map.map is an array of canvas images. Each cell of
193 * the array will contain one tile. Here, we create the
194 * space for the cells and then create the cells for easy
195 * access later.
197 for (i = 0, y = 0; y < height; y += ghack_glyph_height()) {
198 for (x = 0; x < width; x += ghack_glyph_width()) {
199 ghack_map.map[i++] = GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
200 myCanvasGroup, gnome_canvas_image_get_type(), "x", (double) x,
201 "y", (double) y, "width", (double) ghack_glyph_width(),
202 "height", (double) ghack_glyph_height(), "anchor",
203 GTK_ANCHOR_NORTH_WEST, NULL));
207 /* Set up the pet mark image */
208 petmark = gdk_imlib_create_image_from_xpm_data(pet_mark_xpm);
209 if (petmark == NULL) {
210 g_warning("Bummer! Failed to load the pet_mark image!");
211 } else {
212 gdk_imlib_render(petmark, petmark->rgb_width, petmark->rgb_height);
214 /* ghack_map.overlay is an array of canvas images used to
215 * overlay tile images...
217 for (i = 0, y = 0; y < height; y += ghack_glyph_height()) {
218 for (x = 0; x < width; x += ghack_glyph_width()) {
219 ghack_map.overlay[i] =
220 GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
221 myCanvasGroup, gnome_canvas_image_get_type(), "x",
222 (double) x, "y", (double) y, "width",
223 (double) petmark->rgb_width, "height",
224 (double) petmark->rgb_height, "image", petmark,
225 "anchor", GTK_ANCHOR_NORTH_WEST, NULL));
226 gnome_canvas_item_lower_to_bottom(
227 GNOME_CANVAS_ITEM(ghack_map.overlay[i++]));
232 /* Resize the canvas when the spinbutton changes
234 gtk_signal_connect(GTK_OBJECT(adj), "value_changed",
235 (GtkSignalFunc) ghack_map_window_zoom,
236 ghack_map.canvas);
238 /* Game signals
240 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_curs",
241 GTK_SIGNAL_FUNC(ghack_map_cursor_to), NULL);
242 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_putstr",
243 GTK_SIGNAL_FUNC(ghack_map_putstr), NULL);
244 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_print_glyph",
245 GTK_SIGNAL_FUNC(ghack_map_print_glyph), NULL);
246 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_clear",
247 GTK_SIGNAL_FUNC(ghack_map_clear), NULL);
248 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_display",
249 GTK_SIGNAL_FUNC(ghack_map_display), NULL);
250 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_cliparound",
251 GTK_SIGNAL_FUNC(ghack_map_cliparound), NULL);
252 gtk_signal_connect(GTK_OBJECT(ghack_map.canvas), "button_press_event",
253 GTK_SIGNAL_FUNC(ghack_handle_button_press), NULL);
254 gtk_signal_connect(GTK_OBJECT(ghack_map.canvas), "gnome_delay_output",
255 GTK_SIGNAL_FUNC(ghack_delay), NULL);
257 return GTK_WIDGET(vbox);
260 /* NAME:
261 * ghack_map_window_zoom
263 * ARGUMENTS:
264 * double zoom -- The zoom factor
266 * RETURNS:
267 * Nothing.
269 * PURPOSE:
270 * Zoom the map image in and out. This should allow the user to
271 * dynamically scale the map. Ideally, the background should
272 * *NOT* scale, but this may be impractical.
275 static void
276 ghack_map_window_zoom(GtkAdjustment *adj, gpointer data)
278 if (adj->value > 3.0)
279 adj->value = 3.0;
280 if (adj->value < 0.5)
281 adj->value = 0.5;
282 ghack_map.zoom = adj->value;
283 gnome_canvas_set_pixels_per_unit(data, adj->value);
286 void
287 ghack_map_cursor_to(GtkWidget *win, int x, int y, gpointer data)
289 GnomeCanvasGroup *group;
290 static GnomeCanvasRE *cursor = NULL;
292 double x1, y1, x2, y2;
293 float hp;
294 guint r, g, b;
296 x1 = x * ghack_glyph_width() - 1;
297 y1 = y * ghack_glyph_height() - 1;
298 x2 = x1 + ghack_glyph_width() + 2;
299 y2 = y1 + ghack_glyph_height() + 2;
300 hp = u.mtimedone ? (u.mhmax ? (float) u.mh / u.mhmax : 1)
301 : (u.uhpmax ? (float) u.uhp / u.uhpmax : 1);
303 r = 255;
304 g = (hp >= 0.75) ? 255 : (hp >= 0.25 ? 255 * 2 * (hp - 0.25) : 0);
305 b = (hp >= 0.75) ? 255 * 4 * (hp - 0.75)
306 : (hp >= 0.25 ? 0 : 255 * 4 * (0.25 - hp));
308 group = gnome_canvas_root(GNOME_CANVAS(ghack_map.canvas));
310 if (!cursor) {
311 cursor = GNOME_CANVAS_RE(gnome_canvas_item_new(
312 group, gnome_canvas_rect_get_type(), "width_units", 1.0, NULL));
314 gnome_canvas_item_set(GNOME_CANVAS_ITEM(cursor), "outline_color_rgba",
315 GNOME_CANVAS_COLOR(r, g, b), "x1", x1, "y1", y1,
316 "x2", x2, "y2", y2, NULL);
318 gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(cursor));
319 gnome_canvas_item_show(GNOME_CANVAS_ITEM(cursor));
322 void
323 ghack_map_putstr(GtkWidget *win, int attr, const char *text, gpointer data)
325 g_warning("Fixme!!! ghack_map_putstr is not implemented");
328 /* NAME:
329 * ghack_map_print_glyph( )
331 * ARGUMENTS:
332 * XCHAR_P x, y -- The coordinates where which to print the glyph
333 * GdkImlibImage* glyph -- The glyph image to print
335 * RETURNS:
336 * Nothing.
338 * PURPOSE:
339 * Draw the glyph-tile at the specified coordinates.
342 void
343 ghack_map_print_glyph(GtkObject *win, guint x, guint y, GdkImlibImage *im,
344 gpointer data)
346 GnomeCanvasGroup *group;
347 int i = y * COLNO + x;
348 int glyph = glyph_at(x, y);
349 GnomeCanvasImage *canvas_image = GNOME_CANVAS_IMAGE(ghack_map.map[i]);
351 group = gnome_canvas_root(GNOME_CANVAS(ghack_map.canvas));
353 gnome_canvas_item_set(GNOME_CANVAS_ITEM(canvas_image), "image", im, NULL);
354 gnome_canvas_item_show(GNOME_CANVAS_ITEM(canvas_image));
356 canvas_image = GNOME_CANVAS_IMAGE(ghack_map.overlay[i]);
358 if (x == u.ux && y == u.uy)
359 ghack_map_cliparound(NULL, x, y, NULL);
361 if (glyph_is_pet(glyph)
362 #ifdef TEXTCOLOR
363 && iflags.hilite_pet
364 #endif
366 gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(canvas_image));
367 gnome_canvas_item_show(GNOME_CANVAS_ITEM(canvas_image));
368 } else {
369 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(canvas_image));
373 /* NAME:
374 * ghack_map_clear( )
376 * ARGUMENTS:
377 * NONE
379 * RETURNS:
380 * Nothing.
382 * PURPOSE:
383 * Clear the map by hiding all the map tiles.
386 void
387 ghack_map_clear(GtkWidget *win, gpointer data)
389 int i;
391 for (i = 0; i < ROWNO * COLNO; i++) {
392 if (GNOME_IS_CANVAS_IMAGE(ghack_map.map[i])) {
393 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ghack_map.map[i]));
395 if (GNOME_IS_CANVAS_IMAGE(ghack_map.overlay[i])) {
396 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ghack_map.overlay[i]));
399 gnome_canvas_update_now(GNOME_CANVAS(ghack_map.canvas));
402 void
403 ghack_map_display(GtkWidget *win, boolean block, gpointer data)
405 gtk_widget_show_all(GTK_WIDGET(win));
408 void
409 ghack_map_cliparound(GtkWidget *win, int x, int y, gpointer data)
411 int map_width, map_height;
412 int to_x, to_y;
413 int cur_x, cur_y;
414 int width, height, half_width, half_height;
416 x *= ghack_glyph_width() * ghack_map.zoom;
417 y *= ghack_glyph_height() * ghack_map.zoom;
418 map_width = COLNO * ghack_glyph_width() * ghack_map.zoom;
419 map_height = ROWNO * ghack_glyph_height() * ghack_map.zoom;
421 gdk_window_get_size(GTK_LAYOUT(ghack_map.canvas)->bin_window, &width,
422 &height);
423 gnome_canvas_get_scroll_offsets(ghack_map.canvas, &cur_x, &cur_y);
425 half_width = width * 0.5;
426 half_height = height * 0.5;
428 if (((x - cur_x) < (width * 0.25)) || ((x - cur_x) > (width * 0.75))) {
429 to_x = ((x - half_width) > 0) ? x - half_width : 0;
430 to_x = ((x + half_width) > map_width) ? map_width - 2 * half_width
431 : to_x;
432 } else {
433 to_x = cur_x;
436 if (((y - cur_y) < (height * 0.25)) || ((y - cur_y) > (height * 0.75))) {
437 to_y = ((y - half_height) > 0) ? y - half_height : 0;
438 to_y = ((y + half_height) > map_height) ? map_height - 2 * half_height
439 : to_y;
440 } else {
441 to_y = cur_y;
444 if (to_x != cur_x || to_y != cur_y)
445 gnome_canvas_scroll_to(ghack_map.canvas, to_x, to_y);
446 // gnome_canvas_update_now ( ghack_map.canvas);
449 void
450 ghack_reinit_map_window()
452 GnomeCanvasImage *bg;
453 double width, height, x, y;
454 int i;
456 /* ghack_map_clear(NULL, NULL); */
458 width = COLNO * ghack_glyph_width();
459 height = ROWNO * ghack_glyph_height();
461 gnome_canvas_set_scroll_region(GNOME_CANVAS(ghack_map.canvas), 0, 0,
462 width + 2 * ghack_glyph_width(),
463 height + 2 * ghack_glyph_height());
465 /* remove everything currently in the canvas map */
466 gtk_object_destroy(GTK_OBJECT(myCanvasGroup));
468 /* Put some groups back */
469 myCanvasGroup = GNOME_CANVAS_GROUP(gnome_canvas_item_new(
470 gnome_canvas_root(GNOME_CANVAS(ghack_map.canvas)),
471 gnome_canvas_group_get_type(), "x", 0.0, "y", 0.0, NULL));
473 /* Tile the map background with a pretty image */
474 if (background != NULL) {
475 /* Tile the map background */
476 for (y = 0; y < height + background->rgb_height;
477 y += background->rgb_height) {
478 for (x = 0; x < width + background->rgb_width;
479 x += background->rgb_width) {
480 bg = GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
481 myCanvasGroup, gnome_canvas_image_get_type(), "x",
482 (double) x, "y", (double) y, "width",
483 (double) background->rgb_width, "height",
484 (double) background->rgb_height, "image", background,
485 "anchor", (GtkAnchorType) GTK_ANCHOR_CENTER, NULL));
486 gnome_canvas_item_lower_to_bottom(GNOME_CANVAS_ITEM(bg));
491 /* ghack_map.map is an array of canvas images. Each cell of
492 * the array will contain one tile. Here, we create the
493 * space for the cells and then create the cells for easy
494 * access later.
496 for (i = 0, y = 0; y < height; y += ghack_glyph_height()) {
497 for (x = 0; x < width; x += ghack_glyph_width()) {
498 ghack_map.map[i++] = GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
499 myCanvasGroup, gnome_canvas_image_get_type(), "x", (double) x,
500 "y", (double) y, "width", (double) ghack_glyph_width(),
501 "height", (double) ghack_glyph_height(), "anchor",
502 GTK_ANCHOR_NORTH_WEST, NULL));
506 if (petmark != NULL) {
507 /* ghack_map.overlay is an array of canvas images used to
508 * overlay tile images...
510 for (i = 0, y = 0; y < height; y += ghack_glyph_height()) {
511 for (x = 0; x < width; x += ghack_glyph_width()) {
512 ghack_map.overlay[i] =
513 GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
514 myCanvasGroup, gnome_canvas_image_get_type(), "x",
515 (double) x, "y", (double) y, "width",
516 (double) petmark->rgb_width, "height",
517 (double) petmark->rgb_height, "image", petmark,
518 "anchor", GTK_ANCHOR_NORTH_WEST, NULL));
519 gnome_canvas_item_lower_to_bottom(
520 GNOME_CANVAS_ITEM(ghack_map.overlay[i++]));
525 ghack_map_cliparound(NULL, u.ux, u.uy, NULL);
526 ghack_map_cursor_to(NULL, u.ux, u.uy, NULL);
527 gnome_canvas_update_now(ghack_map.canvas);
528 doredraw();