]> granicus.if.org Git - nethack/commitdiff
X11: TTY-style status lines
authorPasi Kallinen <paxed@alt.org>
Mon, 22 Oct 2018 18:23:12 +0000 (21:23 +0300)
committerPasi Kallinen <paxed@alt.org>
Mon, 22 Oct 2018 18:26:56 +0000 (21:26 +0300)
Set X resource NetHack*fancy_status: False to enable the TTY-style
status lines. Default is the fancy status.

This patch is somewhat unfinished - even though the TTY-style status
allow for status hilites, the colors don't work correctly yet.
Also changes the fancy status to use the windowport notification code.

include/extern.h
include/winX.h
src/botl.c
win/X11/NetHack.ad
win/X11/winX.c
win/X11/winstat.c

index e73c931a6e9808100408ada80900dae9c1dca0c6..27699c8bfcdd72c398af72901d125c96e8a5067c 100644 (file)
@@ -145,6 +145,7 @@ E int NDECL(getbones);
 
 /* ### botl.c ### */
 
+E const char *FDECL(bl_idx_to_fldname, (int));
 E char *NDECL(do_statusline1);
 E void NDECL(check_gold_symbol);
 E char *NDECL(do_statusline2);
index 3fe2171076af1de8db0bf2b7dc2da40226901e42..9a9b8ce754a1d566680b66a42ac475442e83afe3 100644 (file)
@@ -254,6 +254,7 @@ E boolean plsel_ask_name;
 
 typedef struct {
     Boolean slow;             /* issue prompts between map and message wins */
+    Boolean fancy_status;     /* use "fancy" status vs. TTY-style status */
     Boolean autofocus;        /* grab pointer focus for popup windows */
     Boolean message_line;     /* separate current turn mesgs from prev ones */
     Boolean highlight_prompt; /* if 'slow', highlight yn prompts */
@@ -433,6 +434,10 @@ E void FDECL(X11_getlin, (const char *, char *));
 E int NDECL(X11_get_ext_cmd);
 E void FDECL(X11_number_pad, (int));
 E void NDECL(X11_delay_output);
+E void NDECL(X11_status_init);
+E void NDECL(X11_status_finish);
+E void FDECL(X11_status_enablefield, (int, const char *, const char *, BOOLEAN_P));
+E void FDECL(X11_status_update, (int, genericptr_t, int, int, int, unsigned long *));
 
 /* other defs that really should go away (they're tty specific) */
 E void NDECL(X11_start_screen);
index fde46e2fb7e45129594eb83fc9d71bf206c96c6f..5d1fe2bcb392376f8caff5d779bf04b61ff0f84b 100644 (file)
@@ -1248,6 +1248,16 @@ static struct fieldid_t {
 static const char threshold_value[] = "hilite_status threshold ",
                   is_out_of_range[] = " is out of range";
 
+
+const char *
+bl_idx_to_fldname(idx)
+int idx;
+{
+    if (idx >= 0 && idx < MAXBLSTATS)
+        return initblstats[idx].fldname;
+    return (const char *) 0;
+}
+
 /* field name to bottom line index */
 STATIC_OVL enum statusfields
 fldname_to_bl_indx(name)
index f7ec106130846ade30774da6d84a1c4055e01ef2..77274d9ca50f04d4492b7b671402baf5206ad29c 100644 (file)
@@ -100,6 +100,10 @@ NetHack*highlight_prompt: False
 ! has a lot of popups and is almost unplayable without some kind of autofocus.
 !NetHack*autofocus: True
 !
+
+! True, use a "fancy" style status area vs. TTY-style status lines
+!NetHack*fancy_status: False
+
 ! Specify the number of rows and columns of the map window.  The default
 ! is the standard 80x21 window.  Note: this _does_not_ change nethack's
 ! level size, only what you see of it.
index 834937e9330fac63b1c4959f54d85ca0971f6e79..18a8fb9f53c1a5a3deecc18df8d2ba70f0b1faa9 100644 (file)
@@ -103,7 +103,7 @@ struct window_procs X11_procs = {
     (WC_COLOR | WC_HILITE_PET | WC_ASCII_MAP | WC_TILED_MAP
      | WC_PLAYER_SELECTION | WC_PERM_INVENT | WC_MOUSE_SUPPORT),
 #if defined(STATUS_HILITES)
-    WC2_FLUSH_STATUS | WC2_RESET_STATUS |
+    WC2_FLUSH_STATUS | WC2_RESET_STATUS | WC2_HILITE_STATUS |
 #endif
     0L,
     X11_init_nhwindows,
@@ -134,8 +134,8 @@ struct window_procs X11_procs = {
     genl_outrip,
 #endif
     X11_preference_update, X11_getmsghistory, X11_putmsghistory,
-    genl_status_init, genl_status_finish, genl_status_enablefield,
-    genl_status_update,
+    X11_status_init, X11_status_finish, X11_status_enablefield,
+    X11_status_update,
     genl_can_suspend_no, /* XXX may not always be correct */
 };
 
@@ -827,9 +827,11 @@ const char *str;
         toplines[TBUFSZ - 1] = 0;
         append_message(wp, str);
         break;
+#ifndef STATUS_HILITES
     case NHW_STATUS:
         adjust_status(wp, str);
         break;
+#endif
     case NHW_MAP:
         impossible("putstr: called on map window \"%s\"", str);
         break;
@@ -1267,6 +1269,8 @@ static XtActionsRec actions[] = {
 static XtResource resources[] = {
     { nhStr("slow"), nhStr("Slow"), XtRBoolean, sizeof(Boolean),
       XtOffset(AppResources *, slow), XtRString, nhStr("True") },
+    { nhStr("fancy_status"), nhStr("Fancy_status"), XtRBoolean, sizeof(Boolean),
+      XtOffset(AppResources *, fancy_status), XtRString, nhStr("True") },
     { nhStr("autofocus"), nhStr("AutoFocus"), XtRBoolean, sizeof(Boolean),
       XtOffset(AppResources *, autofocus), XtRString, nhStr("False") },
     { nhStr("message_line"), nhStr("Message_line"), XtRBoolean,
@@ -2251,7 +2255,7 @@ static int
 input_event(exit_condition)
 int exit_condition;
 {
-    if (WIN_STATUS != WIN_ERR) /* hilighting on the fancy status window */
+    if (appResources.fancy_status && WIN_STATUS != WIN_ERR) /* hilighting on the fancy status window */
         check_turn_events();
     if (WIN_MAP != WIN_ERR) /* make sure cursor is not clipped */
         check_cursor_visibility(&window_list[WIN_MAP]);
@@ -2521,7 +2525,8 @@ init_standard_windows()
      * after the fancy status widget is realized (above, with the game popup),
      * but before it is popped up.
      */
-    null_out_status();
+    if (appResources.fancy_status)
+        null_out_status();
     /*
      * Set the map size to its standard size.  As with the message window
      * above, the map window needs to be set to its constrained size until
index 8eb9469bb77ad4f308b8c4ba6bbac03163626b3e..6ab189189ad142c64687f7ac3a05073ec03b8aa8 100644 (file)
@@ -15,6 +15,7 @@
 #endif
 
 #include <X11/Intrinsic.h>
+#include <X11/IntrinsicP.h>
 #include <X11/StringDefs.h>
 #include <X11/Shell.h>
 #include <X11/Xaw/AsciiText.h>
@@ -22,6 +23,7 @@
 #include <X11/Xaw/Form.h>
 #include <X11/Xaw/Paned.h>
 #include <X11/Xaw/Label.h>
+#include <X11/Xaw/Viewport.h>
 #include <X11/Xatom.h>
 
 #ifdef PRESERVE_NO_SYSV
 #undef PRESERVE_NO_SYSV
 #endif
 
+#include "xwindow.h"
+
 #include "hack.h"
 #include "winX.h"
 
-extern const char *hu_stat[];  /* from eat.c */
-extern const char *enc_stat[]; /* from botl.c */
+/*
+ * Fancy status form entry storage indices.
+ */
+#define F_DUMMY     0
+#define F_STR       1
+#define F_DEX       2
+#define F_CON       3
+#define F_INT       4
+#define F_WIS       5
+#define F_CHA       6
+
+#define F_NAME      7
+#define F_DLEVEL    8
+#define F_GOLD      9
+#define F_HP       10
+#define F_MAXHP    11
+#define F_POWER    12
+#define F_MAXPOWER 13
+#define F_AC       14
+#define F_LEVEL    15
+#define F_EXP      16
+#define F_ALIGN    17
+#define F_TIME     18
+#define F_SCORE    19
+
+/* status conditions grouped by columns; tty orders these differently */
+#define F_STONE    20
+#define F_SLIME    21
+#define F_STRNGL   22
+#define F_FOODPOIS 23
+#define F_TERMILL  24
+
+#define F_HUNGER   25
+#define F_ENCUMBER 26
+#define F_LEV      27
+#define F_FLY      28
+#define F_RIDE     29
+
+#define F_BLIND    30
+#define F_DEAF     31
+#define F_STUN     32
+#define F_CONF     33
+#define F_HALLU    34
+
+#define NUM_STATS 35
 
 static void FDECL(update_fancy_status, (struct xwindow *));
+static void FDECL(update_fancy_status_field, (int));
 static Widget FDECL(create_fancy_status, (Widget, Widget));
 static void FDECL(destroy_fancy_status, (struct xwindow *));
+static void FDECL(create_status_window_fancy, (struct xwindow *, BOOLEAN_P, Widget));
+static void FDECL(create_status_window_tty, (struct xwindow *, BOOLEAN_P, Widget));
+static void FDECL(destroy_status_window_fancy, (struct xwindow *));
+static void FDECL(destroy_status_window_tty, (struct xwindow *));
+static void FDECL(adjust_status_fancy, (struct xwindow *, const char *));
+static void FDECL(adjust_status_tty, (struct xwindow *, const char *));
+
+extern const char *status_fieldfmt[MAXBLSTATS];
+extern char *status_vals[MAXBLSTATS];
+extern boolean status_activefields[MAXBLSTATS];
+static long X11_condition_bits;
+static int X11_status_colors[MAXBLSTATS];
+static int hpbar_percent, hpbar_color;
+
+#define X11_NUM_STATUS_LINES 2
+#define X11_NUM_STATUS_FIELD 15
+
+static enum statusfields X11_fieldorder[X11_NUM_STATUS_LINES][X11_NUM_STATUS_FIELD] = {
+    { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN,
+      BL_SCORE, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH,
+      BL_FLUSH },
+    { BL_LEVELDESC, BL_GOLD, BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX,
+      BL_AC, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_HUNGER,
+      BL_CAP, BL_CONDITION, BL_FLUSH }
+};
+
+static boolean X11_labels_created = FALSE;
+static Widget X11_status_widget;
+static Widget X11_status_labels[MAXBLSTATS];
+static Widget X11_cond_labels[32]; /* Ugh */
+
+static Pixel X11_colors[16];
+static Pixel X11_status_widget_fg, X11_status_widget_bg;
+
+
+int
+condcolor(bm, bmarray)
+long bm;
+unsigned long *bmarray;
+{
+    int i;
+
+    if (bm && bmarray)
+        for (i = 0; i < CLR_MAX; ++i) {
+            if (bmarray[i] && (bm & bmarray[i]))
+                return i;
+        }
+    return NO_COLOR;
+}
+
+int
+condattr(bm, bmarray)
+long bm;
+unsigned long *bmarray;
+{
+    int attr = 0;
+    int i;
+
+    if (bm && bmarray) {
+        for (i = HL_ATTCLR_DIM; i < BL_ATTCLR_MAX; ++i) {
+            if (bmarray[i] && (bm & bmarray[i])) {
+                switch(i) {
+                case HL_ATTCLR_DIM:
+                    attr |= HL_DIM;
+                    break;
+                case HL_ATTCLR_BLINK:
+                    attr |= HL_BLINK;
+                    break;
+                case HL_ATTCLR_ULINE:
+                    attr |= HL_ULINE;
+                    break;
+                case HL_ATTCLR_INVERSE:
+                    attr |= HL_INVERSE;
+                    break;
+                case HL_ATTCLR_BOLD:
+                    attr |= HL_BOLD;
+                    break;
+                }
+            }
+        }
+    }
+    return attr;
+}
+
+void
+X11_status_init()
+{
+#ifdef STATUS_HILITES
+    int i;
+
+    for (i = 0; i < MAXBLSTATS; ++i)
+        X11_status_colors[i] = NO_COLOR; /* no color */
+    X11_condition_bits = 0L;
+    hpbar_percent = 0, hpbar_color = NO_COLOR;
+#endif /* STATUS_HILITES */
+    /* let genl_status_init do most of the initialization */
+    genl_status_init();
+}
+
+void
+X11_status_finish()
+{
+    /* nothing */
+}
+
+void
+X11_status_enablefield(fieldidx, nm, fmt, enable)
+int fieldidx;
+const char *nm;
+const char *fmt;
+boolean enable;
+{
+    genl_status_enablefield(fieldidx, nm, fmt, enable);
+}
+
+
+int
+cond_bm2idx(bm)
+unsigned long bm;
+{
+    int i;
+    for (i = 0; i < 32; i++)
+        if ((1 << i) == bm)
+            return i;
+    return -1;
+}
+
+void
+MaybeDisplayCond(bm, colormasks, text)
+unsigned long bm;
+unsigned long *colormasks;
+const char *text;
+{
+    int idx = cond_bm2idx(bm);
+    Widget label;
+    Arg args[10];
+    Cardinal num_args;
+    Pixel fg = X11_status_widget_fg, bg = X11_status_widget_bg;
+    Dimension lbl_wid;
+    Dimension lbl_hei;
+    Dimension lbl_border_wid;
+    Dimension lbl_iwidth;
+
+    if (idx < 0)
+        return;
+
+    label = X11_cond_labels[idx];
+    if ((X11_condition_bits & bm)) {
+        int attrmask, coloridx;
+        XFontStruct *font;
+        Position lbl_x;
+        Position lbl_y;
+#ifdef TEXTCOLOR
+        coloridx = condcolor(bm, colormasks);
+#endif
+        attrmask = condattr(bm, colormasks);
+        num_args = 0;
+        XtSetArg(args[num_args], nhStr(XtNfont), &font); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNx), &lbl_x); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNy), &lbl_y); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNwidth), &lbl_wid); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNheight), &lbl_hei); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNinternalWidth), &lbl_iwidth); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNborderWidth), &lbl_border_wid); num_args++;
+        XtGetValues(label, args, num_args);
+
+        if (text && *text)
+            lbl_wid = lbl_iwidth + font->max_bounds.width * strlen(text);
+        else
+            lbl_wid = 1;
+
+        num_args = 0;
+        XtSetArg(args[num_args], nhStr(XtNlabel), (text && *text) ? text : ""); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNwidth), lbl_wid); num_args++;
+
+        fg = (coloridx != NO_COLOR) ? X11_colors[coloridx] : X11_status_widget_fg;
+        if (attrmask & HL_INVERSE) {
+            Pixel tmppx = fg;
+            fg = bg;
+            bg = tmppx;
+        }
+        if (fg == bg)
+            fg = X11_colors[CLR_GRAY];
+
+        XtSetArg(args[num_args], nhStr(XtNforeground), fg); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbackground), bg); num_args++;
+        XtSetValues(label, args, num_args);
+        XtResizeWidget(label, lbl_wid, lbl_hei, lbl_border_wid);
+    } else {
+        num_args = 0;
+        XtSetArg(args[num_args], nhStr(XtNwidth), &lbl_wid); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNheight), &lbl_hei); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNinternalWidth), &lbl_iwidth); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNborderWidth), &lbl_border_wid); num_args++;
+        XtGetValues(label, args, num_args);
+
+        num_args = 0;
+        XtSetArg(args[num_args], nhStr(XtNlabel), ""); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNwidth), 1); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNforeground), fg); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbackground), bg); num_args++;
+        XtSetValues(label, args, num_args);
+
+        XtResizeWidget(label, lbl_wid, lbl_hei, lbl_border_wid);
+    }
+}
+
+
+void
+X11_status_update_tty(fld, ptr, chg, percent, color, colormasks)
+int fld, chg UNUSED, percent UNUSED, color;
+genericptr_t ptr;
+unsigned long *colormasks;
+{
+    long *condptr = (long *) ptr;
+    int i, j, attrmask = 0;
+#ifdef TEXTCOLOR
+    int coloridx = NO_COLOR;
+#endif
+    const char *text = (char *) ptr;
+    char tmpbuf[BUFSZ];
+    static boolean oncearound = FALSE; /* prevent premature partial display */
+    int attridx = 0;
+
+    XFontStruct *font;
+    int direction;
+    int ascent;
+    int descent;
+    XCharStruct overall;
+    Arg args[10];
+    Cardinal num_args;
+    Position lbl_x;
+    Position lbl_y;
+    Dimension lbl_wid;
+    Dimension lbl_hei;
+    Dimension lbl_border_wid;
+    Dimension lbl_iwidth;
+    Widget label;
+    Pixel fg = X11_status_widget_fg, bg = X11_status_widget_bg;
+
+    if (fld < BL_RESET || fld >= MAXBLSTATS)
+        return;
+
+    if ((fld >= 0 && fld < MAXBLSTATS) && !status_activefields[fld])
+        return;
+
+    if (fld != BL_FLUSH && fld != BL_RESET) {
+        if (!status_activefields[fld])
+            return;
+        switch (fld) {
+        case BL_CONDITION:
+            X11_condition_bits = *condptr;
+            oncearound = TRUE;
+            break;
+        default:
+            Sprintf(status_vals[fld],
+                    (fld == BL_TITLE && iflags.wc2_hitpointbar) ? "%-30s" :
+                    status_fieldfmt[fld] ? status_fieldfmt[fld] : "%s",
+                    text);
+#ifdef TEXTCOLOR
+            X11_status_colors[fld] = color;
+#else
+            X11_status_colors[fld] = NO_COLOR;
+#endif
+            if (iflags.wc2_hitpointbar && fld == BL_HP) {
+                hpbar_percent = percent;
+#ifdef TEXTCOLOR
+                hpbar_color = color;
+#else
+                hpbar_color = NO_COLOR;
+#endif
+             }
+             break;
+        }
+        if (fld == BL_CONDITION) {
+            MaybeDisplayCond(BL_MASK_STONE, colormasks, "Stone");
+            MaybeDisplayCond(BL_MASK_SLIME, colormasks, "Slime");
+            MaybeDisplayCond(BL_MASK_STRNGL, colormasks, "Strngl");
+            MaybeDisplayCond(BL_MASK_FOODPOIS, colormasks, "FoodPois");
+            MaybeDisplayCond(BL_MASK_TERMILL, colormasks, "TermIll");
+            MaybeDisplayCond(BL_MASK_BLIND, colormasks, "Blind");
+            MaybeDisplayCond(BL_MASK_DEAF, colormasks, "Deaf");
+            MaybeDisplayCond(BL_MASK_STUN, colormasks, "Stun");
+            MaybeDisplayCond(BL_MASK_CONF, colormasks, "Conf");
+            MaybeDisplayCond(BL_MASK_HALLU, colormasks, "Hallu");
+            MaybeDisplayCond(BL_MASK_LEV, colormasks, "Lev");
+            MaybeDisplayCond(BL_MASK_FLY, colormasks, "Fly");
+            MaybeDisplayCond(BL_MASK_RIDE, colormasks, "Ride");
+        } else {
+            label = X11_status_labels[fld];
+            text = status_vals[fld];
+            if (fld == BL_GOLD)
+                text = decode_mixed(tmpbuf, text);
+
+#ifdef TEXTCOLOR
+            coloridx = X11_status_colors[fld] & 0x00FF;
+#endif
+            attridx = (X11_status_colors[fld] & 0xFF00) >> 8;
+
+
+            num_args = 0;
+            XtSetArg(args[num_args], nhStr(XtNfont), &font); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNx), &lbl_x); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNy), &lbl_y); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNwidth), &lbl_wid); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNheight), &lbl_hei); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNinternalWidth), &lbl_iwidth); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNborderWidth), &lbl_border_wid); num_args++;
+            XtGetValues(label, args, num_args);
+
+            /*raw_printf("font: %i-%i", font->min_bounds.width, font->max_bounds.width);*/
+
+            if (text && *text)
+                lbl_wid = lbl_iwidth + font->max_bounds.width * strlen(text);
+            else
+                lbl_wid = 1;
+
+            /*raw_printf("1:lbl_wid=%i('%s')", lbl_wid, text);*/
+
+            num_args = 0;
+            XtSetArg(args[num_args], nhStr(XtNlabel), (text && *text) ? text : ""); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNwidth), lbl_wid); num_args++;
+
+            fg = (coloridx != NO_COLOR) ? X11_colors[coloridx] : X11_status_widget_fg;
+            if (attridx & HL_INVERSE) {
+                Pixel tmppx = fg;
+                fg = bg;
+                bg = tmppx;
+            }
+
+            if (fg == bg)
+                fg = X11_colors[CLR_GRAY];
+
+            XtSetArg(args[num_args], nhStr(XtNforeground), fg); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNbackground), bg); num_args++;
+            XtSetValues(label, args, num_args);
+            XtResizeWidget(label, lbl_wid, lbl_hei, lbl_border_wid);
+        }
+    } else {
+        int x,y;
+        for (y = 0; y < X11_NUM_STATUS_LINES; y++) {
+            Cardinal dx = 0;
+            for (x = 0; x < X11_NUM_STATUS_FIELD; x++) {
+                int f = X11_fieldorder[y][x];
+
+                if (f <= BL_FLUSH)
+                    continue;
+                if (!status_activefields[f])
+                    continue;
+
+                if (f == BL_CONDITION) {
+                    int i;
+
+                    for (i = 0; i < 32; i++) {
+                        label = X11_cond_labels[i];
+
+                        num_args = 0;
+                        XtSetArg(args[num_args], nhStr(XtNx), &lbl_x); num_args++;
+                        XtSetArg(args[num_args], nhStr(XtNy), &lbl_y); num_args++;
+                        XtSetArg(args[num_args], nhStr(XtNwidth), &lbl_wid); num_args++;
+                        XtSetArg(args[num_args], nhStr(XtNheight), &lbl_hei); num_args++;
+                        XtSetArg(args[num_args], nhStr(XtNborderWidth), &lbl_border_wid); num_args++;
+                        XtGetValues(label, args, num_args);
+
+                        lbl_x = dx;
+
+                        num_args = 0;
+                        XtSetArg(args[num_args], nhStr(XtNx), lbl_x); num_args++;
+                        XtSetValues(label, args, num_args);
+                        XtConfigureWidget(label, lbl_x, lbl_y, lbl_wid, lbl_hei, lbl_border_wid);
+
+                        if (lbl_wid > 1)
+                            dx += lbl_wid;
+                    }
+                    continue;
+                }
+                label = X11_status_labels[f];
+
+                text = status_vals[f];
+                if (f == BL_GOLD)
+                    text = decode_mixed(tmpbuf, text);
+
+                num_args = 0;
+                XtSetArg(args[num_args], nhStr(XtNx), &lbl_x); num_args++;
+                XtSetArg(args[num_args], nhStr(XtNy), &lbl_y); num_args++;
+                XtSetArg(args[num_args], nhStr(XtNwidth), &lbl_wid); num_args++;
+                XtSetArg(args[num_args], nhStr(XtNheight), &lbl_hei); num_args++;
+                XtSetArg(args[num_args], nhStr(XtNborderWidth), &lbl_border_wid); num_args++;
+                XtGetValues(label, args, num_args);
+
+                lbl_x = dx;
+                /*raw_printf("2:lbl_wid=%i('%s')", lbl_wid, text);*/
+
+                num_args = 0;
+                XtSetArg(args[num_args], nhStr(XtNx), lbl_x); num_args++;
+                XtSetArg(args[num_args], nhStr(XtNlabel), text); num_args++;
+                XtSetValues(label, args, num_args);
+                XtConfigureWidget(label, lbl_x, lbl_y, lbl_wid, lbl_hei, lbl_border_wid);
+
+                dx += lbl_wid;
+            }
+        }
+    }
+}
+
+void
+X11_status_update_fancy(fld, ptr, chg, percent, color, colormasks)
+int fld, chg UNUSED, percent UNUSED, color;
+genericptr_t ptr;
+unsigned long *colormasks;
+{
+    int i;
+    struct {
+        int bl, ff;
+    } bl_to_fancyfield[] = {
+        { BL_TITLE, F_NAME },
+        { BL_STR, F_STR },
+        { BL_DX, F_DEX },
+        { BL_CO, F_CON },
+        { BL_IN, F_INT },
+        { BL_WI, F_WIS },
+        { BL_CH, F_CHA },
+        { BL_ALIGN, F_ALIGN },
+        { BL_SCORE, F_SCORE },
+        { BL_CAP, F_ENCUMBER },
+        { BL_GOLD, F_GOLD },
+        { BL_ENE, F_POWER },
+        { BL_ENEMAX, F_MAXPOWER },
+        { BL_XP, F_LEVEL },
+        { BL_AC, F_AC },
+        /*{ BL_HD, F_ },*/
+        { BL_TIME, F_TIME },
+        { BL_HUNGER, F_HUNGER },
+        { BL_HP, F_HP },
+        { BL_HPMAX, F_MAXHP },
+        { BL_LEVELDESC, F_DLEVEL },
+        { BL_EXP, F_EXP }
+    };
+
+    struct {
+        long mask;
+        int ff;
+    } mask_to_fancyfield[] = {
+        { BL_MASK_STONE, F_STONE },
+        { BL_MASK_SLIME, F_SLIME },
+        { BL_MASK_STRNGL, F_STRNGL },
+        { BL_MASK_FOODPOIS, F_FOODPOIS },
+        { BL_MASK_TERMILL, F_TERMILL },
+        { BL_MASK_BLIND, F_BLIND },
+        { BL_MASK_DEAF, F_DEAF },
+        { BL_MASK_STUN, F_STUN },
+        { BL_MASK_CONF, F_CONF },
+        { BL_MASK_HALLU, F_HALLU },
+        { BL_MASK_LEV, F_LEV },
+        { BL_MASK_FLY, F_FLY },
+        { BL_MASK_RIDE, F_RIDE }
+    };
+
+    if (fld == BL_RESET || fld == BL_FLUSH) {
+        if (WIN_STATUS != WIN_ERR) {
+            struct xwindow *wp = &window_list[WIN_STATUS];
+            update_fancy_status(wp);
+        }
+        return;
+    }
+
+    if (fld == BL_CONDITION) {
+        unsigned long mask = (unsigned long) ptr;
+
+        for (i = 0; i < SIZE(mask_to_fancyfield); i++)
+            if (mask_to_fancyfield[i].mask == mask)
+                update_fancy_status_field(mask_to_fancyfield[i].ff);
+    } else {
+        for (i = 0; i < SIZE(bl_to_fancyfield); i++)
+            if (bl_to_fancyfield[i].bl == fld)
+                update_fancy_status_field(bl_to_fancyfield[i].ff);
+    }
+}
+
+void
+X11_status_update(fld, ptr, chg, percent, color, colormasks)
+int fld, chg UNUSED, percent UNUSED, color;
+genericptr_t ptr;
+unsigned long *colormasks;
+{
+    if (appResources.fancy_status)
+        X11_status_update_fancy(fld, ptr, chg, percent, color, colormasks);
+    else
+        X11_status_update_tty(fld, ptr, chg, percent, color, colormasks);
+}
+
+
+void
+init_nhcolors(w)
+Widget w;
+{
+    int i;
+    Display *dpy = XtDisplay(w);
+    int defscreen = DefaultScreen(dpy);
+    Colormap cmap = DefaultColormap(dpy, defscreen);
+    const char * resource2clr[16] = {
+        XtNblack,
+        XtNred,
+        XtNgreen,
+        XtNbrown,
+        XtNblue,
+        XtNmagenta,
+        XtNcyan,
+        XtNgray,
+        XtNforeground,
+        XtNorange,
+        XtNbright_green,
+        XtNyellow,
+        XtNbright_blue,
+        XtNbright_magenta,
+        XtNbright_cyan,
+        XtNwhite
+    };
+
+    for (i = 0; i < SIZE(resource2clr); i++) {
+        XColor color, ignore;
+
+        if (XAllocNamedColor(dpy, cmap, resource2clr[i], &color, &ignore))
+            X11_colors[i] = color.pixel;
+        else
+            X11_colors[i] = WhitePixel(dpy, defscreen);
+    }
+}
+
+Widget
+create_tty_status(parent, top)
+Widget parent, top;
+{
+    Widget form; /* The form that surrounds everything. */
+    Widget w;
+    Arg args[16];
+    Cardinal num_args;
+    char buf[32];
+    int i, x, y;
+    Widget testlabel;
+
+    num_args = 0;
+    if (top != (Widget) 0) {
+        XtSetArg(args[num_args], nhStr(XtNfromVert), top);
+        num_args++;
+    }
+    XtSetArg(args[num_args], nhStr(XtNdefaultDistance), 0);
+    num_args++;
+    XtSetArg(args[num_args], XtNborderWidth, 0);
+    num_args++;
+    XtSetArg(args[num_args], XtNwidth, 400); num_args++;
+    XtSetArg(args[num_args], XtNheight, 100); num_args++;
+    form = XtCreateManagedWidget("status_viewport", viewportWidgetClass,
+                                 parent, args, num_args);
+
+    num_args = 0;
+    XtSetArg(args[num_args], XtNwidth, 400); num_args++;
+    XtSetArg(args[num_args], XtNheight, 100); num_args++;
+    w = XtCreateManagedWidget("status_form", formWidgetClass,
+                             form, args, num_args);
+    for (y = 0; y < X11_NUM_STATUS_LINES; y++) {
+        for (x = 0; x < X11_NUM_STATUS_FIELD; x++) {
+            int fld = X11_fieldorder[y][x];
+            char labelname[BUFSZ];
+            int prevfld;
+            if (fld <= BL_FLUSH)
+                continue;
+            Sprintf(labelname, "label_%s", bl_idx_to_fldname(fld));
+            num_args = 0;
+            if (y > 0) {
+                prevfld = X11_fieldorder[y-1][0];
+                XtSetArg(args[num_args], nhStr(XtNfromVert), X11_status_labels[prevfld]); num_args++;
+            }
+            if (x > 0) {
+                prevfld = X11_fieldorder[y][x-1];
+                XtSetArg(args[num_args], nhStr(XtNfromHoriz), X11_status_labels[prevfld]); num_args++;
+            }
+
+            XtSetArg(args[num_args], nhStr(XtNhorizDistance), 0); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNvertDistance), 0); num_args++;
+
+            XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNbottomMargin), 0); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNleftMargin), 0); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNrightMargin), 0); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNborderWidth), 0); num_args++;
+            /*
+            XtSetArg(args[num_args], nhStr(XtNlabel), bl_idx_to_fldname(fld)); num_args++;
+            */
+            XtSetArg(args[num_args], nhStr(XtNlabel), ""); num_args++;
+            X11_status_labels[fld] = XtCreateManagedWidget(labelname,
+                                                           labelWidgetClass, w,
+                                                           args, num_args);
+        }
+     }
+
+    for (i = 0; i < 32; i++) {
+        char condname[BUFSZ];
+        int prevfld;
+
+        Sprintf(condname, "cond_%i", i);
+        num_args = 0;
+
+        prevfld = X11_fieldorder[0][0];
+        XtSetArg(args[num_args], nhStr(XtNfromVert), X11_status_labels[prevfld]); num_args++;
+
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz),
+                 (i == 0) ? X11_status_labels[BL_CONDITION]
+                 : X11_cond_labels[i-1]); num_args++;
+
+        XtSetArg(args[num_args], nhStr(XtNhorizDistance), 0); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNvertDistance), 0); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottomMargin), 0); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleftMargin), 0); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNrightMargin), 0); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNborderWidth), 0); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNlabel), ""); num_args++;
+        X11_cond_labels[i] = XtCreateManagedWidget(condname,
+                                                   labelWidgetClass, w,
+                                                   args, num_args);
+    }
+
+    init_nhcolors(w);
+
+    return w;
+}
+
+void
+create_status_window_tty(wp, create_popup, parent)
+struct xwindow *wp; /* window pointer */
+boolean create_popup;
+Widget parent;
+{
+    Arg args[10];
+    Cardinal num_args;
+
+    wp->type = NHW_STATUS;
+    X11_status_widget = wp->w = create_tty_status(parent, (Widget) 0);
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNforeground), &X11_status_widget_fg); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNbackground), &X11_status_widget_bg); num_args++;
+    XtGetValues(X11_status_widget, args, num_args);
+}
+
+void
+destroy_status_window_tty(wp)
+struct xwindow *wp;
+{
+    /* If status_information is defined, then it a "text" status window. */
+    if (wp->status_information) {
+        if (wp->popup) {
+            nh_XtPopdown(wp->popup);
+            if (!wp->keep_window)
+                XtDestroyWidget(wp->popup), wp->popup = (Widget) 0;
+        }
+        free((genericptr_t) wp->status_information);
+        wp->status_information = 0;
+    } else {
+    }
+    if (!wp->keep_window)
+        wp->type = NHW_NONE;
+}
+
+void
+adjust_status_tty(wp, str)
+struct xwindow *wp;
+const char *str;
+{
+    /* nothing */
+}
 
 void
 create_status_window(wp, create_popup, parent)
 struct xwindow *wp; /* window pointer */
 boolean create_popup;
 Widget parent;
+{
+    if (appResources.fancy_status)
+        create_status_window_fancy(wp, create_popup, parent);
+    else
+        create_status_window_tty(wp, create_popup, parent);
+}
+
+void
+destroy_status_window(wp)
+struct xwindow *wp;
+{
+    if (appResources.fancy_status)
+        destroy_status_window_fancy(wp);
+    else
+        destroy_status_window_tty(wp);
+}
+
+void
+adjust_status(wp, str)
+struct xwindow *wp;
+const char *str;
+{
+    if (appResources.fancy_status)
+        adjust_status_fancy(wp, str);
+    else
+        adjust_status_tty(wp, str);
+}
+
+extern const char *hu_stat[];  /* from eat.c */
+extern const char *enc_stat[]; /* from botl.c */
+
+void
+create_status_window_fancy(wp, create_popup, parent)
+struct xwindow *wp; /* window pointer */
+boolean create_popup;
+Widget parent;
 {
     XFontStruct *fs;
     Arg args[8];
@@ -60,7 +818,7 @@ Widget parent;
          * window.
          */
         if (!parent)
-            panic("create_status_window: no parent for fancy status");
+            panic("create_status_window_fancy: no parent for fancy status");
         wp->status_information = 0;
         wp->w = create_fancy_status(parent, (Widget) 0);
         return;
@@ -133,7 +891,7 @@ Widget parent;
 }
 
 void
-destroy_status_window(wp)
+destroy_status_window_fancy(wp)
 struct xwindow *wp;
 {
     /* If status_information is defined, then it a "text" status window. */
@@ -159,7 +917,7 @@ struct xwindow *wp;
  *     + We didn't set stringInPlace on the widget.
  */
 void
-adjust_status(wp, str)
+adjust_status_fancy(wp, str)
 struct xwindow *wp;
 const char *str;
 {
@@ -216,52 +974,6 @@ static Widget FDECL(init_column, (const char *, Widget, Widget, Widget,
 static void NDECL(fixup_cond_widths);
 static Widget FDECL(init_info_form, (Widget, Widget, Widget));
 
-/*
- * Form entry storage indices.
- */
-#define F_DUMMY     0
-#define F_STR       1
-#define F_DEX       2
-#define F_CON       3
-#define F_INT       4
-#define F_WIS       5
-#define F_CHA       6
-
-#define F_NAME      7
-#define F_DLEVEL    8
-#define F_GOLD      9
-#define F_HP       10
-#define F_MAXHP    11
-#define F_POWER    12
-#define F_MAXPOWER 13
-#define F_AC       14
-#define F_LEVEL    15
-#define F_EXP      16
-#define F_ALIGN    17
-#define F_TIME     18
-#define F_SCORE    19
-
-/* status conditions grouped by columns; tty orders these differently */
-#define F_STONE    20
-#define F_SLIME    21
-#define F_STRNGL   22
-#define F_FOODPOIS 23
-#define F_TERMILL  24
-
-#define F_HUNGER   25
-#define F_ENCUMBER 26
-#define F_LEV      27
-#define F_FLY      28
-#define F_RIDE     29
-
-#define F_BLIND    30
-#define F_DEAF     31
-#define F_STUN     32
-#define F_CONF     33
-#define F_HALLU    34
-
-#define NUM_STATS 35
-
 /*
  * Notes:
  * + Alignment needs a different init value, because -1 is an alignment.
@@ -583,18 +1295,13 @@ long new_value;
  * [**] HD is shown instead of level and exp if Upolyd.
  */
 static void
-update_fancy_status(wp)
-struct xwindow *wp;
+update_fancy_status_field(i)
+int i;
 {
-    struct X_status_value *sv;
+    struct X_status_value *sv = &shown_stats[i];
     long val;
-    int i;
 
-    if (wp->cursy != 0)
-        return; /* do a complete update when line 0 is done */
-
-    for (i = 0, sv = shown_stats; i < NUM_STATS; i++, sv++) {
-        switch (i) {
+    switch (i) {
         case F_DUMMY:
             val = 0L;
             break;
@@ -734,11 +1441,26 @@ struct xwindow *wp;
             val = 0L;
             break;
         } /* default */
-        } /* switch */
-        update_val(sv, val);
-    }
+    } /* switch */
+    update_val(sv, val);
+}
+
+static void
+update_fancy_status(wp)
+struct xwindow *wp;
+{
+    struct X_status_value *sv;
+    long val;
+    int i;
+
+    /*if (wp->cursy != 0)
+      return;*/ /* do a complete update when line 0 is done */
+
+    for (i = 0; i < NUM_STATS; i++)
+        update_fancy_status_field(i);
 }
 
+
 /*
  * Turn off hilighted status values after a certain amount of turns.
  */