I. Window Types and Terminology
-There are 5 basic window types, used to call create_nhwindow():
+There are 4 basic window types, used to call create_nhwindow():
NHW_MESSAGE (top line)
- NHW_STATUS (bottom lines)
NHW_MAP (main dungeon)
NHW_MENU (inventory or other "corner" windows)
NHW_TEXT (help/text, full screen paged window)
The tty window-port also uses NHW_BASE (the base display) internally.
+(The genl_status_* routines use NHW_STATUS for backward compatibility
+ when displaying status information on the bottom lines. New code
+ should not use NHW_STATUS. NHW_STATUS will be phased out over time.)
+
NHW_MENU windows can be used for either menu or text display. Their
basic feature is that for the tty-port, if the window is small enough,
it appears in the corner of the tty display instead of overwriting
a few fixed window names that are known throughout the code:
WIN_MESSAGE (top line)
- WIN_STATUS (bottom lines)
WIN_MAP (main dungeon)
WIN_INVEN (inventory)
Other windows are created and destroyed as needed.
+(The genl_status_* routines use WIN_STATUS for backward compatibility
+ when displaying status information on the bottom lines. New code
+ should not use WIN_STATUS, or assume its presence. NHW_STATUS will
+ be phased out over time.)
+
"Port" in this document refers to a CPU/OS/hardware platform (UNIX, MSDOS
TOS, etc.) "window-port" refers to the windowing platform. This is
orthogonal (e.g. UNIX might use either a tty window-port or an X11
displayable cursor to (x,y). For backward compatibility,
1 <= x < cols, 0 <= y < rows, where cols and rows are
the size of window.
- -- For variable sized windows, like the status window, the
+ -- For variable sized windows, like the old status window, the
behavior when curs() is called outside the window's limits
is unspecified. The mac port wraps to 0, with the status
window being 2 lines high and 80 columns wide.
- -- Still used by curs_on_u(), status updates, screen locating
- (identify, teleport).
+ -- Still used by curs_on_u(), obsolete status updates,
+ screen locating (identify, teleport).
-- NHW_MESSAGE, NHW_MENU and NHW_TEXT windows do not
currently support curs in the tty window-port.
putstr(window, attr, str)
windows typically won't need this functionality, so can
substitute genl_message_menu (windows.c) instead.
-D. Misc. Routines
+D. Status Display Routines
+
+status_init() -- core calls this to notify the window port that a status
+ display is required. The window port should perform
+ the necessary initialization in here, allocate memory, etc.
+status_enablefield(int fldindex, char fldname, char fieldfmt, boolean enable)
+ -- notifies the window port which fields it is authorized to
+ display.
+ -- This may be called at any time, and is used
+ to disable as well as enable fields, depending on the
+ value of the final argument (TRUE = enable).
+ -- fldindex could be one of the following from botl.h:
+ BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
+ BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX,
+ BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX,
+ BL_LEVELDESC, BL_EXP, BL_CONDITION
+ -- There are MAXBLSTATS status fields (from botl.h)
+status_update(int fldindex, genericptr_t ptr, int chg, int percentage)
+ -- update the value of a status field
+ -- the fldindex identifies which field is changing and
+ is an integer index value from botl.h
+ -- fldindex could be any one of the following from botl.h:
+ BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
+ BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX,
+ BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX,
+ BL_LEVELDESC, BL_EXP, BL_CONDITION,
+ -- fldindex could also be BL_FLUSH (-1), which is not really
+ a field index, but is a special trigger to tell the
+ windowport that it should redisplay all its status fields,
+ even if no changes have been presented to it.
+ -- ptr is usually a "char *", unless fldindex is BL_CONDITION.
+ If fldindex is BL_CONDITION, then ptr is a long value with
+ any or none of the following bits set (from botl.h):
+ BL_MASK_BLIND 0x00000001L
+ BL_MASK_CONF 0x00000002L
+ BL_MASK_FOODPOIS 0x00000004L
+ BL_MASK_ILL 0x00000008L
+ BL_MASK_HALLU 0x00000010L
+ BL_MASK_STUNNED 0x00000020L
+ BL_MASK_SLIMED 0x00000040L
+status_finish() -- called when it is time for the window port to tear down
+ the status display and free allocated memory, etc.
+
+
+E. Misc. Routines
make_sound(???) -- To be determined later. THIS IS CURRENTLY UN-IMPLEMENTED.
nhbell() -- Beep at user. [This will exist at least until sounds are
char toplines[BUFSZ] Contains the last message printed to the WIN_MESSAGE
window, used by Norep().
-winid WIN_MESSAGE, WIN_MAP, WIN_STATUS, WIN_INVEN
- The four standard windows.
+winid WIN_MESSAGE, WIN_MAP, WIN_INVEN
+ The three standard windows.
+ There is also a window called WIN_STATUS that is used
+ only for backward compatibility in the genl_status_*
+ set of generic status display functions.
char *AE, *AS; Checked in options.c to see if we should switch
to DEC_GRAPHICS. It is #ifdefed VMS and UNIX.
int LI, CO; Set in sys/unix/ioctl.c.
+--------------------+--------------------+--------------------+--------+
align_message -- where to place message window (top, bottom, left, right)
-align_status -- where to place status window (top, bottom, left, right).
+align_status -- where to place status display (top, bottom, left, right).
ascii_map -- port should display an ascii map if it can.
color -- port should display color if it can.
eight_bit_tty -- port should allow eight bit input.
font_size_menu -- port should use this size font for menu windows.
font_size_message
-- port should use this size font for the message window.
-font_size_status-- port should use this size font for the status window.
+font_size_status-- port should use this size font for the status display.
font_size_text -- port should use this size font for text windows.
-font_status -- port should use a font by this name for status window.
+font_status -- port should use a font by this name for status display.
font_text -- port should use a font by this name for text windows.
fullscreen -- port should try to use the whole screen.
hilite_pet -- port should mark pets in some special way on the map.
raw_print() will not fail. Choose_windows() should be called almost
immediately upon entering main(). Look at unixmain.c for an example.
-Display_gamewindows() is a common routine that displays the three standard
-game windows (WIN_MESSAGE, WIN_MAP, and WIN_STATUS). It is normally called
-just before the "Hello, welcome" message.
+Display_gamewindows() is a common routine that displays the two standard
+game windows (WIN_MESSAGE, WIN_MAP), and the status display. It is normally
+called just before the "Hello, welcome" message.
Process_options() is currently still unique to each port. There may be need
in the future to make it possible to replace this on a per window-port basis.
"Overloaded"
};
+#ifdef STATUS_VIA_WINDOWPORT
+STATIC_OVL void NDECL(init_blstats);
+#else
STATIC_DCL void NDECL(bot1);
STATIC_DCL void NDECL(bot2);
+#endif
/* MAXCO must hold longest uncompressed status line, and must be larger
* than COLNO
}
#endif
+#ifndef STATUS_VIA_WINDOWPORT
STATIC_OVL void
bot1()
{
char newbot1[MAXCO];
register char *nb;
register int i,j;
-
Strcpy(newbot1, plname);
if('a' <= newbot1[0] && newbot1[0] <= 'z') newbot1[0] += 'A'-'a';
newbot1[10] = 0;
curs(WIN_STATUS, 1, 0);
putstr(WIN_STATUS, 0, newbot1);
}
+#endif
/* provide the name of the current level for display by various ports */
int
return ret;
}
+#ifndef STATUS_VIA_WINDOWPORT
STATIC_OVL void
bot2()
{
context.botl = context.botlx = 0;
}
+#else /* STATUS_VIA_WINDOWPORT */
+
+/* These are used within botl.c only */
+#define P_MASK 1
+#define P_STR 2
+#define P_INT 3
+#define P_LNG 4
+#define P_UINT 5
+
+struct istat_s {
+ long time;
+ unsigned ptype;
+ anything ptr;
+ char *val;
+ int valwidth;
+ int idxmax;
+};
+
+#define percentage(current, maximum) ((100 * current) / maximum)
+#define percentagel(current, maximum) ((int)((100L * current) / maximum))
+
+/* If entries are added to this, botl.h will required updating too */
+struct istat_s blstats[2][MAXBLSTATS] = {
+ {
+ { 0L, P_STR, (genericptr_t)0, (char *)0, 80, 0}, /* 0 BL_TITLE */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 6, 0}, /* 1 BL_STR */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 6, 0}, /* 2 BL_DX */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 6, 0}, /* 3 BL_CO */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 6, 0}, /* 4 BL_IN */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 6, 0}, /* 5 BL_WI */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 6, 0}, /* 6 BL_CH */
+ { 0L, P_STR, (genericptr_t)0, (char *)0, 8, 0}, /* 7 BL_ALIGN */
+ { 0L, P_LNG, (genericptr_t)0, (char *)0, 20, 0}, /* 8 BL_SCORE */
+ { 0L, P_LNG, (genericptr_t)0, (char *)0, 20, 0}, /* 9 BL_CAP */
+ { 0L, P_LNG, (genericptr_t)0, (char *)0, 8, 0}, /* 10 BL_GOLD */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 6, BL_ENEMAX}, /* 11 BL_ENE */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 6, 0}, /* 12 BL_ENEMAX */
+ { 0L, P_LNG, (genericptr_t)0, (char *)0, 6, 0}, /* 13 BL_XP */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 6, 0}, /* 14 BL_AC */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 6, 0}, /* 15 BL_HD */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 10, 0}, /* 16 BL_TIME */
+ { 0L, P_UINT,(genericptr_t)0, (char *)0, 20, 0}, /* 17 BL_HUNGER */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 10,BL_HPMAX}, /* 18 BL_HP */
+ { 0L, P_INT, (genericptr_t)0, (char *)0, 10, 0}, /* 19 BL_HPMAX */
+ { 0L, P_STR, (genericptr_t)0, (char *)0, 80, 0}, /* 20 BL_LEVELDESC */
+ { 0L, P_LNG, (genericptr_t)0, (char *)0, 20, 0}, /* 21 BL_EXP */
+ { 0L, P_MASK,(genericptr_t)0, (char *)0, 0, 0}, /* 22 BL_CONDITION */
+ }
+};
+
+static boolean update_all = FALSE;
+
+void
+status_initialize(reassessment)
+boolean reassessment; /* TRUE = just reassess fields w/o other initialization*/
+{
+ int i;
+ const char *fieldfmts[] = {
+ "%s"," St:%s"," Dx:%s"," Co:%s"," In:%s"," Wi:%s"," Ch:%s",
+ " %s"," S:%s"," %s"," %s"," Pw:%s", "(%s)"," Xp:%s", " AC:%s",
+ " HD:%s"," T:%s"," %s"," HP:%s","(%s)","%s","/%s","%s"
+ };
+ const char *fieldnames[] = {
+ "title", "strength", "dexterity", "constitution", "intelligence",
+ "wisdom", "charisma", "alignment", "score", "capacity",
+ "gold", "power", "power-max", "experience-level", "armor-class",
+ "HD", "time", "hunger", "hitpoints", "hitpoints-max",
+ "dungeon-level", "experience", "condition"
+ };
+ if (!reassessment) {
+ init_blstats();
+ (*windowprocs.win_status_init)();
+ }
+ for (i = 0; i < MAXBLSTATS; ++i) {
+ if ((i == BL_SCORE && !flags.showscore) ||
+ (i == BL_EXP && !flags.showexp) ||
+ (i == BL_TIME && !flags.time))
+ status_enablefield(i, fieldnames[i], fieldfmts[i], FALSE);
+ else
+ status_enablefield(i, fieldnames[i], fieldfmts[i], TRUE);
+ }
+ update_all = TRUE;
+}
+
+void
+status_finish()
+{
+ int i;
+
+ /* call the window port cleanup routine first */
+ (*windowprocs.win_status_finish)();
+
+ /* free memory that we alloc'd now */
+ for (i = 0; i < MAXBLSTATS; ++i) {
+ free(blstats[0][i].ptr.a_void);
+ free(blstats[1][i].ptr.a_void);
+ if (blstats[0][i].val) free((genericptr_t)blstats[0][i].val);
+ if (blstats[1][i].val) free((genericptr_t)blstats[1][i].val);
+ }
+}
+
+STATIC_OVL void
+init_blstats()
+{
+ int i;
+
+ for (i = 0; i < MAXBLSTATS; ++i) {
+ switch(blstats[0][i].ptype) {
+ case P_INT:
+ blstats[0][i].ptr.a_iptr = (int *)alloc(sizeof(int));
+ blstats[1][i].ptr.a_iptr = (int *)alloc(sizeof(int));
+ *blstats[0][i].ptr.a_iptr = 0;
+ *blstats[1][i].ptr.a_iptr = 0;
+ break;
+ case P_LNG:
+ case P_MASK:
+ blstats[0][i].ptr.a_lptr = (long *)alloc(sizeof(long));
+ blstats[1][i].ptr.a_lptr = (long *)alloc(sizeof(long));
+ *blstats[0][i].ptr.a_lptr = 0L;
+ *blstats[1][i].ptr.a_lptr = 0L;
+ break;
+ case P_UINT:
+ blstats[0][i].ptr.a_uptr = (unsigned *)alloc(sizeof(unsigned));
+ blstats[1][i].ptr.a_uptr = (unsigned *)alloc(sizeof(unsigned));
+ *blstats[0][i].ptr.a_uptr = 0;
+ *blstats[1][i].ptr.a_uptr = 0;
+ break;
+ }
+ if (blstats[0][i].valwidth) {
+ blstats[0][i].val = (char *)alloc(blstats[0][i].valwidth);
+ blstats[1][i].val = (char *)alloc(blstats[0][i].valwidth);
+ } else {
+ blstats[0][i].val = (char *)0;
+ blstats[1][i].val = (char *)0;
+ }
+ blstats[1][i].ptype = blstats[0][i].ptype;
+ }
+}
+
+void
+bot()
+{
+ char buf[BUFSZ];
+ register char *nb;
+ static boolean init = FALSE;
+ static int idx = 0, idx_p, idxmax;
+ boolean updated = FALSE;
+ unsigned ptype;
+ int i, pc, cap = near_capacity();
+ anything curr, prev;
+ boolean valset[MAXBLSTATS];
+
+ idx = (++idx % 2);
+ idx_p = ((idx+1) % 2);
+
+ /* clear the "value set" indicators */
+ (void) memset((genericptr_t)valset, 0, MAXBLSTATS * sizeof(boolean));
+
+ /*
+ * Player name and title.
+ */
+ buf[0] = '\0';
+ Strcpy(buf, plname);
+ if('a' <= buf[0] && buf[0] <= 'z') buf[0] += 'A'-'a';
+ buf[10] = 0;
+ Sprintf(nb = eos(buf)," the ");
+ if (Upolyd) {
+ char mbot[BUFSZ];
+ int k = 0;
+
+ Strcpy(mbot, mons[u.umonnum].mname);
+ while(mbot[k] != 0) {
+ if ((k == 0 || (k > 0 && mbot[k-1] == ' ')) &&
+ 'a' <= mbot[k] && mbot[k] <= 'z')
+ mbot[k] += 'A' - 'a';
+ k++;
+ }
+ Sprintf(nb = eos(nb), mbot);
+ } else
+ Sprintf(nb = eos(nb), rank());
+ Sprintf(blstats[idx][BL_TITLE].val, "%-29s", buf);
+
+ /* Strength */
+
+ buf[0] = '\0';
+ *(blstats[idx][BL_STR].ptr.a_iptr) = ACURR(A_STR);
+ if (ACURR(A_STR) > 18) {
+ if (ACURR(A_STR) > STR18(100))
+ Sprintf(buf,"%2d",ACURR(A_STR)-100);
+ else if (ACURR(A_STR) < STR18(100))
+ Sprintf(buf, "18/%02d",ACURR(A_STR)-18);
+ else
+ Sprintf(buf,"18/**");
+ } else
+ Sprintf(buf, "%-1d",ACURR(A_STR));
+ Strcpy(blstats[idx][BL_STR].val, buf);
+ valset[BL_STR] = TRUE; /* indicate val already set */
+
+
+ /* Dexterity, constitution, intelligence, wisdom, charisma. */
+
+ *(blstats[idx][BL_DX].ptr.a_iptr) = ACURR(A_DEX);
+ *(blstats[idx][BL_CO].ptr.a_iptr) = ACURR(A_CON);
+ *(blstats[idx][BL_IN].ptr.a_iptr) = ACURR(A_INT);
+ *(blstats[idx][BL_WI].ptr.a_iptr) = ACURR(A_WIS);
+ *(blstats[idx][BL_CH].ptr.a_iptr) = ACURR(A_CHA);
+
+ /* Alignment */
+
+ Sprintf(blstats[idx][BL_ALIGN].val,
+ (u.ualign.type == A_CHAOTIC) ? "Chaotic" :
+ (u.ualign.type == A_NEUTRAL) ? "Neutral" : "Lawful");
+
+ /* Score */
+
+ *(blstats[idx][BL_SCORE].ptr.a_lptr) =
+#ifdef SCORE_ON_BOTL
+ botl_score();
+#else
+ 0;
+#endif
+ /* Hit points */
+
+ *(blstats[idx][BL_HP].ptr.a_iptr) = Upolyd ? u.mh : u.uhp;
+ *(blstats[idx][BL_HPMAX].ptr.a_iptr) = Upolyd ? u.mhmax : u.uhpmax;
+ if( *(blstats[idx][BL_HP].ptr.a_iptr) < 0)
+ *(blstats[idx][BL_HP].ptr.a_iptr) = 0;
+
+ /* Dungeon level. */
+
+ (void) describe_level(blstats[idx][BL_LEVELDESC].val);
+
+ /* Gold */
+
+ *(blstats[idx][BL_GOLD].ptr.a_lptr) =
+#ifndef GOLDOBJ
+ u.ugold;
+#else
+ money_cnt(invent);
+#endif
+ Sprintf(blstats[idx][BL_GOLD].val, "%c:%ld",
+ oc_syms[COIN_CLASS], *(blstats[idx][BL_GOLD].ptr.a_lptr));
+ valset[BL_GOLD] = TRUE; /* indicate val already set */
+
+ /* Power (magical energy) */
+
+ *(blstats[idx][BL_ENE].ptr.a_iptr) = u.uen;
+ *(blstats[idx][BL_ENEMAX].ptr.a_iptr) = u.uenmax;
+
+ /* Armor class */
+
+ *(blstats[idx][BL_AC].ptr.a_iptr) = u.uac;
+
+ /* Monster level (if Upolyd) */
+
+ if (Upolyd)
+ *(blstats[idx][BL_HD].ptr.a_iptr) = mons[u.umonnum].mlevel;
+ else
+ *(blstats[idx][BL_HD].ptr.a_iptr) = 0;
+
+ /* Experience */
+
+ *(blstats[idx][BL_XP].ptr.a_iptr) = u.ulevel;
+ *(blstats[idx][BL_EXP].ptr.a_lptr) = u.uexp;
+
+ /* Time (moves) */
+
+ *(blstats[idx][BL_TIME].ptr.a_lptr) = moves;
+
+ /* Hunger */
+
+ *(blstats[idx][BL_HUNGER].ptr.a_uptr) = u.uhs;
+ *(blstats[idx][BL_HUNGER].val) = '\0';
+ if(strcmp(hu_stat[u.uhs], " ") != 0)
+ Strcpy(blstats[idx][BL_HUNGER].val, hu_stat[u.uhs]);
+ valset[BL_HUNGER] = TRUE;
+
+ /* Carrying capacity */
+
+ *(blstats[idx][BL_CAP].val) = '\0';
+ *(blstats[idx][BL_CAP].ptr.a_iptr) = cap;
+ if(cap > UNENCUMBERED)
+ Strcpy(blstats[idx][BL_CAP].val, enc_stat[cap]);
+ valset[BL_CAP] = TRUE;
+
+ /* Conditions */
+
+ if (Blind) *(blstats[idx][BL_CONDITION].ptr.a_lptr) |= BL_MASK_BLIND;
+ else *(blstats[idx][BL_CONDITION].ptr.a_lptr) &= ~BL_MASK_BLIND;
+
+ if (Confusion) *(blstats[idx][BL_CONDITION].ptr.a_lptr) |= BL_MASK_CONF;
+ else *(blstats[idx][BL_CONDITION].ptr.a_lptr) &= ~BL_MASK_CONF;
+
+ if (Sick && u.usick_type & SICK_VOMITABLE)
+ *(blstats[idx][BL_CONDITION].ptr.a_lptr) |= BL_MASK_FOODPOIS;
+ else *(blstats[idx][BL_CONDITION].ptr.a_lptr) &= ~BL_MASK_FOODPOIS;
+
+ if (Sick && u.usick_type & SICK_NONVOMITABLE)
+ *(blstats[idx][BL_CONDITION].ptr.a_lptr) |= BL_MASK_ILL;
+ else *(blstats[idx][BL_CONDITION].ptr.a_lptr) &= ~BL_MASK_ILL;
+
+ if (Hallucination) *(blstats[idx][BL_CONDITION].ptr.a_lptr) |= BL_MASK_HALLU;
+ else *(blstats[idx][BL_CONDITION].ptr.a_lptr) &= ~BL_MASK_HALLU;
+
+ if (Stunned) *(blstats[idx][BL_CONDITION].ptr.a_lptr) |= BL_MASK_STUNNED;
+ else *(blstats[idx][BL_CONDITION].ptr.a_lptr) &= ~BL_MASK_STUNNED;
+
+ if (Slimed) *(blstats[idx][BL_CONDITION].ptr.a_lptr) |= BL_MASK_SLIMED;
+ else *(blstats[idx][BL_CONDITION].ptr.a_lptr) &= ~BL_MASK_SLIMED;
+
+ /*
+ * Now pass the changed values to window port.
+ */
+ for (i = 0; i < MAXBLSTATS; i++) {
+ if (((i == BL_SCORE) && !flags.showscore) ||
+ ((i == BL_EXP) && !flags.showexp) ||
+ ((i == BL_TIME) && !flags.time) ||
+ ((i == BL_HD) && !Upolyd))
+ continue;
+ ptype = blstats[idx][i].ptype;
+ switch (ptype) {
+ case P_INT:
+ curr.a_iptr = blstats[idx][i].ptr.a_iptr;
+ prev.a_iptr = blstats[idx_p][i].ptr.a_iptr;
+ if (update_all || (*curr.a_iptr != *prev.a_iptr)) {
+ idxmax = blstats[idx][i].idxmax;
+ pc = (idxmax) ? percentage(*curr.a_iptr,
+ *(blstats[idx][idxmax].ptr.a_iptr)) : 0;
+ if (!valset[i])
+ Sprintf(blstats[idx][i].val,
+ "%d", *curr.a_iptr);
+ status_update(i,
+ (genericptr_t)blstats[idx][i].val,
+ (update_all || *curr.a_iptr > *prev.a_iptr) ?
+ 1 : -1, pc);
+ updated = TRUE;
+ }
+ break;
+ case P_LNG:
+ curr.a_lptr = blstats[idx][i].ptr.a_lptr;
+ prev.a_lptr = blstats[idx_p][i].ptr.a_lptr;
+ if (update_all || (*curr.a_lptr != *prev.a_lptr)) {
+ idxmax = blstats[idx][i].idxmax;
+ pc = (idxmax) ? percentagel(*curr.a_lptr,
+ *(blstats[idx][idxmax].ptr.a_lptr)) : 0;
+ if (!valset[i])
+ Sprintf(blstats[idx][i].val,
+ "%-1ld", *curr.a_lptr);
+ status_update(i,
+ (genericptr_t)blstats[idx][i].val,
+ (update_all || *curr.a_lptr > *prev.a_lptr) ?
+ 1 : -1, pc);
+ updated = TRUE;
+ }
+ break;
+ case P_UINT:
+ curr.a_uptr = blstats[idx][i].ptr.a_uptr;
+ prev.a_uptr = blstats[idx_p][i].ptr.a_uptr;
+ if (update_all || (*curr.a_uptr != *prev.a_uptr)) {
+ /*
+ * idxmax = blstats[idx][i].idxmax);
+ * pc = (idxmax) ? percentage(*curr.a_uptr,
+ * *(blstats[idx][idxmax].ptr.a_uptr)) : 0;
+ * status_via_win(i, val,
+ * (*curr.a_uptr > *prev.a_uptr) ? 1 : -1, pc);
+ */
+ if (!valset[i])
+ Sprintf(blstats[idx][i].val,
+ "%u", *curr.a_uptr);
+ status_update(i,
+ (genericptr_t)blstats[idx][i].val,
+ (update_all || *curr.a_uptr > *prev.a_uptr) ?
+ 1 : -1, 0);
+ updated = TRUE;
+ }
+ break;
+ case P_STR:
+ if (update_all ||
+ strcmp(blstats[idx][i].val, blstats[idx_p][i].val)) {
+ status_update(i,
+ (genericptr_t) blstats[idx][i].val,0,0);
+ updated = TRUE;
+ }
+ break;
+ case P_MASK:
+ curr.a_lptr = blstats[idx][i].ptr.a_lptr;
+ prev.a_lptr = blstats[idx_p][i].ptr.a_lptr;
+ if (update_all || (*curr.a_lptr != *prev.a_lptr)) {
+ status_update(i,
+ /* send the actual mask, not a pointer to it */
+ (genericptr_t)*curr.a_lptr,0,0);
+ updated = TRUE;
+ }
+ break;
+ }
+ }
+ /*
+ * It is possible to get here, with nothing having been pushed
+ * to the window port, when none of the info has changed. In that
+ * case, we need to force a call to status_update() when
+ * context.botlx is set. The tty port in particular has a problem
+ * if that isn't done, since it sets context.botlx when a menu or
+ * text display obliterates the status line.
+ *
+ * To work around it, we call status_update() with ficticious
+ * index of BL_FLUSH (-1).
+ */
+ if (context.botlx && !updated)
+ status_update(BL_FLUSH,(genericptr_t)0,0,0);
+
+ context.botl = context.botlx = 0;
+ update_all = FALSE;
+}
+
+/*****************************************************************************/
+/* genl backward compat stuff - probably doesn't belong in botl.c any longer */
+/*****************************************************************************/
+
+const char *fieldnm[MAXBLSTATS];
+const char *fieldfmt[MAXBLSTATS];
+char *vals[MAXBLSTATS];
+boolean activefields[MAXBLSTATS];
+NEARDATA winid WIN_STATUS;
+
+void
+genl_status_init()
+{
+ int i;
+ for (i = 0; i < MAXBLSTATS; ++i) {
+ vals[i] = (char *)alloc(MAXCO);
+ *vals[i] = '\0';
+ activefields[i] = FALSE;
+ fieldfmt[i] = FALSE;
+ }
+ /* Use a window for the genl version; backward port compatibility */
+ WIN_STATUS = create_nhwindow(NHW_STATUS);
+ display_nhwindow(WIN_STATUS, FALSE);
+}
+
+void
+genl_status_finish()
+{
+ /* tear down routine */
+ int i;
+
+ /* free alloc'd memory here */
+ for (i = 0; i < MAXBLSTATS; ++i)
+ free((genericptr_t)vals[i]);
+}
+
+void
+genl_status_enablefield(fieldidx, nm, fmt, enable)
+int fieldidx;
+const char *nm;
+const char *fmt;
+boolean enable;
+{
+ fieldfmt[fieldidx] = fmt;
+ fieldnm[fieldidx] = nm;
+ activefields[fieldidx] = enable;
+}
+
+void
+genl_status_update(idx, ptr, chg, percent)
+int idx, chg, percent;
+genericptr_t ptr;
+{
+ char newbot1[MAXCO], newbot2[MAXCO];
+ static int init = FALSE;
+ long cond;
+ register int i;
+ int fieldorder1[] = {
+ BL_TITLE, BL_STR, BL_DX,BL_CO, BL_IN,
+ BL_WI, BL_CH,BL_ALIGN, BL_SCORE, -1
+ };
+ int fieldorder2[] = {
+ BL_LEVELDESC, BL_GOLD, BL_HP, BL_HPMAX,
+ BL_ENE, BL_ENEMAX, BL_AC, BL_XP, BL_EXP, BL_TIME,
+ BL_HUNGER,BL_CAP, BL_CONDITION, -1
+ };
+
+ if (idx != BL_FLUSH) {
+ if (!activefields[idx]) return;
+ switch(idx) {
+ case BL_CONDITION:
+ cond = (long)ptr;
+ *vals[idx] = '\0';
+ if (cond & BL_MASK_BLIND) Strcat(vals[idx], " Blind");
+ if (cond & BL_MASK_CONF) Strcat(vals[idx], " Conf");
+ if (cond & BL_MASK_FOODPOIS)
+ Strcat(vals[idx], " FoodPois");
+ if (cond & BL_MASK_ILL) Strcat(vals[idx], " Ill");
+ if (cond & BL_MASK_STUNNED) Strcat(vals[idx], " Hallu");
+ if (cond & BL_MASK_HALLU) Strcat(vals[idx], " Stun");
+ if (cond & BL_MASK_SLIMED) Strcat(vals[idx], " Slime");
+ break;
+ default:
+ (void) Sprintf(vals[idx],
+ fieldfmt[idx] ? fieldfmt[idx] : "%s",
+ (char *)ptr, MAXCO);
+ break;
+ }
+ }
+
+ /* This genl version updates everything on the display, evertime */
+ newbot1[0] = '\0';
+ for (i = 0; fieldorder1[i] >= 0; ++i) {
+ int idx = fieldorder1[i];
+ if (activefields[idx])
+ Strcat(newbot1, vals[idx]);
+ }
+ newbot2[0] = '\0';
+ for (i = 0; fieldorder2[i] >= 0; ++i) {
+ int idx = fieldorder2[i];
+ if (activefields[idx])
+ Strcat(newbot2, vals[idx]);
+ }
+ curs(WIN_STATUS, 1, 0);
+ putstr(WIN_STATUS, 0, newbot1);
+ curs(WIN_STATUS, 1, 1);
+ putstr(WIN_STATUS, 0, newbot2);
+}
+#endif /*STATUS_VIA_WINDOWPORT*/
+
/*botl.c*/
+
+