-/* NetHack 3.6 winmap.c $NHDT-Date: 1447844616 2015/11/18 11:03:36 $ $NHDT-Branch: master $:$NHDT-Revision: 1.25 $ */
+/* NetHack 3.6 winmap.c $NHDT-Date: 1455389908 2016/02/13 18:58:28 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.29 $ */
/* Copyright (c) Dean Luick, 1992 */
/* NetHack may be freely redistributed. See license for details. */
#include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/Scrollbar.h>
#include <X11/Xaw/Viewport.h>
+#include <X11/Xaw/Label.h>
#include <X11/Xatom.h>
+#include <X11/keysym.h>
#ifdef PRESERVE_NO_SYSV
#ifdef SYSV
static void FDECL(get_char_info, (struct xwindow *));
static void FDECL(display_cursor, (struct xwindow *));
+#ifdef X11LARGETILE
+struct pxm_slot_t {
+ int fg;
+ int bg;
+ int age;
+ Pixmap pixmap;
+};
+#define MAX_PXM_SLOTS 100
+ struct pxm_slot_t pxm_slot[MAX_PXM_SLOTS];
+#endif
+
/* Global functions ======================================================= */
void
int color, och;
unsigned special;
#ifdef TEXTCOLOR
+ int colordif;
register unsigned char *co_ptr;
#endif
/* map glyph to character and color */
- (void) mapglyph(glyph, &och, &color, &special, x, y);
+ (void) mapglyph(glyph, &och, &color, &special, x, y, 0);
ch = (uchar) och;
if (special != map_info->tile_map.glyphs[y][x].special) {
/* Only update if we need to. */
ch_ptr = &map_info->text_map.text[y][x];
-
-#ifdef TEXTCOLOR
- co_ptr = &map_info->text_map.colors[y][x];
- if (*ch_ptr != ch || *co_ptr != color)
-#else
- if (*ch_ptr != ch)
-#endif
- {
+ if (*ch_ptr != ch) {
*ch_ptr = ch;
+ if (!map_info->is_tile)
+ update_bbox = TRUE;
+ }
#ifdef TEXTCOLOR
- if ((special & MG_PET) && iflags.hilite_pet)
- color += CLR_MAX;
- if ((special & MG_OBJPILE) && iflags.hilite_pile)
- *co_ptr = color;
-#endif
+ co_ptr = &map_info->text_map.colors[y][x];
+ colordif = (((special & MG_PET) != 0 && iflags.hilite_pet)
+ || ((special & MG_OBJPILE) != 0 && iflags.hilite_pile)
+ || ((special & (MG_DETECT | MG_BW_LAVA)) != 0))
+ ? CLR_MAX : 0;
+ if (*co_ptr != (uchar) (color + colordif)) {
+ *co_ptr = (uchar) (color + colordif);
if (!map_info->is_tile)
update_bbox = TRUE;
}
+#endif
}
if (update_bbox) { /* update row bbox */
/*ARGSUSED*/
void
X11_cliparound(x, y)
-int x, y;
+int x UNUSED;
+int y UNUSED;
{
+ return;
}
#endif /* CLIPPING */
* or just keep it on a per-window basis.
*/
Pixmap tile_pixmap = None;
+#ifdef X11LARGETILE
+Pixmap tile_clipmask = None;
+GC tile_gc;
+/*JP #ifdef USE_XPM*/
+XpmImage tile_image;
+/* #endif*/
+
+#define TILE_WIDTH appResources.tile_width
+#define TILE_HEIGHT appResources.tile_height
+int TILE_PER_COL;
+#else
static int tile_width;
static int tile_height;
static int tile_count;
static XImage *tile_image = 0;
+#endif
/*
* This structure is used for small bitmaps that are used for annotating
post_process_tiles()
{
Display *dpy = XtDisplay(toplevel);
+#ifndef X11LARGETILE
unsigned int width, height;
if (tile_image == 0)
tile_image, 0, 0, 0, 0, /* src, dest top left */
width, height);
+#ifdef MONITOR_HEAP
+ /* if we let XDestroyImage() handle it, our tracking will be off */
+ if (tile_image->data)
+ free((genericptr_t) tile_image->data), tile_image->data = 0;
+#endif
XDestroyImage(tile_image); /* data bytes free'd also */
tile_image = 0;
+#else
+ Colormap cmap;
+# ifdef USE_XPM
+ XpmAttributes attributes;
+# endif
+ Arg args[16];
+ XGCValues val;
+
+# ifdef USE_XPM
+ if(tile_image.data){
+ XtSetArg(args[0], XtNcolormap, &cmap);
+ XtGetValues(toplevel, args, ONE);
+
+ attributes.valuemask = XpmCloseness | XpmColormap;
+ attributes.colormap = cmap;
+ attributes.closeness = 25000;
+
+ XpmCreatePixmapFromXpmImage(
+ dpy,
+ XtWindow(toplevel),
+ &tile_image,
+ &tile_pixmap,
+ &tile_clipmask,
+ &attributes
+ );
+
+ val.function = GXcopy;
+ val.clip_mask = tile_clipmask;
+
+ tile_gc = XCreateGC(
+ dpy,
+ XtWindow(toplevel),
+ GCFunction | GCClipMask,
+ &val
+ );
+
+ XpmFreeXpmImage(&tile_image);
+ }
+# endif
+#endif
init_annotation(&pet_annotation, appResources.pet_mark_bitmap,
appResources.pet_mark_color);
attributes.valuemask = XpmCloseness;
attributes.closeness = 25000;
+# ifndef X11LARGETILE
errorcode = XpmReadFileToImage(dpy, appResources.tile_file, &tile_image,
0, &attributes);
+# else
+ errorcode = XpmReadFileToXpmImage(appResources.tile_file, &tile_image,
+ NULL);
+# endif
+# ifndef X11LARGETILE
if (errorcode == XpmColorFailed) {
Sprintf(buf, "Insufficient colors available to load %s.",
appResources.tile_file);
errorcode = XpmReadFileToImage(dpy, appResources.tile_file,
&tile_image, 0, &attributes);
}
+# endif
if (errorcode != XpmSuccess) {
if (errorcode == XpmColorFailed) {
goto tiledone;
}
+# ifdef X11LARGETILE
+ TILE_PER_COL = tile_image.width / TILE_WIDTH;
+# else
/* assume a fixed number of tiles per row */
if (tile_image->width % TILES_PER_ROW != 0
|| tile_image->width <= TILES_PER_ROW) {
}
tile_width = image_width / TILES_PER_ROW;
tile_height = image_height / (tile_count / TILES_PER_ROW);
+# endif
#else /* !USE_XPM */
/* any less than 16 colours makes tiles useless */
ddepth = DefaultDepthOfScreen(screen);
values.graphics_exposures = False;
values.foreground =
WhitePixelOfScreen(screen)
+# ifndef X11LARGETILE
^ XGetPixel(tile_image, 0,
tile_height * glyph2tile[cmap_to_glyph(S_corr)]);
+# else
+ ^ XGetPixel(tile_image,
+ tile_width*(glyph2tile[cmap_to_glyph(S_corr)]%TILE_PER_COL),
+ tile_height*(glyph2tile[cmap_to_glyph(S_corr)]/TILE_PER_COL));
+# endif
values.function = GXxor;
tile_info->white_gc = XtGetGC(wp->w, mask, &values);
free((genericptr_t) tile_bytes);
if (colors)
free((genericptr_t) colors);
+# ifdef X11LARGETILE
+ {
+ int i;
+ for(i = 0; i < MAX_PXM_SLOTS; i++){
+ pxm_slot[i].age = 0;
+ pxm_slot[i].bg = pxm_slot[i].fg = -99;
+ pxm_slot[i].pixmap=0;
+ }
+ }
+# endif
#endif
if (result) { /* succeeded */
+#ifndef X11LARGETILE
tile_info->square_height = tile_height;
tile_info->square_width = tile_width;
+#else
+ tile_info->square_height = TILE_HEIGHT;
+ tile_info->square_width = TILE_WIDTH;
+#endif
tile_info->square_ascent = 0;
tile_info->square_lbearing = 0;
tile_info->image_width = image_width;
set_color_gc(CLR_BRIGHT_CYAN, XtNbright_cyan);
set_color_gc(CLR_WHITE, XtNwhite);
#else
- set_gc(wp->w, font, XtNforeground, bgpixel, &map_info->text_map.copy_gc,
+ set_gc(wp->w, font, XtNforeground, bgpixel,
+ &map_info->text_map.copy_gc,
&map_info->text_map.inv_copy_gc);
#endif
}
XClearWindow(XtDisplay(wp->w), XtWindow(wp->w));
set_map_size(wp, COLNO, ROWNO);
check_cursor_visibility(wp);
+ highlight_yn(TRUE); /* change fg/bg to match map */
} else if (wp->prevx != wp->cursx || wp->prevy != wp->cursy) {
register unsigned int x = wp->prevx, y = wp->prevy;
map_all_stone(map_info);
(void) memset((genericptr_t) map_info->text_map.text, ' ',
- sizeof(map_info->text_map.text));
+ sizeof map_info->text_map.text);
#ifdef TEXTCOLOR
(void) memset((genericptr_t) map_info->text_map.colors, NO_COLOR,
- sizeof(map_info->text_map.colors));
+ sizeof map_info->text_map.colors);
#endif
/* force a full update */
(void) memset((genericptr_t) map_info->t_start, (char) 0,
- sizeof(map_info->t_start));
+ sizeof map_info->t_start);
(void) memset((genericptr_t) map_info->t_stop, (char) COLNO - 1,
- sizeof(map_info->t_stop));
+ sizeof map_info->t_stop);
display_map_window(wp);
}
#ifdef VERBOSE
printf("Font information:\n");
printf("fid = %ld, direction = %d\n", fs->fid, fs->direction);
- printf("first = %d, last = %d\n", fs->min_char_or_byte2,
- fs->max_char_or_byte2);
+ printf("first = %d, last = %d\n",
+ fs->min_char_or_byte2, fs->max_char_or_byte2);
printf("all chars exist? %s\n", fs->all_chars_exist ? "yes" : "no");
printf("min_bounds:lb=%d rb=%d width=%d asc=%d des=%d attr=%d\n",
fs->min_bounds.lbearing, fs->min_bounds.rbearing,
fs->max_bounds.width, fs->max_bounds.ascent,
fs->max_bounds.descent, fs->max_bounds.attributes);
printf("per_char = 0x%lx\n", (unsigned long) fs->per_char);
- printf("Text: (max) width = %d, height = %d\n", text_map->square_width,
- text_map->square_height);
+ printf("Text: (max) width = %d, height = %d\n",
+ text_map->square_width, text_map->square_height);
#endif
if (fs->min_bounds.width != fs->max_bounds.width)
* keyhit buffer
*/
#define INBUF_SIZE 64
-int inbuf[INBUF_SIZE];
-int incount = 0;
-int inptr = 0; /* points to valid data */
+static int inbuf[INBUF_SIZE];
+static int incount = 0;
+static int inptr = 0; /* points to valid data */
/*
* Keyboard and button event handler for map window.
Cardinal in_nparams = (num_params ? *num_params : 0);
char c;
char keystring[MAX_KEY_STRING];
+#if 1 /*JP*/
+ KeySym keysym = 0;
+#endif
switch (event->type) {
case ButtonPress:
+ if (!iflags.wc_mouse_support)
+ return;
+
button = (XButtonEvent *) event;
#ifdef VERBOSE_INPUT
printf("button press\n");
* Assume that mod1 is really the meta key.
*/
meta = !!(key->state & Mod1Mask);
+#if 0 /*JP*/
nbytes = XLookupString(key, keystring, MAX_KEY_STRING,
(KeySym *) 0, (XComposeStatus *) 0);
+#else
+ nbytes = XLookupString(key, keystring, MAX_KEY_STRING,
+ &keysym, (XComposeStatus *) 0);
+#endif
+ }
+#if 1 /*JP*/
+ /*
+ \8b\88ø\82É
+ */
+ if(!iflags.num_pad){
+ if(keysym == XK_KP_1 || keysym == XK_KP_End){
+ keystring[0] = 'b';
+ nbytes = 1;
+ }
+ else if(keysym == XK_KP_2 || keysym == XK_KP_Down){
+ keystring[0] = 'j';
+ nbytes = 1;
+ }
+ else if(keysym == XK_KP_3 || keysym == XK_KP_Page_Down){
+ keystring[0] = 'n';
+ nbytes = 1;
+ }
+ else if(keysym == XK_KP_4 || keysym == XK_KP_Left){
+ keystring[0] = 'h';
+ nbytes = 1;
+ }
+ else if(keysym == XK_KP_5 || keysym == XK_KP_Begin){
+ keystring[0] = '.';
+ nbytes = 1;
+ }
+ else if(keysym == XK_KP_6 || keysym == XK_KP_Right){
+ keystring[0] = 'l';
+ nbytes = 1;
+ }
+ else if(keysym == XK_KP_7 || keysym == XK_KP_Home){
+ keystring[0] = 'y';
+ nbytes = 1;
+ }
+ else if(keysym == XK_KP_8 || keysym == XK_KP_Up){
+ keystring[0] = 'k';
+ nbytes = 1;
+ }
+ else if(keysym == XK_KP_9 || keysym == XK_KP_Page_Up){
+ keystring[0] = 'u';
+ nbytes = 1;
+ }
}
+#endif
key_events:
/* Modifier keys return a zero length string when pressed. */
if (nbytes) {
/*
* Do the actual work of the putting characters onto our X window. This
* is called from the expose event routine, the display window (flush)
- * routine, and the display cursor routine. The later involves inverting
+ * routine, and the display cursor routine. The last involves inverting
* the foreground and background colors, which are also inverted when the
* position's color is above CLR_MAX.
*
}
#ifdef VERBOSE_UPDATE
- printf("update: [0x%x] %d %d %d %d\n", (int) wp->w, start_row, stop_row,
- start_col, stop_col);
+ printf("update: [0x%x] %d %d %d %d\n",
+ (int) wp->w, start_row, stop_row, start_col, stop_col);
#endif
win_start_row = start_row;
win_start_col = start_col;
Display *dpy = XtDisplay(wp->w);
Screen *screen = DefaultScreenOfDisplay(dpy);
+#ifdef X11LARGETILE
+ /* each slots ages */
+ {
+ int i;
+
+ for(i = 0; i < MAX_PXM_SLOTS; i++)
+ pxm_slot[i].age++;
+ }
+#endif
for (row = start_row; row <= stop_row; row++) {
for (cur_col = start_col; cur_col <= stop_col; cur_col++) {
+#ifndef X11LARGETILE
int glyph = tile_map->glyphs[row][cur_col].glyph;
int tile = glyph2tile[glyph];
int src_x, src_y;
src_y = (tile / TILES_PER_ROW) * tile_height;
XCopyArea(dpy, tile_pixmap, XtWindow(wp->w),
tile_map->black_gc, /* no grapics_expose */
- src_x, src_y, tile_width, tile_height, dest_x,
- dest_y);
+ src_x, src_y, tile_width, tile_height,
+ dest_x, dest_y);
+#else
+ struct rm *lev = &levl[cur_col][row];
+ int glyph = tile_map->glyphs[row][cur_col].glyph;
+ int bg = back_to_glyph(cur_col, row);
+ int tile = 0;
+ int bgtile = 0;
+ int dest_x = 0;
+ int dest_y = 0;
+ int src_x;
+ int src_y;
+ int bgsrc_x;
+ int bgsrc_y;
+
+ if(tile_pixmap){
+ if(youmonst.data && (Blind || (viz_array && !cansee(cur_col, row))))
+ bg = lev->glyph;
+
+ bgtile = glyph2tile[bg];
+ tile = glyph2tile[glyph];
+ dest_x = cur_col * tile_map->square_width;
+ dest_y = row * tile_map->square_height;
+ bgsrc_x = (bgtile % TILE_PER_COL) * TILE_WIDTH;
+ bgsrc_y = (bgtile / TILE_PER_COL) * TILE_HEIGHT;
+ src_x = (tile % TILE_PER_COL) * TILE_WIDTH;
+ src_y = (tile / TILE_PER_COL) * TILE_HEIGHT;
+ {
+ int i, match;
+ int maxage = 0;
+
+ if(bgtile != -1){
+ match = -1;
+ for(i = 0; i < MAX_PXM_SLOTS; i++){
+ if(tile == pxm_slot[i].fg && bgtile == pxm_slot[i].bg){
+ match = i;
+ break;
+ }
+ }
+ if(match == -1){
+ /* no match found:dispose the oldest slot and compose pixmap */
+ for(i = 0; i < MAX_PXM_SLOTS; i++)
+ if(maxage < pxm_slot[i].age){
+ match = i;
+ maxage = pxm_slot[i].age;
+ }
+ if(!pxm_slot[match].pixmap)
+ pxm_slot[match].pixmap = XCreatePixmap(
+ dpy, XtWindow(toplevel),
+ TILE_WIDTH, TILE_HEIGHT, DefaultDepth(dpy, DefaultScreen(dpy)));
+ XCopyArea(dpy, tile_pixmap, pxm_slot[match].pixmap,
+ tile_map->black_gc,
+ bgsrc_x, bgsrc_y,
+ TILE_WIDTH, TILE_HEIGHT,
+ 0,0);
+
+ XSetClipOrigin(dpy, tile_gc, 0 - src_x, 0 - src_y);
+
+ XCopyArea(dpy, tile_pixmap, pxm_slot[match].pixmap,
+ tile_gc,
+ src_x, src_y,
+ TILE_WIDTH, TILE_HEIGHT,
+ 0,0);
+ pxm_slot[match].fg = tile;
+ pxm_slot[match].bg = bgtile;
+ }
+ /* slot ready */
+ pxm_slot[match].age = 0;
+ XCopyArea(dpy, pxm_slot[match].pixmap, XtWindow(wp->w),
+ tile_map->black_gc,
+ 0, 0,
+ TILE_WIDTH, TILE_HEIGHT,
+ dest_x, dest_y);
+ }
+ else{
+ /* no clip mask */
+ XCopyArea(dpy, tile_pixmap, XtWindow(wp->w),
+ tile_map->black_gc,
+ src_x, src_y,
+ TILE_WIDTH, TILE_HEIGHT,
+ dest_x, dest_y);
+ }
+ }
+ }
+#endif /* X11LARGETILE */
if (glyph_is_pet(glyph) && iflags.hilite_pet) {
/* draw pet annotation (a heart) */
struct text_map_info_t *text_map = &map_info->text_map;
#ifdef TEXTCOLOR
- if (iflags.use_color) {
+ {
register char *c_ptr;
char *t_ptr;
int cur_col, color, win_ystart;
}
XDrawImageString(XtDisplay(wp->w), XtWindow(wp->w),
- cur_inv ? text_map->inv_color_gcs[color]
- : text_map->color_gcs[color],
+ iflags.use_color
+ ? (cur_inv
+ ? text_map->inv_color_gcs[color]
+ : text_map->color_gcs[color])
+ : (cur_inv
+ ? text_map->inv_copy_gc
+ : text_map->copy_gc),
text_map->square_lbearing
+ (text_map->square_width * cur_col),
win_ystart, t_ptr, count);
cur_col += count;
} /* col loop */
} /* row loop */
- } else
-#endif /* TEXTCOLOR */
+ }
+#else /* !TEXTCOLOR */
{
int win_row, win_xstart;
count);
}
}
+#endif /* ?TEXTCOLOR */
}
}
}
num_args = 0;
- XtSetArg(args[num_args], XtNwidth, wp->pixel_width);
- num_args++;
- XtSetArg(args[num_args], XtNheight, wp->pixel_height);
- num_args++;
+ XtSetArg(args[num_args], XtNwidth, wp->pixel_width); num_args++;
+ XtSetArg(args[num_args], XtNheight, wp->pixel_height); num_args++;
XtSetValues(wp->w, args, num_args);
}
struct map_info_t *map_info = wp->map_information;
struct text_map_info_t *text_map = &map_info->text_map;
- (void) memset((genericptr_t) text_map->text, ' ', sizeof(text_map->text));
+ (void) memset((genericptr_t) text_map->text, ' ', sizeof text_map->text);
#ifdef TEXTCOLOR
(void) memset((genericptr_t) text_map->colors, NO_COLOR,
- sizeof(text_map->colors));
+ sizeof text_map->colors);
#endif
get_char_info(wp);
XtSetArg(args[num_args], XtNinput, False);
num_args++;
+#if 0 /*JP*/
wp->popup = parent = XtCreatePopupShell("nethack",
+#else
+ wp->popup = parent = XtCreatePopupShell("jnethack",
+#endif
topLevelShellWidgetClass,
toplevel, args, num_args);
/*
(XtPointer) 0);
else
wp->type = NHW_NONE; /* allow re-use */
+
+ /* when map goes away, presumably we're exiting, so get rid of the
+ cached extended commands menu (if we aren't actually exiting, it
+ will get recreated if needed again) */
+ release_extended_cmds();
}
boolean exit_x_event; /* exit condition for the event loop */