Source:NetHack 3.6.1/src/botl.c

From NetHackWiki
(Redirected from Botl.c)
Jump to: navigation, search

Below is the full text to botl.c from the source code of NetHack 3.6.1. To link to a particular line, write [[Source:NetHack 3.6.1/src/botl.c#line123]], for example.

Top of file

  1.  /* NetHack 3.6	botl.c	$NHDT-Date: 1506903619 2017/10/02 00:20:19 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.81 $ */
  2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  /*-Copyright (c) Michael Allison, 2006. */
  4.  /* NetHack may be freely redistributed.  See license for details. */

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

  1.  
  2.  #include "hack.h"
  3.  #include <limits.h>
  4.  
  5.  extern const char *hu_stat[]; /* defined in eat.c */
  6.  
  7.  const char *const enc_stat[] = { "",         "Burdened",  "Stressed",
  8.                                   "Strained", "Overtaxed", "Overloaded" };
  9.  
  10.  STATIC_OVL NEARDATA int mrank_sz = 0; /* loaded by max_rank_sz (from u_init) */
  11.  STATIC_DCL const char *NDECL(rank);
  12.  #ifdef STATUS_HILITES
  13.  STATIC_DCL void NDECL(bot_via_windowport);
  14.  #endif
  15.  

get_strength_str

  1.  static char *
  2.  get_strength_str()
  3.  {
  4.      static char buf[32];
  5.      int st = ACURR(A_STR);
  6.  
  7.      if (st > 18) {
  8.          if (st > STR18(100))
  9.              Sprintf(buf, "%2d", st - 100);
  10.          else if (st < STR18(100))
  11.              Sprintf(buf, "18/%02d", st - 18);
  12.          else
  13.              Sprintf(buf, "18/**");
  14.      } else
  15.          Sprintf(buf, "%-1d", st);
  16.  
  17.      return buf;
  18.  }
  19.  

do_statusline1

  1.  char *
  2.  do_statusline1()
  3.  {
  4.      static char newbot1[BUFSZ];
  5.      register char *nb;
  6.      register int i, j;
  7.  
  8.      Strcpy(newbot1, plname);
  9.      if ('a' <= newbot1[0] && newbot1[0] <= 'z')
  10.          newbot1[0] += 'A' - 'a';
  11.      newbot1[10] = 0;
  12.      Sprintf(nb = eos(newbot1), " the ");
  13.  
  14.      if (Upolyd) {
  15.          char mbot[BUFSZ];
  16.          int k = 0;
  17.  
  18.          Strcpy(mbot, mons[u.umonnum].mname);
  19.          while (mbot[k] != 0) {
  20.              if ((k == 0 || (k > 0 && mbot[k - 1] == ' ')) && 'a' <= mbot[k]
  21.                  && mbot[k] <= 'z')
  22.                  mbot[k] += 'A' - 'a';
  23.              k++;
  24.          }
  25.          Strcpy(nb = eos(nb), mbot);
  26.      } else
  27.          Strcpy(nb = eos(nb), rank());
  28.  
  29.      Sprintf(nb = eos(nb), "  ");
  30.      i = mrank_sz + 15;
  31.      j = (int) ((nb + 2) - newbot1); /* strlen(newbot1) but less computation */
  32.      if ((i - j) > 0)
  33.          Sprintf(nb = eos(nb), "%*s", i - j, " "); /* pad with spaces */
  34.  
  35.      Sprintf(nb = eos(nb), "St:%s Dx:%-1d Co:%-1d In:%-1d Wi:%-1d Ch:%-1d",
  36.              get_strength_str(),
  37.              ACURR(A_DEX), ACURR(A_CON), ACURR(A_INT), ACURR(A_WIS),
  38.              ACURR(A_CHA));
  39.      Sprintf(nb = eos(nb),
  40.              (u.ualign.type == A_CHAOTIC)
  41.                  ? "  Chaotic"
  42.                  : (u.ualign.type == A_NEUTRAL) ? "  Neutral" : "  Lawful");
  43.  #ifdef SCORE_ON_BOTL
  44.      if (flags.showscore)
  45.          Sprintf(nb = eos(nb), " S:%ld", botl_score());
  46.  #endif
  47.      return newbot1;
  48.  }
  49.  

check_gold_symbol

  1.  void
  2.  check_gold_symbol()
  3.  {
  4.      int goldch, goldoc;
  5.      unsigned int goldos;
  6.      int goldglyph = objnum_to_glyph(GOLD_PIECE);
  7.      (void) mapglyph(goldglyph, &goldch, &goldoc, &goldos, 0, 0);
  8.      iflags.invis_goldsym = ((char)goldch <= ' ');
  9.  }
  10.  

do_statusline2

  1.  char *
  2.  do_statusline2()
  3.  {
  4.      static char newbot2[BUFSZ], /* MAXCO: botl.h */
  5.           /* dungeon location (and gold), hero health (HP, PW, AC),
  6.              experience (HD if poly'd, else Exp level and maybe Exp points),
  7.              time (in moves), varying number of status conditions */
  8.           dloc[QBUFSZ], hlth[QBUFSZ], expr[QBUFSZ], tmmv[QBUFSZ], cond[QBUFSZ];
  9.      register char *nb;
  10.      unsigned dln, dx, hln, xln, tln, cln;
  11.      int hp, hpmax, cap;
  12.      long money;
  13.  
  14.      /*
  15.       * Various min(x,9999)'s are to avoid having excessive values
  16.       * violate the field width assumptions in botl.h and should not
  17.       * impact normal play.  Particularly 64-bit long for gold which
  18.       * could require many more digits if someone figures out a way
  19.       * to get and carry a really large (or negative) amount of it.
  20.       * Turn counter is also long, but we'll risk that.
  21.       */
  22.  
  23.      /* dungeon location plus gold */
  24.      (void) describe_level(dloc); /* includes at least one trailing space */
  25.      if ((money = money_cnt(invent)) < 0L)
  26.          money = 0L; /* ought to issue impossible() and then discard gold */
  27.      Sprintf(eos(dloc), "%s:%-2ld", /* strongest hero can lift ~300000 gold */
  28.              (iflags.in_dumplog || iflags.invis_goldsym) ? "$"
  29.              : encglyph(objnum_to_glyph(GOLD_PIECE)),
  30.              min(money, 999999L));
  31.      dln = strlen(dloc);
  32.      /* '$' encoded as \GXXXXNNNN is 9 chars longer than display will need */
  33.      dx = strstri(dloc, "\\G") ? 9 : 0;
  34.  
  35.      /* health and armor class (has trailing space for AC 0..9) */
  36.      hp = Upolyd ? u.mh : u.uhp;
  37.      hpmax = Upolyd ? u.mhmax : u.uhpmax;
  38.      if (hp < 0)
  39.          hp = 0;
  40.      Sprintf(hlth, "HP:%d(%d) Pw:%d(%d) AC:%-2d",
  41.              min(hp, 9999), min(hpmax, 9999),
  42.              min(u.uen, 9999), min(u.uenmax, 9999), u.uac);
  43.      hln = strlen(hlth);
  44.  
  45.      /* experience */
  46.      if (Upolyd)
  47.          Sprintf(expr, "HD:%d", mons[u.umonnum].mlevel);
  48.      else if (flags.showexp)
  49.          Sprintf(expr, "Xp:%u/%-1ld", u.ulevel, u.uexp);
  50.      else
  51.          Sprintf(expr, "Exp:%u", u.ulevel);
  52.      xln = strlen(expr);
  53.  
  54.      /* time/move counter */
  55.      if (flags.time)
  56.          Sprintf(tmmv, "T:%ld", moves);
  57.      else
  58.          tmmv[0] = '\0';
  59.      tln = strlen(tmmv);
  60.  
  61.      /* status conditions; worst ones first */
  62.      cond[0] = '\0'; /* once non-empty, cond will have a leading space */
  63.      nb = cond;
  64.      /*
  65.       * Stoned, Slimed, Strangled, and both types of Sick are all fatal
  66.       * unless remedied before timeout expires.  Should we order them by
  67.       * shortest time left?  [Probably not worth the effort, since it's
  68.       * unusual for more than one of them to apply at a time.]
  69.       */
  70.      if (Stoned)
  71.          Strcpy(nb = eos(nb), " Stone");
  72.      if (Slimed)
  73.          Strcpy(nb = eos(nb), " Slime");
  74.      if (Strangled)
  75.          Strcpy(nb = eos(nb), " Strngl");
  76.      if (Sick) {
  77.          if (u.usick_type & SICK_VOMITABLE)
  78.              Strcpy(nb = eos(nb), " FoodPois");
  79.          if (u.usick_type & SICK_NONVOMITABLE)
  80.              Strcpy(nb = eos(nb), " TermIll");
  81.      }
  82.      if (u.uhs != NOT_HUNGRY)
  83.          Sprintf(nb = eos(nb), " %s", hu_stat[u.uhs]);
  84.      if ((cap = near_capacity()) > UNENCUMBERED)
  85.          Sprintf(nb = eos(nb), " %s", enc_stat[cap]);
  86.      if (Blind)
  87.          Strcpy(nb = eos(nb), " Blind");
  88.      if (Deaf)
  89.          Strcpy(nb = eos(nb), " Deaf");
  90.      if (Stunned)
  91.          Strcpy(nb = eos(nb), " Stun");
  92.      if (Confusion)
  93.          Strcpy(nb = eos(nb), " Conf");
  94.      if (Hallucination)
  95.          Strcpy(nb = eos(nb), " Hallu");
  96.      /* levitation and flying are mutually exclusive; riding is not */
  97.      if (Levitation)
  98.          Strcpy(nb = eos(nb), " Lev");
  99.      if (Flying)
  100.          Strcpy(nb = eos(nb), " Fly");
  101.      if (u.usteed)
  102.          Strcpy(nb = eos(nb), " Ride");
  103.      cln = strlen(cond);
  104.  
  105.      /*
  106.       * Put the pieces together.  If they all fit, keep the traditional
  107.       * sequence.  Otherwise, move least important parts to the end in
  108.       * case the interface side of things has to truncate.  Note that
  109.       * dloc[] contains '$' encoded in ten character sequence \GXXXXNNNN
  110.       * so we want to test its display length rather than buffer length.
  111.       *
  112.       * We don't have an actual display limit here, so have to go by the
  113.       * width of the map.  Since we're reordering rather than truncating,
  114.       * wider displays can still show wider status than the map if the
  115.       * interface supports that.
  116.       */
  117.      if ((dln - dx) + 1 + hln + 1 + xln + 1 + tln + 1 + cln <= COLNO) {
  118.          Sprintf(newbot2, "%s %s %s %s %s", dloc, hlth, expr, tmmv, cond);
  119.      } else {
  120.          if (dln + 1 + hln + 1 + xln + 1 + tln + 1 + cln + 1 > MAXCO) {
  121.              panic("bot2: second status line exceeds MAXCO (%u > %d)",
  122.                    (dln + 1 + hln + 1 + xln + 1 + tln + 1 + cln + 1), MAXCO);
  123.          } else if ((dln - dx) + 1 + hln + 1 + xln + 1 + cln <= COLNO) {
  124.              Sprintf(newbot2, "%s %s %s %s %s", dloc, hlth, expr, cond, tmmv);
  125.          } else if ((dln - dx) + 1 + hln + 1 + cln <= COLNO) {
  126.              Sprintf(newbot2, "%s %s %s %s %s", dloc, hlth, cond, expr, tmmv);
  127.          } else {
  128.              Sprintf(newbot2, "%s %s %s %s %s", hlth, cond, dloc, expr, tmmv);
  129.          }
  130.          /* only two or three consecutive spaces available to squeeze out */
  131.          mungspaces(newbot2);
  132.      }
  133.      return newbot2;
  134.  }
  135.  

bot

  1.  void
  2.  bot()
  3.  {
  4.      if (youmonst.data && iflags.status_updates) {
  5.  #ifdef STATUS_HILITES
  6.          bot_via_windowport();
  7.  #else
  8.          curs(WIN_STATUS, 1, 0);
  9.          putstr(WIN_STATUS, 0, do_statusline1());
  10.          curs(WIN_STATUS, 1, 1);
  11.          putmixed(WIN_STATUS, 0, do_statusline2());
  12.  #endif
  13.      }
  14.      context.botl = context.botlx = 0;
  15.  }
  16.  

xlev_to_rank

  1.  /* convert experience level (1..30) to rank index (0..8) */
  2.  int
  3.  xlev_to_rank(xlev)
  4.  int xlev;
  5.  {
  6.      return (xlev <= 2) ? 0 : (xlev <= 30) ? ((xlev + 2) / 4) : 8;
  7.  }
  8.  

rank_to_xlev

  1.  #if 0 /* not currently needed */
  2.  /* convert rank index (0..8) to experience level (1..30) */
  3.  int
  4.  rank_to_xlev(rank)
  5.  int rank;
  6.  {
  7.      return (rank <= 0) ? 1 : (rank <= 8) ? ((rank * 4) - 2) : 30;
  8.  }
  9.  #endif
  10.  

rank_of

  1.  const char *
  2.  rank_of(lev, monnum, female)
  3.  int lev;
  4.  short monnum;
  5.  boolean female;
  6.  {
  7.      register const struct Role *role;
  8.      register int i;
  9.  
  10.      /* Find the role */
  11.      for (role = roles; role->name.m; role++)
  12.          if (monnum == role->malenum || monnum == role->femalenum)
  13.              break;
  14.      if (!role->name.m)
  15.          role = &urole;
  16.  
  17.      /* Find the rank */
  18.      for (i = xlev_to_rank((int) lev); i >= 0; i--) {
  19.          if (female && role->rank[i].f)
  20.              return role->rank[i].f;
  21.          if (role->rank[i].m)
  22.              return role->rank[i].m;
  23.      }
  24.  
  25.      /* Try the role name, instead */
  26.      if (female && role->name.f)
  27.          return role->name.f;
  28.      else if (role->name.m)
  29.          return role->name.m;
  30.      return "Player";
  31.  }
  32.  

rank

  1.  STATIC_OVL const char *
  2.  rank()
  3.  {
  4.      return rank_of(u.ulevel, Role_switch, flags.female);
  5.  }
  6.  

title_to_mon

  1.  int
  2.  title_to_mon(str, rank_indx, title_length)
  3.  const char *str;
  4.  int *rank_indx, *title_length;
  5.  {
  6.      register int i, j;
  7.  
  8.      /* Loop through each of the roles */
  9.      for (i = 0; roles[i].name.m; i++)
  10.          for (j = 0; j < 9; j++) {
  11.              if (roles[i].rank[j].m
  12.                  && !strncmpi(str, roles[i].rank[j].m,
  13.                               strlen(roles[i].rank[j].m))) {
  14.                  if (rank_indx)
  15.                      *rank_indx = j;
  16.                  if (title_length)
  17.                      *title_length = strlen(roles[i].rank[j].m);
  18.                  return roles[i].malenum;
  19.              }
  20.              if (roles[i].rank[j].f
  21.                  && !strncmpi(str, roles[i].rank[j].f,
  22.                               strlen(roles[i].rank[j].f))) {
  23.                  if (rank_indx)
  24.                      *rank_indx = j;
  25.                  if (title_length)
  26.                      *title_length = strlen(roles[i].rank[j].f);
  27.                  return (roles[i].femalenum != NON_PM) ? roles[i].femalenum
  28.                                                        : roles[i].malenum;
  29.              }
  30.          }
  31.      return NON_PM;
  32.  }
  33.  

max_rank_sz

  1.  void
  2.  max_rank_sz()
  3.  {
  4.      register int i, r, maxr = 0;
  5.      for (i = 0; i < 9; i++) {
  6.          if (urole.rank[i].m && (r = strlen(urole.rank[i].m)) > maxr)
  7.              maxr = r;
  8.          if (urole.rank[i].f && (r = strlen(urole.rank[i].f)) > maxr)
  9.              maxr = r;
  10.      }
  11.      mrank_sz = maxr;
  12.      return;
  13.  }
  14.  

botl_score

  1.  #ifdef SCORE_ON_BOTL
  2.  long
  3.  botl_score()
  4.  {
  5.      long deepest = deepest_lev_reached(FALSE);
  6.      long utotal;
  7.  
  8.      utotal = money_cnt(invent) + hidden_gold();
  9.      if ((utotal -= u.umoney0) < 0L)
  10.          utotal = 0L;
  11.      utotal += u.urexp + (50 * (deepest - 1))
  12.            + (deepest > 30 ? 10000 : deepest > 20 ? 1000 * (deepest - 20) : 0);
  13.      if (utotal < u.urexp)
  14.          utotal = LONG_MAX; /* wrap around */
  15.      return utotal;
  16.  }
  17.  #endif /* SCORE_ON_BOTL */
  18.  

describe_level

  1.  /* provide the name of the current level for display by various ports */
  2.  int
  3.  describe_level(buf)
  4.  char *buf;
  5.  {
  6.      int ret = 1;
  7.  
  8.      /* TODO:    Add in dungeon name */
  9.      if (Is_knox(&u.uz))
  10.          Sprintf(buf, "%s ", dungeons[u.uz.dnum].dname);
  11.      else if (In_quest(&u.uz))
  12.          Sprintf(buf, "Home %d ", dunlev(&u.uz));
  13.      else if (In_endgame(&u.uz))
  14.          Sprintf(buf, Is_astralevel(&u.uz) ? "Astral Plane " : "End Game ");
  15.      else {
  16.          /* ports with more room may expand this one */
  17.          Sprintf(buf, "Dlvl:%-2d ", depth(&u.uz));
  18.          ret = 0;
  19.      }
  20.      return ret;
  21.  }
  22.  
  23.  /* =======================================================================*/
  24.  /*  statusnew routines                                                    */
  25.  /* =======================================================================*/
  26.  
  27.  /* structure that tracks the status details in the core */
  28.  
  29.  #ifdef STATUS_HILITES
  30.  struct hilite_s {
  31.      enum statusfields fld;
  32.      boolean set;
  33.      unsigned anytype;
  34.      anything value;
  35.      int behavior;
  36.      char textmatch[QBUFSZ];
  37.      enum relationships rel;
  38.      int coloridx;
  39.      struct hilite_s *next;
  40.  };
  41.  
  42.  struct condmap {
  43.      const char *id;
  44.      unsigned long bitmask;
  45.  };
  46.  #endif /* STATUS_HILITES */
  47.  
  48.  struct istat_s {
  49.      const char *fldname;
  50.      const char *fldfmt;
  51.      long time;  /* moves when this field hilite times out */
  52.      boolean chg; /* need to recalc time? */
  53.      unsigned anytype;
  54.      anything a;
  55.      char *val;
  56.      int valwidth;
  57.      enum statusfields idxmax;
  58.      enum statusfields fld;
  59.  #ifdef STATUS_HILITES
  60.      struct hilite_s *thresholds;
  61.  #endif
  62.  };
  63.  
  64.  
  65.  STATIC_DCL void NDECL(init_blstats);
  66.  STATIC_DCL char *FDECL(anything_to_s, (char *, anything *, int));
  67.  STATIC_OVL int FDECL(percentage, (struct istat_s *, struct istat_s *));
  68.  STATIC_OVL int FDECL(compare_blstats, (struct istat_s *, struct istat_s *));
  69.  STATIC_DCL boolean FDECL(evaluate_and_notify_windowport_field,
  70.                           (int, boolean *, int, int));
  71.  STATIC_DCL void FDECL(evaluate_and_notify_windowport, (boolean *, int, int));
  72.  
  73.  #ifdef STATUS_HILITES
  74.  STATIC_DCL boolean FDECL(hilite_reset_needed, (struct istat_s *, long));
  75.  STATIC_DCL void FDECL(s_to_anything, (anything *, char *, int));
  76.  STATIC_DCL boolean FDECL(is_ltgt_percentnumber, (const char *));
  77.  STATIC_DCL boolean FDECL(has_ltgt_percentnumber, (const char *));
  78.  STATIC_DCL boolean FDECL(parse_status_hl2, (char (*)[QBUFSZ],BOOLEAN_P));
  79.  STATIC_DCL boolean FDECL(parse_condition, (char (*)[QBUFSZ], int));
  80.  STATIC_DCL void FDECL(merge_bestcolor, (int *, int));
  81.  STATIC_DCL void FDECL(get_hilite_color, (int, int, genericptr_t, int,
  82.                                                  int, int *));
  83.  STATIC_DCL unsigned long FDECL(match_str2conditionbitmask, (const char *));
  84.  STATIC_DCL unsigned long FDECL(str2conditionbitmask, (char *));
  85.  STATIC_DCL void FDECL(split_clridx, (int, int *, int *));
  86.  STATIC_DCL char *FDECL(hlattr2attrname, (int, char *, int));
  87.  STATIC_DCL void FDECL(status_hilite_linestr_add, (int, struct hilite_s *,
  88.                                              unsigned long, const char *));
  89.  
  90.  STATIC_DCL void NDECL(status_hilite_linestr_done);
  91.  STATIC_DCL int FDECL(status_hilite_linestr_countfield, (int));
  92.  STATIC_DCL void NDECL(status_hilite_linestr_gather_conditions);
  93.  STATIC_DCL void NDECL(status_hilite_linestr_gather);
  94.  STATIC_DCL char *FDECL(status_hilite2str, (struct hilite_s *));
  95.  STATIC_DCL boolean FDECL(status_hilite_menu_add, (int));
  96.  #define has_hilite(i) (blstats[0][(i)].thresholds)
  97.  #endif
  98.  
  99.  #define INIT_BLSTAT(name, fmtstr, anytyp, wid, fld)                     \
  100.      { name, fmtstr, 0L, FALSE, anytyp,  { (genericptr_t) 0 }, (char *) 0, \
  101.        wid,  -1, fld }
  102.  #define INIT_BLSTATP(name, fmtstr, anytyp, wid, maxfld, fld)            \
  103.      { name, fmtstr, 0L, FALSE, anytyp,  { (genericptr_t) 0 }, (char *) 0, \
  104.        wid,  maxfld, fld }
  105.  
  106.  /* If entries are added to this, botl.h will require updating too */
  107.  STATIC_DCL struct istat_s initblstats[MAXBLSTATS] = {
  108.      INIT_BLSTAT("title", "%s", ANY_STR, 80, BL_TITLE),
  109.      INIT_BLSTAT("strength", " St:%s", ANY_INT, 10, BL_STR),
  110.      INIT_BLSTAT("dexterity", " Dx:%s", ANY_INT,  10, BL_DX),
  111.      INIT_BLSTAT("constitution", " Co:%s", ANY_INT, 10, BL_CO),
  112.      INIT_BLSTAT("intelligence", " In:%s", ANY_INT, 10, BL_IN),
  113.      INIT_BLSTAT("wisdom", " Wi:%s", ANY_INT, 10, BL_WI),
  114.      INIT_BLSTAT("charisma", " Ch:%s", ANY_INT, 10, BL_CH),
  115.      INIT_BLSTAT("alignment", " %s", ANY_STR, 40, BL_ALIGN),
  116.      INIT_BLSTAT("score", " S:%s", ANY_LONG, 20, BL_SCORE),
  117.      INIT_BLSTAT("carrying-capacity", " %s", ANY_LONG, 20, BL_CAP),
  118.      INIT_BLSTAT("gold", " %s", ANY_LONG, 30, BL_GOLD),
  119.      INIT_BLSTATP("power", " Pw:%s", ANY_INT, 10, BL_ENEMAX, BL_ENE),
  120.      INIT_BLSTAT("power-max", "(%s)", ANY_INT, 10, BL_ENEMAX),
  121.      INIT_BLSTAT("experience-level", " Xp:%s", ANY_LONG, 10, BL_XP),
  122.      INIT_BLSTAT("armor-class", " AC:%s", ANY_INT, 10, BL_AC),
  123.      INIT_BLSTAT("HD", " HD:%s", ANY_INT, 10, BL_HD),
  124.      INIT_BLSTAT("time", " T:%s", ANY_INT, 20, BL_TIME),
  125.      INIT_BLSTAT("hunger", " %s", ANY_UINT, 40, BL_HUNGER),
  126.      INIT_BLSTATP("hitpoints", " HP:%s", ANY_INT, 10, BL_HPMAX, BL_HP),
  127.      INIT_BLSTAT("hitpoints-max", "(%s)", ANY_INT, 10, BL_HPMAX),
  128.      INIT_BLSTAT("dungeon-level", "%s", ANY_STR, 80, BL_LEVELDESC),
  129.      INIT_BLSTAT("experience", "/%s", ANY_LONG, 20, BL_EXP),
  130.      INIT_BLSTAT("condition", "%s", ANY_MASK32, 0, BL_CONDITION)
  131.  };
  132.  
  133.  #undef INIT_BLSTATP
  134.  #undef INIT_BLSTAT
  135.  
  136.  struct istat_s blstats[2][MAXBLSTATS];
  137.  static boolean blinit = FALSE, update_all = FALSE;
  138.  static boolean valset[MAXBLSTATS];
  139.  unsigned long blcolormasks[CLR_MAX];
  140.  static long bl_hilite_moves = 0L;
  141.  
  142.  /* we don't put this next declaration in #ifdef STATUS_HILITES.
  143.   * In the absence of STATUS_HILITES, each array
  144.   * element will be 0 however, and quite meaningless,
  145.   * but we need to pass the first array element as
  146.   * the final argument of status_update, with or
  147.   * without STATUS_HILITES.
  148.   */
  149.  unsigned long cond_hilites[BL_ATTCLR_MAX];
  150.  

bot_via_windowport

  1.  void
  2.  bot_via_windowport()
  3.  {
  4.      char buf[BUFSZ];
  5.      register char *nb;
  6.      static int i, idx = 0, idx_p, cap;
  7.      long money;
  8.  
  9.      if (!blinit)
  10.          panic("bot before init.");
  11.  
  12.      idx_p = idx;
  13.      idx = 1 - idx; /* 0 -> 1, 1 -> 0 */
  14.  
  15.      /* clear the "value set" indicators */
  16.      (void) memset((genericptr_t) valset, 0, MAXBLSTATS * sizeof (boolean));
  17.  
  18.      /*
  19.       * Note: min(x,9999) - we enforce the same maximum on hp, maxhp,
  20.       * pw, maxpw, and gold as basic status formatting so that the two
  21.       * modes of status display don't produce different information.
  22.       */
  23.  
  24.      /*
  25.       *  Player name and title.
  26.       */
  27.      Strcpy(nb = buf, plname);
  28.      nb[0] = highc(nb[0]);
  29.      nb[10] = '\0';
  30.      Sprintf(nb = eos(nb), " the ");
  31.      if (Upolyd) {
  32.          for (i = 0, nb = strcpy(eos(nb), mons[u.umonnum].mname); nb[i]; i++)
  33.              if (i == 0 || nb[i - 1] == ' ')
  34.                  nb[i] = highc(nb[i]);
  35.      } else
  36.          Strcpy(nb = eos(nb), rank());
  37.      Sprintf(blstats[idx][BL_TITLE].val, "%-29s", buf);
  38.      valset[BL_TITLE] = TRUE; /* indicate val already set */
  39.  
  40.      /* Strength */
  41.      blstats[idx][BL_STR].a.a_int = ACURR(A_STR);
  42.      Strcpy(blstats[idx][BL_STR].val, get_strength_str());
  43.      valset[BL_STR] = TRUE; /* indicate val already set */
  44.  
  45.      /*  Dexterity, constitution, intelligence, wisdom, charisma. */
  46.      blstats[idx][BL_DX].a.a_int = ACURR(A_DEX);
  47.      blstats[idx][BL_CO].a.a_int = ACURR(A_CON);
  48.      blstats[idx][BL_IN].a.a_int = ACURR(A_INT);
  49.      blstats[idx][BL_WI].a.a_int = ACURR(A_WIS);
  50.      blstats[idx][BL_CH].a.a_int = ACURR(A_CHA);
  51.  
  52.      /* Alignment */
  53.      Strcpy(blstats[idx][BL_ALIGN].val, (u.ualign.type == A_CHAOTIC)
  54.                                            ? "Chaotic"
  55.                                            : (u.ualign.type == A_NEUTRAL)
  56.                                                 ? "Neutral"
  57.                                                 : "Lawful");
  58.  
  59.      /* Score */
  60.      blstats[idx][BL_SCORE].a.a_long =
  61.  #ifdef SCORE_ON_BOTL
  62.          flags.showscore ? botl_score() :
  63.  #endif
  64.          0L;
  65.  
  66.      /*  Hit points  */
  67.      i = Upolyd ? u.mh : u.uhp;
  68.      if (i < 0)
  69.          i = 0;
  70.      blstats[idx][BL_HP].a.a_int = min(i, 9999);
  71.      i = Upolyd ? u.mhmax : u.uhpmax;
  72.      blstats[idx][BL_HPMAX].a.a_int = min(i, 9999);
  73.  
  74.      /*  Dungeon level. */
  75.      (void) describe_level(blstats[idx][BL_LEVELDESC].val);
  76.      valset[BL_LEVELDESC] = TRUE; /* indicate val already set */
  77.  
  78.      /* Gold */
  79.      if ((money = money_cnt(invent)) < 0L)
  80.          money = 0L; /* ought to issue impossible() and then discard gold */
  81.      blstats[idx][BL_GOLD].a.a_long = min(money, 999999L);
  82.      /*
  83.       * The tty port needs to display the current symbol for gold
  84.       * as a field header, so to accommodate that we pass gold with
  85.       * that already included. If a window port needs to use the text
  86.       * gold amount without the leading "$:" the port will have to
  87.       * skip past ':' to the value pointer it was passed in status_update()
  88.       * for the BL_GOLD case.
  89.       *
  90.       * Another quirk of BL_GOLD is that the field display may have
  91.       * changed if a new symbol set was loaded, or we entered or left
  92.       * the rogue level.
  93.       *
  94.       * The currency prefix is encoded as ten character \GXXXXNNNN
  95.       * sequence.
  96.       */
  97.      Sprintf(blstats[idx][BL_GOLD].val, "%s:%ld",
  98.              encglyph(objnum_to_glyph(GOLD_PIECE)),
  99.              blstats[idx][BL_GOLD].a.a_long);
  100.      valset[BL_GOLD] = TRUE; /* indicate val already set */
  101.  
  102.      /* Power (magical energy) */
  103.      blstats[idx][BL_ENE].a.a_int = min(u.uen, 9999);
  104.      blstats[idx][BL_ENEMAX].a.a_int = min(u.uenmax, 9999);
  105.  
  106.      /* Armor class */
  107.      blstats[idx][BL_AC].a.a_int = u.uac;
  108.  
  109.      /* Monster level (if Upolyd) */
  110.      blstats[idx][BL_HD].a.a_int = Upolyd ? (int) mons[u.umonnum].mlevel : 0;
  111.  
  112.      /* Experience */
  113.      blstats[idx][BL_XP].a.a_int = u.ulevel;
  114.      blstats[idx][BL_EXP].a.a_int = u.uexp;
  115.  
  116.      /* Time (moves) */
  117.      blstats[idx][BL_TIME].a.a_long = moves;
  118.  
  119.      /* Hunger */
  120.      blstats[idx][BL_HUNGER].a.a_uint = u.uhs;
  121.      Strcpy(blstats[idx][BL_HUNGER].val,
  122.             (u.uhs != NOT_HUNGRY) ? hu_stat[u.uhs] : "");
  123.      valset[BL_HUNGER] = TRUE;
  124.  
  125.      /* Carrying capacity */
  126.      cap = near_capacity();
  127.      blstats[idx][BL_CAP].a.a_int = cap;
  128.      Strcpy(blstats[idx][BL_CAP].val,
  129.             (cap > UNENCUMBERED) ? enc_stat[cap] : "");
  130.      valset[BL_CAP] = TRUE;
  131.  
  132.      /* Conditions */
  133.      blstats[idx][BL_CONDITION].a.a_ulong = 0L;
  134.      if (Stoned)
  135.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_STONE;
  136.      if (Slimed)
  137.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_SLIME;
  138.      if (Strangled)
  139.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_STRNGL;
  140.      if (Sick && (u.usick_type & SICK_VOMITABLE) != 0)
  141.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_FOODPOIS;
  142.      if (Sick && (u.usick_type & SICK_NONVOMITABLE) != 0)
  143.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_TERMILL;
  144.      /*
  145.       * basic formatting puts hunger status and encumbrance here
  146.       */
  147.      if (Blind)
  148.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_BLIND;
  149.      if (Deaf)
  150.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_DEAF;
  151.      if (Stunned)
  152.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_STUN;
  153.      if (Confusion)
  154.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_CONF;
  155.      if (Hallucination)
  156.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_HALLU;
  157.      /* levitation and flying are mututally exclusive */
  158.      if (Levitation)
  159.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_LEV;
  160.      if (Flying)
  161.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_FLY;
  162.      if (u.usteed)
  163.          blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_RIDE;
  164.      evaluate_and_notify_windowport(valset, idx, idx_p);
  165.  }
  166.  

evaluate_and_notify_windowport_field

  1.  STATIC_OVL boolean
  2.  evaluate_and_notify_windowport_field(fld, valsetlist, idx, idx_p)
  3.  int fld, idx, idx_p;
  4.  boolean *valsetlist;
  5.  {
  6.      static int oldrndencode = 0;
  7.      int pc, chg, color = NO_COLOR;
  8.      unsigned anytype;
  9.      boolean updated = FALSE, reset;
  10.      struct istat_s *curr = NULL, *prev = NULL;
  11.      enum statusfields idxmax;
  12.  
  13.      /*
  14.       *  Now pass the changed values to window port.
  15.       */
  16.      anytype = blstats[idx][fld].anytype;
  17.      curr = &blstats[idx][fld];
  18.      prev = &blstats[idx_p][fld];
  19.      color = NO_COLOR;
  20.  
  21.      chg = update_all ? 0 : compare_blstats(prev, curr);
  22.  
  23.      /* Temporary? hack: moveloop()'s prolog for a new game sets
  24.       * context.rndencode after the status window has been init'd,
  25.       * so $:0 has already been encoded and cached by the window
  26.       * port.  Without this hack, gold's \G sequence won't be
  27.       * recognized and ends up being displayed as-is for 'update_all'.
  28.       */
  29.      if (context.rndencode != oldrndencode && fld == BL_GOLD) {
  30.          chg = 2;
  31.          oldrndencode = context.rndencode;
  32.      }
  33.  
  34.      reset = FALSE;
  35.  #ifdef STATUS_HILITES
  36.      if (!update_all && !chg) {
  37.          reset = hilite_reset_needed(prev, bl_hilite_moves);
  38.          if (reset)
  39.            curr->time = prev->time = 0L;
  40.      }
  41.  #endif
  42.  
  43.      if (update_all || chg || reset) {
  44.          idxmax = curr->idxmax;
  45.          pc = (idxmax > BL_FLUSH) ? percentage(curr, &blstats[idx][idxmax]) : 0;
  46.  
  47.          if (!valsetlist[fld])
  48.              (void) anything_to_s(curr->val, &curr->a, anytype);
  49.  
  50.          if (anytype != ANY_MASK32) {
  51.  #ifdef STATUS_HILITES
  52.              if ((chg || *curr->val)) {
  53.                  get_hilite_color(idx, fld, (genericptr_t)&curr->a,
  54.                                   chg, pc, &color);
  55.                  if (chg == 2) {
  56.                      color = NO_COLOR;
  57.                      chg = 0;
  58.                  }
  59.              }
  60.  #endif /* STATUS_HILITES */
  61.              status_update(fld, (genericptr_t) curr->val,
  62.                            chg, pc, color, &cond_hilites[0]);
  63.          } else {
  64.              /* Color for conditions is done through cond_hilites[] */
  65.              status_update(fld, (genericptr_t) &curr->a.a_ulong, chg, pc,
  66.                            color, &cond_hilites[0]);
  67.          }
  68.          curr->chg = prev->chg = TRUE;
  69.          updated = TRUE;
  70.      }
  71.      return updated;
  72.  }
  73.  

evaluate_and_notify_windowport

  1.  static void
  2.  evaluate_and_notify_windowport(valsetlist, idx, idx_p)
  3.  int idx, idx_p;
  4.  boolean *valsetlist;
  5.  {
  6.      int i;
  7.      boolean updated = FALSE;
  8.  
  9.      /*
  10.       *  Now pass the changed values to window port.
  11.       */
  12.      for (i = 0; i < MAXBLSTATS; i++) {
  13.          if (((i == BL_SCORE) && !flags.showscore)
  14.              || ((i == BL_EXP) && !flags.showexp)
  15.              || ((i == BL_TIME) && !flags.time)
  16.              || ((i == BL_HD) && !Upolyd)
  17.              || ((i == BL_XP || i == BL_EXP) && Upolyd))
  18.              continue;
  19.          if (evaluate_and_notify_windowport_field(i, valsetlist, idx, idx_p))
  20.              updated = TRUE;
  21.      }
  22.      /*
  23.       * It is possible to get here, with nothing having been pushed
  24.       * to the window port, when none of the info has changed. In that
  25.       * case, we need to force a call to status_update() when
  26.       * context.botlx is set. The tty port in particular has a problem
  27.       * if that isn't done, since it sets context.botlx when a menu or
  28.       * text display obliterates the status line.
  29.       *
  30.       * To work around it, we call status_update() with fictitious
  31.       * index of BL_FLUSH (-1).
  32.       */
  33.      if ((context.botlx && !updated)
  34.          || (windowprocs.wincap2 & WC2_FLUSH_STATUS) != 0L)
  35.          status_update(BL_FLUSH, (genericptr_t) 0, 0, 0,
  36.                        NO_COLOR, &cond_hilites[0]);
  37.  
  38.      context.botl = context.botlx = 0;
  39.      update_all = FALSE;
  40.  }
  41.  

status_eval_next_unhilite

  1.  void
  2.  status_eval_next_unhilite()
  3.  {
  4.      int i;
  5.      struct istat_s *curr = NULL;
  6.      long next_unhilite, this_unhilite;
  7.  
  8.      bl_hilite_moves = moves;
  9.      /* figure out when the next unhilight needs to be performed */
  10.      next_unhilite = 0L;
  11.      for (i = 0; i < MAXBLSTATS; ++i) {
  12.          curr = &blstats[0][i]; /* blstats[0][*].time == blstats[1][*].time */
  13.  
  14.          if (curr->chg) {
  15.              struct istat_s *prev = &blstats[1][i];
  16.  
  17.  #ifdef STATUS_HILITES
  18.              curr->time = prev->time = (bl_hilite_moves + iflags.hilite_delta);
  19.  #endif
  20.              curr->chg = prev->chg = FALSE;
  21.          }
  22.  
  23.          this_unhilite = curr->time;
  24.          if (this_unhilite > 0L
  25.              && (next_unhilite == 0L || this_unhilite < next_unhilite)
  26.  #ifdef STATUS_HILITES
  27.              && hilite_reset_needed(curr, this_unhilite + 1L)
  28.  #endif
  29.              )
  30.              next_unhilite = this_unhilite;
  31.      }
  32.      if (next_unhilite > 0L && next_unhilite < bl_hilite_moves)
  33.          context.botl = TRUE;
  34.  }
  35.  

status_initialize

  1.  void
  2.  status_initialize(reassessment)
  3.  boolean
  4.      reassessment; /* TRUE = just reassess fields w/o other initialization*/
  5.  {
  6.      int i;
  7.      const char *fieldfmt = (const char *) 0;
  8.      const char *fieldname = (const char *) 0;
  9.  
  10.      if (!reassessment) {
  11.          if (blinit)
  12.              impossible("2nd status_initialize with full init.");
  13.          init_blstats();
  14.          (*windowprocs.win_status_init)();
  15.          blinit = TRUE;
  16.      }
  17.      for (i = 0; i < MAXBLSTATS; ++i) {
  18.          enum statusfields fld = initblstats[i].fld;
  19.          boolean fldenabled = (fld == BL_SCORE) ? flags.showscore
  20.              : (fld == BL_XP) ? (boolean) !Upolyd
  21.              : (fld == BL_HD) ? (boolean) Upolyd
  22.              : (fld == BL_TIME) ? flags.time
  23.              : (fld == BL_EXP) ? (boolean) (flags.showexp && !Upolyd)
  24.              : TRUE;
  25.  
  26.          fieldname = initblstats[i].fldname;
  27.          fieldfmt = initblstats[i].fldfmt;
  28.          status_enablefield(fld, fieldname, fieldfmt, fldenabled);
  29.      }
  30.      update_all = TRUE;
  31.  }
  32.  

status_finish

  1.  void
  2.  status_finish()
  3.  {
  4.      int i;
  5.  
  6.      /* call the window port cleanup routine first */
  7.      (*windowprocs.win_status_finish)();
  8.  
  9.      /* free memory that we alloc'd now */
  10.      for (i = 0; i < MAXBLSTATS; ++i) {
  11.          if (blstats[0][i].val)
  12.              free((genericptr_t) blstats[0][i].val), blstats[0][i].val = 0;
  13.          if (blstats[1][i].val)
  14.              free((genericptr_t) blstats[1][i].val), blstats[1][i].val = 0;
  15.  #ifdef STATUS_HILITES
  16.          if (blstats[0][i].thresholds) {
  17.              struct hilite_s *temp = blstats[0][i].thresholds,
  18.                              *next = (struct hilite_s *)0;
  19.              while (temp) {
  20.                  next = temp->next;
  21.                  free(temp);
  22.                  blstats[0][i].thresholds = (struct hilite_s *)0;
  23.                  blstats[1][i].thresholds = blstats[0][i].thresholds;
  24.                  temp = next;
  25.              }
  26.  	}
  27.  #endif /* STATUS_HILITES */
  28.      }
  29.  }
  30.  

init_blstats

  1.  STATIC_OVL void
  2.  init_blstats()
  3.  {
  4.      static boolean initalready = FALSE;
  5.      int i, j;
  6.  
  7.      if (initalready) {
  8.          impossible("init_blstats called more than once.");
  9.          return;
  10.      }
  11.  
  12.      initalready = TRUE;
  13.      for (i = BEFORE; i <= NOW; ++i) {
  14.          for (j = 0; j < MAXBLSTATS; ++j) {
  15.  #ifdef STATUS_HILITES
  16.              struct hilite_s *keep_hilite_chain = blstats[i][j].thresholds;
  17.  #endif
  18.              blstats[i][j] = initblstats[j];
  19.              blstats[i][j].a = zeroany;
  20.              if (blstats[i][j].valwidth) {
  21.                  blstats[i][j].val = (char *) alloc(blstats[i][j].valwidth);
  22.                  blstats[i][j].val[0] = '\0';
  23.              } else
  24.                  blstats[i][j].val = (char *) 0;
  25.  #ifdef STATUS_HILITES
  26.              if (keep_hilite_chain)
  27.                  blstats[i][j].thresholds = keep_hilite_chain;
  28.  #endif
  29.          }
  30.      }
  31.  }
  32.  

compare_blstats

  1.  /*
  2.   * This compares the previous stat with the current stat,
  3.   * and returns one of the following results based on that:
  4.   *
  5.   *   if prev_value < new_value (stat went up, increased)
  6.   *      return 1
  7.   *
  8.   *   if prev_value > new_value (stat went down, decreased)
  9.   *      return  -1
  10.   *
  11.   *   if prev_value == new_value (stat stayed the same)
  12.   *      return 0
  13.   *
  14.   *   Special cases:
  15.   *     - for bitmasks, 0 = stayed the same, 1 = changed
  16.   *     - for strings,  0 = stayed the same, 1 = changed
  17.   *
  18.   */
  19.  STATIC_OVL int
  20.  compare_blstats(bl1, bl2)
  21.  struct istat_s *bl1, *bl2;
  22.  {
  23.      int anytype, result = 0;
  24.  
  25.      if (!bl1 || !bl2) {
  26.          panic("compare_blstat: bad istat pointer %s, %s",
  27.                fmt_ptr((genericptr_t) bl1), fmt_ptr((genericptr_t) bl2));
  28.      }
  29.  
  30.      anytype = bl1->anytype;
  31.      if ((!bl1->a.a_void || !bl2->a.a_void)
  32.          && (anytype == ANY_IPTR || anytype == ANY_UPTR || anytype == ANY_LPTR
  33.              || anytype == ANY_ULPTR)) {
  34.          panic("compare_blstat: invalid pointer %s, %s",
  35.                fmt_ptr((genericptr_t) bl1->a.a_void),
  36.                fmt_ptr((genericptr_t) bl2->a.a_void));
  37.      }
  38.  
  39.      switch (anytype) {
  40.      case ANY_INT:
  41.          result = (bl1->a.a_int < bl2->a.a_int)
  42.                       ? 1
  43.                       : (bl1->a.a_int > bl2->a.a_int) ? -1 : 0;
  44.          break;
  45.      case ANY_IPTR:
  46.          result = (*bl1->a.a_iptr < *bl2->a.a_iptr)
  47.                       ? 1
  48.                       : (*bl1->a.a_iptr > *bl2->a.a_iptr) ? -1 : 0;
  49.          break;
  50.      case ANY_LONG:
  51.          result = (bl1->a.a_long < bl2->a.a_long)
  52.                       ? 1
  53.                       : (bl1->a.a_long > bl2->a.a_long) ? -1 : 0;
  54.          break;
  55.      case ANY_LPTR:
  56.          result = (*bl1->a.a_lptr < *bl2->a.a_lptr)
  57.                       ? 1
  58.                       : (*bl1->a.a_lptr > *bl2->a.a_lptr) ? -1 : 0;
  59.          break;
  60.      case ANY_UINT:
  61.          result = (bl1->a.a_uint < bl2->a.a_uint)
  62.                       ? 1
  63.                       : (bl1->a.a_uint > bl2->a.a_uint) ? -1 : 0;
  64.          break;
  65.      case ANY_UPTR:
  66.          result = (*bl1->a.a_uptr < *bl2->a.a_uptr)
  67.                       ? 1
  68.                       : (*bl1->a.a_uptr > *bl2->a.a_uptr) ? -1 : 0;
  69.          break;
  70.      case ANY_ULONG:
  71.          result = (bl1->a.a_ulong < bl2->a.a_ulong)
  72.                       ? 1
  73.                       : (bl1->a.a_ulong > bl2->a.a_ulong) ? -1 : 0;
  74.          break;
  75.      case ANY_ULPTR:
  76.          result = (*bl1->a.a_ulptr < *bl2->a.a_ulptr)
  77.                       ? 1
  78.                       : (*bl1->a.a_ulptr > *bl2->a.a_ulptr) ? -1 : 0;
  79.          break;
  80.      case ANY_STR:
  81.          result = sgn(strcmp(bl1->val, bl2->val));
  82.          break;
  83.      case ANY_MASK32:
  84.          result = (bl1->a.a_ulong != bl2->a.a_ulong);
  85.          break;
  86.      default:
  87.          result = 1;
  88.      }
  89.      return result;
  90.  }
  91.  

anything_to_s

  1.  STATIC_OVL char *
  2.  anything_to_s(buf, a, anytype)
  3.  char *buf;
  4.  anything *a;
  5.  int anytype;
  6.  {
  7.      if (!buf)
  8.          return (char *) 0;
  9.  
  10.      switch (anytype) {
  11.      case ANY_ULONG:
  12.          Sprintf(buf, "%lu", a->a_ulong);
  13.          break;
  14.      case ANY_MASK32:
  15.          Sprintf(buf, "%lx", a->a_ulong);
  16.          break;
  17.      case ANY_LONG:
  18.          Sprintf(buf, "%ld", a->a_long);
  19.          break;
  20.      case ANY_INT:
  21.          Sprintf(buf, "%d", a->a_int);
  22.          break;
  23.      case ANY_UINT:
  24.          Sprintf(buf, "%u", a->a_uint);
  25.          break;
  26.      case ANY_IPTR:
  27.          Sprintf(buf, "%d", *a->a_iptr);
  28.          break;
  29.      case ANY_LPTR:
  30.          Sprintf(buf, "%ld", *a->a_lptr);
  31.          break;
  32.      case ANY_ULPTR:
  33.          Sprintf(buf, "%lu", *a->a_ulptr);
  34.          break;
  35.      case ANY_UPTR:
  36.          Sprintf(buf, "%u", *a->a_uptr);
  37.          break;
  38.      case ANY_STR: /* do nothing */
  39.          ;
  40.          break;
  41.      default:
  42.          buf[0] = '\0';
  43.      }
  44.      return buf;
  45.  }
  46.  

s_to_anything

  1.  #ifdef STATUS_HILITES
  2.  STATIC_OVL void
  3.  s_to_anything(a, buf, anytype)
  4.  anything *a;
  5.  char *buf;
  6.  int anytype;
  7.  {
  8.      if (!buf || !a)
  9.          return;
  10.  
  11.      switch (anytype) {
  12.      case ANY_LONG:
  13.          a->a_long = atol(buf);
  14.          break;
  15.      case ANY_INT:
  16.          a->a_int = atoi(buf);
  17.          break;
  18.      case ANY_UINT:
  19.          a->a_uint = (unsigned) atoi(buf);
  20.          break;
  21.      case ANY_ULONG:
  22.          a->a_ulong = (unsigned long) atol(buf);
  23.          break;
  24.      case ANY_IPTR:
  25.          if (a->a_iptr)
  26.              *a->a_iptr = atoi(buf);
  27.          break;
  28.      case ANY_UPTR:
  29.          if (a->a_uptr)
  30.              *a->a_uptr = (unsigned) atoi(buf);
  31.          break;
  32.      case ANY_LPTR:
  33.          if (a->a_lptr)
  34.              *a->a_lptr = atol(buf);
  35.          break;
  36.      case ANY_ULPTR:
  37.          if (a->a_ulptr)
  38.              *a->a_ulptr = (unsigned long) atol(buf);
  39.          break;
  40.      case ANY_MASK32:
  41.          a->a_ulong = (unsigned long) atol(buf);
  42.          break;
  43.      default:
  44.          a->a_void = 0;
  45.          break;
  46.      }
  47.      return;
  48.  }
  49.  #endif /* STATUS_HILITES */
  50.  

percentage

  1.  STATIC_OVL int
  2.  percentage(bl, maxbl)
  3.  struct istat_s *bl, *maxbl;
  4.  {
  5.      int result = 0;
  6.      int anytype;
  7.      int ival;
  8.      long lval;
  9.      unsigned uval;
  10.      unsigned long ulval;
  11.  
  12.      if (!bl || !maxbl) {
  13.          impossible("percentage: bad istat pointer %s, %s",
  14.                     fmt_ptr((genericptr_t) bl), fmt_ptr((genericptr_t) maxbl));
  15.          return 0;
  16.      }
  17.  
  18.      ival = 0, lval = 0L, uval = 0U, ulval = 0UL;
  19.      anytype = bl->anytype;
  20.      if (maxbl->a.a_void) {
  21.          switch (anytype) {
  22.          case ANY_INT:
  23.              ival = bl->a.a_int;
  24.              result = ((100 * ival) / maxbl->a.a_int);
  25.              break;
  26.          case ANY_LONG:
  27.              lval  = bl->a.a_long;
  28.              result = (int) ((100L * lval) / maxbl->a.a_long);
  29.              break;
  30.          case ANY_UINT:
  31.              uval = bl->a.a_uint;
  32.              result = (int) ((100U * uval) / maxbl->a.a_uint);
  33.              break;
  34.          case ANY_ULONG:
  35.              ulval = bl->a.a_ulong;
  36.              result = (int) ((100UL * ulval) / maxbl->a.a_ulong);
  37.              break;
  38.          case ANY_IPTR:
  39.              ival = *bl->a.a_iptr;
  40.              result = ((100 * ival) / (*maxbl->a.a_iptr));
  41.              break;
  42.          case ANY_LPTR:
  43.              lval = *bl->a.a_lptr;
  44.              result = (int) ((100L * lval) / (*maxbl->a.a_lptr));
  45.              break;
  46.          case ANY_UPTR:
  47.              uval = *bl->a.a_uptr;
  48.              result = (int) ((100U * uval) / (*maxbl->a.a_uptr));
  49.              break;
  50.          case ANY_ULPTR:
  51.              ulval = *bl->a.a_ulptr;
  52.              result = (int) ((100UL * ulval) / (*maxbl->a.a_ulptr));
  53.              break;
  54.          }
  55.      }
  56.      /* don't let truncation from integer division produce a zero result
  57.         from a non-zero input; note: if we ever change to something like
  58.         ((((1000 * val) / max) + 5) / 10) for a rounded result, we'll
  59.         also need to check for and convert false 100 to 99 */
  60.      if (result == 0 && (ival != 0 || lval != 0L || uval != 0U || ulval != 0UL))
  61.          result = 1;
  62.  
  63.      return result;
  64.  }
  65.  
  66.  
  67.  #ifdef STATUS_HILITES
  68.  
  69.  /****************************************************************************/
  70.  /* Core status hiliting support */
  71.  /****************************************************************************/
  72.  
  73.  struct hilite_s status_hilites[MAXBLSTATS];
  74.  
  75.  static struct fieldid_t {
  76.      const char *fieldname;
  77.      enum statusfields fldid;
  78.  } fieldids_alias[] = {
  79.      {"characteristics", BL_CHARACTERISTICS},
  80.      {"dx",       BL_DX},
  81.      {"co",       BL_CO},
  82.      {"con",      BL_CO},
  83.      {"points",   BL_SCORE},
  84.      {"cap",      BL_CAP},
  85.      {"pw",       BL_ENE},
  86.      {"pw-max",   BL_ENEMAX},
  87.      {"xl",       BL_XP},
  88.      {"xplvl",    BL_XP},
  89.      {"ac",       BL_AC},
  90.      {"hit-dice", BL_HD},
  91.      {"turns",    BL_TIME},
  92.      {"hp",       BL_HP},
  93.      {"hp-max",   BL_HPMAX},
  94.      {"dgn",      BL_LEVELDESC},
  95.      {"xp",       BL_EXP},
  96.      {"exp",      BL_EXP},
  97.      {"flags",    BL_CONDITION},
  98.      {0,          BL_FLUSH}
  99.  };
  100.  

fldname_to_bl_indx

  1.  /* field name to bottom line index */
  2.  STATIC_OVL enum statusfields
  3.  fldname_to_bl_indx(name)
  4.  const char *name;
  5.  {
  6.      int i, nmatches = 0, fld = 0;
  7.  
  8.      if (name && *name) {
  9.          /* check matches to canonical names */
  10.          for (i = 0; i < SIZE(initblstats); i++)
  11.              if (fuzzymatch(initblstats[i].fldname, name, " -_", TRUE)) {
  12.                  fld = initblstats[i].fld;
  13.                  nmatches++;
  14.              }
  15.  
  16.          if (!nmatches) {
  17.              /* check aliases */
  18.              for (i = 0; fieldids_alias[i].fieldname; i++)
  19.                  if (fuzzymatch(fieldids_alias[i].fieldname, name,
  20.                                 " -_", TRUE)) {
  21.                      fld = fieldids_alias[i].fldid;
  22.                      nmatches++;
  23.                  }
  24.          }
  25.  
  26.          if (!nmatches) {
  27.              /* check partial matches to canonical names */
  28.              int len = (int) strlen(name);
  29.              for (i = 0; i < SIZE(initblstats); i++)
  30.                  if (!strncmpi(name, initblstats[i].fldname, len)) {
  31.                      fld = initblstats[i].fld;
  32.                      nmatches++;
  33.                  }
  34.          }
  35.  
  36.      }
  37.      return (nmatches == 1) ? fld : BL_FLUSH;
  38.  }
  39.  

hilite_reset_needed

  1.  STATIC_OVL boolean
  2.  hilite_reset_needed(bl_p, augmented_time)
  3.  struct istat_s *bl_p;
  4.  long augmented_time;
  5.  {
  6.      struct hilite_s *tl = bl_p->thresholds;
  7.  
  8.      /*
  9.       * This 'multi' handling may need some tuning...
  10.       */
  11.      if (multi)
  12.          return FALSE;
  13.  
  14.      if (bl_p->time == 0 || bl_p->time >= augmented_time)
  15.          return FALSE;
  16.  
  17.      while (tl) {
  18.          /* only this style times out */
  19.          if (tl->behavior == BL_TH_UPDOWN)
  20.              return TRUE;
  21.          tl = tl->next;
  22.      }
  23.  
  24.      return FALSE;
  25.  }
  26.  

reset_status_hilites

  1.  /* called by options handling when 'statushilites' boolean is toggled */
  2.  void
  3.  reset_status_hilites()
  4.  {
  5.      if (iflags.hilite_delta) {
  6.          int i;
  7.  
  8.          for (i = 0; i < MAXBLSTATS; ++i)
  9.              blstats[0][i].time = blstats[1][i].time = 0L;
  10.          update_all = TRUE;
  11.      }
  12.      context.botlx = TRUE;
  13.  }
  14.  

merge_bestcolor

  1.  STATIC_OVL void
  2.  merge_bestcolor(bestcolor, newcolor)
  3.  int *bestcolor;
  4.  int newcolor;
  5.  {
  6.      int natr = HL_UNDEF, nclr = NO_COLOR;
  7.  
  8.      split_clridx(newcolor, &nclr, &natr);
  9.  
  10.      if (nclr != NO_COLOR)
  11.          *bestcolor = (*bestcolor & 0xff00) | nclr;
  12.  
  13.      if (natr != HL_UNDEF) {
  14.          if (natr == HL_NONE)
  15.              *bestcolor = *bestcolor & 0x00ff; /* reset all attributes */
  16.          else
  17.              *bestcolor |= (natr << 8); /* merge attributes */
  18.      }
  19.  }
  20.  

get_hilite_color

  1.  /*
  2.   * get_hilite_color
  3.   * 
  4.   * Figures out, based on the value and the
  5.   * direction it is moving, the color that the field
  6.   * should be displayed in.
  7.   *
  8.   *
  9.   * Provide get_hilite_color() with the following
  10.   * to work with:
  11.   *     actual value vp
  12.   *          useful for BL_TH_VAL_ABSOLUTE
  13.   *     indicator of down, up, or the same (-1, 1, 0) chg
  14.   *          useful for BL_TH_UPDOWN or change detection
  15.   *     percentage (current value percentage of max value) pc
  16.   *          useful for BL_TH_VAL_PERCENTAGE
  17.   *
  18.   * Get back:
  19.   *     color     based on user thresholds set in config file.
  20.   *               The rightmost 8 bits contain a color index.
  21.   *               The 8 bits to the left of that contain
  22.   *               the attribute bits.
  23.   *                   color = 0x00FF
  24.   *                   attrib= 0xFF00
  25.   */
  26.  
  27.  STATIC_OVL void
  28.  get_hilite_color(idx, fldidx, vp, chg, pc, colorptr)
  29.  int idx, fldidx, chg, pc;
  30.  genericptr_t vp;
  31.  int *colorptr;
  32.  {
  33.      int bestcolor = NO_COLOR;
  34.      struct hilite_s *hl;
  35.      anything *value = (anything *)vp;
  36.      char *txtstr, *cmpstr;
  37.  
  38.      if (!colorptr || fldidx < 0 || fldidx >= MAXBLSTATS)
  39.          return;
  40.  
  41.      if (blstats[idx][fldidx].thresholds) {
  42.          /* there are hilites set here */
  43.          int max_pc = 0, min_pc = 100;
  44.          int max_val = 0, min_val = LARGEST_INT;
  45.          boolean exactmatch = FALSE;
  46.  
  47.          hl = blstats[idx][fldidx].thresholds;
  48.  
  49.          while (hl) {
  50.              switch (hl->behavior) {
  51.              case BL_TH_VAL_PERCENTAGE:
  52.                  if (hl->rel == EQ_VALUE && pc == hl->value.a_int) {
  53.                      merge_bestcolor(&bestcolor, hl->coloridx);
  54.                      min_pc = max_pc = hl->value.a_int;
  55.                      exactmatch = TRUE;
  56.                  } else if (hl->rel == LT_VALUE && !exactmatch
  57.                             && (hl->value.a_int >= pc)
  58.                             && (hl->value.a_int <= min_pc)) {
  59.                      merge_bestcolor(&bestcolor, hl->coloridx);
  60.                      min_pc = hl->value.a_int;
  61.                  } else if (hl->rel == GT_VALUE && !exactmatch
  62.                             && (hl->value.a_int <= pc)
  63.                             && (hl->value.a_int >= max_pc)) {
  64.                      merge_bestcolor(&bestcolor, hl->coloridx);
  65.                      max_pc = hl->value.a_int;
  66.                  }
  67.                  break;
  68.              case BL_TH_UPDOWN:
  69.                  if (chg < 0 && hl->rel == LT_VALUE) {
  70.                      merge_bestcolor(&bestcolor, hl->coloridx);
  71.                  } else if (chg > 0 && hl->rel == GT_VALUE) {
  72.                      merge_bestcolor(&bestcolor, hl->coloridx);
  73.                  } else if (hl->rel == EQ_VALUE && chg) {
  74.                      merge_bestcolor(&bestcolor, hl->coloridx);
  75.                      min_val = max_val = hl->value.a_int;
  76.                  }
  77.                  break;
  78.              case BL_TH_VAL_ABSOLUTE:
  79.                  if (hl->rel == EQ_VALUE && hl->value.a_int == value->a_int) {
  80.                      merge_bestcolor(&bestcolor, hl->coloridx);
  81.                      min_val = max_val = hl->value.a_int;
  82.                      exactmatch = TRUE;
  83.                  } else if (hl->rel == LT_VALUE && !exactmatch
  84.                             && (hl->value.a_int >= value->a_int)
  85.                             && (hl->value.a_int < min_val)) {
  86.                      merge_bestcolor(&bestcolor, hl->coloridx);
  87.                      min_val = hl->value.a_int;
  88.                  } else if (hl->rel == GT_VALUE && !exactmatch
  89.                             && (hl->value.a_int <= value->a_int)
  90.                             && (hl->value.a_int > max_val)) {
  91.                      merge_bestcolor(&bestcolor, hl->coloridx);
  92.                      max_val = hl->value.a_int;
  93.                  }
  94.                  break;
  95.              case BL_TH_TEXTMATCH:
  96.                  txtstr = dupstr(blstats[idx][fldidx].val);
  97.                  cmpstr = txtstr;
  98.                  if (fldidx == BL_TITLE) {
  99.                      int len = (strlen(plname) + sizeof(" the"));
  100.                      cmpstr += len;
  101.                  }
  102.                  (void) trimspaces(cmpstr);
  103.                  if (hl->rel == TXT_VALUE && hl->textmatch[0] &&
  104.                      !strcmpi(hl->textmatch, cmpstr)) {
  105.                      merge_bestcolor(&bestcolor, hl->coloridx);
  106.                  }
  107.                  free(txtstr);
  108.                  break;
  109.              case BL_TH_ALWAYS_HILITE:
  110.                  merge_bestcolor(&bestcolor, hl->coloridx);
  111.                  break;
  112.              case BL_TH_NONE:
  113.                  break;
  114.              default:
  115.                  break;
  116.              }
  117.              hl = hl->next;
  118.  	}
  119.      }
  120.      *colorptr = bestcolor;
  121.      return;
  122.  }
  123.  

split_clridx

  1.  STATIC_OVL void
  2.  split_clridx(idx, coloridx, attrib)
  3.  int idx;
  4.  int *coloridx, *attrib;
  5.  {
  6.      if (idx && coloridx && attrib) {
  7.             *coloridx = idx & 0x00FF;
  8.             *attrib = (idx & 0xFF00) >> 8;
  9.      }
  10.  }
  11.  
  12.  

parse_status_hl1

  1.  /*
  2.   * This is the parser for the hilite options
  3.   *
  4.   * parse_status_hl1() separates each hilite entry into
  5.   * a set of field threshold/action component strings,
  6.   * then calls parse_status_hl2() to parse further
  7.   * and configure the hilite.
  8.   */
  9.  boolean
  10.  parse_status_hl1(op, from_configfile)
  11.  char *op;
  12.  boolean from_configfile;
  13.  {
  14.  #define MAX_THRESH 21
  15.      char hsbuf[MAX_THRESH][QBUFSZ];
  16.      boolean rslt, badopt = FALSE;
  17.      int i, fldnum, ccount = 0;
  18.      char c;
  19.  
  20.      fldnum = 0;
  21.      for (i = 0; i < MAX_THRESH; ++i) {
  22.          hsbuf[i][0] = '\0';
  23.      }
  24.      while (*op && fldnum < MAX_THRESH && ccount < (QBUFSZ - 2)) {
  25.          c = lowc(*op);
  26.          if (c == ' ') {
  27.              if (fldnum >= 1) {
  28.                  rslt = parse_status_hl2(hsbuf, from_configfile);
  29.                  if (!rslt) {
  30.                      badopt = TRUE;
  31.                      break;
  32.                  }
  33.              }
  34.              for (i = 0; i < MAX_THRESH; ++i) {
  35.                  hsbuf[i][0] = '\0';
  36.              }
  37.              fldnum = 0;
  38.              ccount = 0;
  39.          } else if (c == '/') {
  40.              fldnum++;
  41.              ccount = 0;
  42.          } else {
  43.              hsbuf[fldnum][ccount++] = c;
  44.              hsbuf[fldnum][ccount] = '\0';
  45.          }
  46.          op++;
  47.      }
  48.      if (fldnum >= 1 && !badopt) {
  49.          rslt = parse_status_hl2(hsbuf, from_configfile);
  50.          if (!rslt)
  51.              badopt = TRUE;
  52.      }
  53.      if (badopt)
  54.          return FALSE;
  55.      return TRUE;
  56.  }
  57.  

is_ltgt_percentnumber

  1.  /* is str in the format of "(<>)?[0-9]+%?" regex */
  2.  STATIC_OVL boolean
  3.  is_ltgt_percentnumber(str)
  4.  const char *str;
  5.  {
  6.      const char *s = str;
  7.  
  8.      if (*s == '<' || *s == '>') s++;
  9.      while (digit(*s)) s++;
  10.      if (*s == '%') s++;
  11.  
  12.      return (*s == '\0');
  13.  }
  14.  

has_ltgt_percentnumber

  1.  /* does str only contain "<>0-9%" chars */
  2.  STATIC_OVL boolean
  3.  has_ltgt_percentnumber(str)
  4.  const char *str;
  5.  {
  6.      const char *s = str;
  7.  
  8.      while (*s) {
  9.          if (!index("<>0123456789%", *s))
  10.              return FALSE;
  11.          s++;
  12.      }
  13.      return TRUE;
  14.  }
  15.  

splitsubfields

  1.  /* splitsubfields(): splits str in place into '+' or '&' separated strings.
  2.   * returns number of strings, or -1 if more than maxsf or MAX_SUBFIELDS
  3.   */
  4.  #define MAX_SUBFIELDS 16
  5.  STATIC_OVL int
  6.  splitsubfields(str, sfarr, maxsf)
  7.  char *str;
  8.  char ***sfarr;
  9.  int maxsf;
  10.  {
  11.      static char *subfields[MAX_SUBFIELDS];
  12.      char *st = (char *) 0;
  13.      int sf = 0;
  14.  
  15.      if (!str)
  16.          return 0;
  17.      for (sf = 0; sf < MAX_SUBFIELDS; ++sf)
  18.          subfields[sf] = (char *) 0;
  19.  
  20.      maxsf = (maxsf == 0) ? MAX_SUBFIELDS : min(maxsf, MAX_SUBFIELDS);
  21.  
  22.      if (index(str, '+') || index(str, '&')) {
  23.          char *c = str;
  24.  
  25.          sf = 0;
  26.          st = c;
  27.          while (*c && sf < maxsf) {
  28.              if (*c == '&' || *c == '+') {
  29.                  *c = '\0';
  30.                  subfields[sf] = st;
  31.                  st = c+1;
  32.                  sf++;
  33.              }
  34.              c++;
  35.          }
  36.          if (sf >= maxsf - 1)
  37.              return -1;
  38.          if (!*c && c != st)
  39.              subfields[sf++] = st;
  40.      } else {
  41.          sf = 1;
  42.          subfields[0] = str;
  43.      }
  44.      *sfarr = subfields;
  45.      return sf;
  46.  }
  47.  #undef MAX_SUBFIELDS
  48.  

is_fld_arrayvalues

  1.  boolean
  2.  is_fld_arrayvalues(str, arr, arrmin, arrmax, retidx)
  3.  const char *str;
  4.  const char *const *arr;
  5.  int arrmin, arrmax;
  6.  int *retidx;
  7.  {
  8.      int i;
  9.  
  10.      for (i = arrmin; i < arrmax; i++)
  11.          if (!strcmpi(str, arr[i])) {
  12.              *retidx = i;
  13.              return TRUE;
  14.          }
  15.      return FALSE;
  16.  }
  17.  

query_arrayvalue

  1.  int
  2.  query_arrayvalue(querystr, arr, arrmin, arrmax)
  3.  const char *querystr;
  4.  const char *const *arr;
  5.  int arrmin, arrmax;
  6.  {
  7.      int i, res, ret = arrmin - 1;
  8.      winid tmpwin;
  9.      anything any;
  10.      menu_item *picks = (menu_item *) 0;
  11.      int adj = (arrmin > 0) ? 1 : arrmax;
  12.  
  13.      tmpwin = create_nhwindow(NHW_MENU);
  14.      start_menu(tmpwin);
  15.  
  16.      for (i = arrmin; i < arrmax; i++) {
  17.          any = zeroany;
  18.          any.a_int = i + adj;
  19.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  20.                   arr[i], MENU_UNSELECTED);
  21.      }
  22.  
  23.      end_menu(tmpwin, querystr);
  24.  
  25.      res = select_menu(tmpwin, PICK_ONE, &picks);
  26.      destroy_nhwindow(tmpwin);
  27.      if (res > 0) {
  28.          ret = picks->item.a_int - adj;
  29.          free((genericptr_t) picks);
  30.      }
  31.  
  32.      return ret;
  33.  }
  34.  

status_hilite_add_threshold

  1.  void
  2.  status_hilite_add_threshold(fld, hilite)
  3.  int fld;
  4.  struct hilite_s *hilite;
  5.  {
  6.      struct hilite_s *new_hilite;
  7.  
  8.      if (!hilite)
  9.          return;
  10.  
  11.      /* alloc and initialize a new hilite_s struct */
  12.      new_hilite = (struct hilite_s *) alloc(sizeof(struct hilite_s));
  13.      *new_hilite = *hilite;   /* copy struct */
  14.  
  15.      new_hilite->set = TRUE;
  16.      new_hilite->fld = fld;
  17.      new_hilite->next = (struct hilite_s *)0;
  18.  
  19.      /* Does that status field currently have any hilite thresholds? */
  20.      if (!blstats[0][fld].thresholds) {
  21.          blstats[0][fld].thresholds = new_hilite;
  22.      } else {
  23.          struct hilite_s *temp_hilite = blstats[0][fld].thresholds;
  24.          new_hilite->next = temp_hilite;
  25.          blstats[0][fld].thresholds = new_hilite;
  26.          /* sort_hilites(fld) */
  27.      }
  28.      /* current and prev must both point at the same hilites */
  29.      blstats[1][fld].thresholds = blstats[0][fld].thresholds;
  30.  }
  31.  
  32.  

parse_status_hl2

  1.  STATIC_OVL boolean
  2.  parse_status_hl2(s, from_configfile)
  3.  char (*s)[QBUFSZ];
  4.  boolean from_configfile;
  5.  {
  6.      char *tmp, *how;
  7.      int sidx = 0, i = -1, dt = -1;
  8.      int coloridx = -1, successes = 0;
  9.      int disp_attrib = 0;
  10.      boolean percent = FALSE, changed = FALSE, numeric = FALSE;
  11.      boolean down= FALSE, up = FALSE;
  12.      boolean gt = FALSE, lt = FALSE, eq = FALSE, neq = FALSE;
  13.      boolean txtval = FALSE;
  14.      boolean always = FALSE;
  15.      const char *txt;
  16.      enum statusfields fld = BL_FLUSH;
  17.      struct hilite_s hilite;
  18.      char tmpbuf[BUFSZ];
  19.      const char *aligntxt[] = {"chaotic", "neutral", "lawful"};
  20.      /* hu_stat[] from eat.c has trailing spaces which foul up comparisons */
  21.      const char *hutxt[] = {"Satiated", "", "Hungry", "Weak",
  22.                             "Fainting", "Fainted", "Starved"};
  23.  
  24.      /* Examples:
  25.          3.6.1:
  26.        OPTION=hilite_status: hitpoints/<10%/red
  27.        OPTION=hilite_status: hitpoints/<10%/red/<5%/purple/1/red+blink+inverse
  28.        OPTION=hilite_status: experience/down/red/up/green
  29.        OPTION=hilite_status: cap/strained/yellow/overtaxed/orange
  30.        OPTION=hilite_status: title/always/blue
  31.        OPTION=hilite_status: title/blue
  32.      */
  33.  
  34.      /* field name to statusfield */
  35.      fld = fldname_to_bl_indx(s[sidx]);
  36.  
  37.      if (fld == BL_CHARACTERISTICS) {
  38.          boolean res = FALSE;
  39.  
  40.          /* recursively set each of strength, dexterity, constitution, &c */
  41.          for (fld = BL_STR; fld <= BL_CH; fld++) {
  42.              Strcpy(s[sidx], initblstats[fld].fldname);
  43.              res = parse_status_hl2(s, from_configfile);
  44.              if (!res)
  45.                  return FALSE;
  46.          }
  47.          return TRUE;
  48.      }
  49.      if (fld == BL_FLUSH) {
  50.          config_error_add("Unknown status field '%s'", s[sidx]);
  51.          return FALSE;
  52.      }
  53.      if (fld == BL_CONDITION)
  54.          return parse_condition(s, sidx);
  55.  
  56.      ++sidx;
  57.      while(s[sidx]) {
  58.          char buf[BUFSZ], **subfields;
  59.          int sf = 0;     /* subfield count */
  60.          int kidx;
  61.  
  62.          txt = (const char *)0;
  63.          percent = changed = numeric = FALSE;
  64.          down = up = FALSE;
  65.          gt = eq = lt = neq = txtval = FALSE;
  66.          always = FALSE;
  67.  
  68.          /* threshold value */
  69.          if (!s[sidx][0])
  70.              return TRUE;
  71.  
  72.          memset((genericptr_t) &hilite, 0, sizeof(struct hilite_s));
  73.          hilite.set = FALSE; /* mark it "unset" */
  74.          hilite.fld = fld;
  75.  
  76.          if (*s[sidx+1] == '\0' || !strcmpi(s[sidx], "always")) {
  77.              /* "field/always/color" OR "field/color" */
  78.              always = TRUE;
  79.              if (*s[sidx+1] == '\0')
  80.                  sidx--;
  81.              goto do_rel;
  82.          } else if (!strcmpi(s[sidx], "up") || !strcmpi(s[sidx], "down")) {
  83.              if (!strcmpi(s[sidx], "down"))
  84.                  down = TRUE;
  85.              else
  86.                  up = TRUE;
  87.              changed = TRUE;
  88.              goto do_rel;
  89.  	} else if (fld == BL_CAP
  90.                     && is_fld_arrayvalues(s[sidx], enc_stat,
  91.                                           SLT_ENCUMBER, OVERLOADED+1, &kidx)) {
  92.              txt = enc_stat[kidx];
  93.              txtval = TRUE;
  94.  	    goto do_rel;
  95.          } else if (fld == BL_ALIGN
  96.                     && is_fld_arrayvalues(s[sidx], aligntxt, 0, 3, &kidx)) {
  97.              txt = aligntxt[kidx];
  98.              txtval = TRUE;
  99.              goto do_rel;
  100.          } else if (fld == BL_HUNGER
  101.                     && is_fld_arrayvalues(s[sidx], hutxt,
  102.                                           SATIATED, STARVED+1, &kidx)) {
  103.              txt = hu_stat[kidx];   /* store hu_stat[] val, not hutxt[] */
  104.              txtval = TRUE;
  105.              goto do_rel;
  106.          } else if (!strcmpi(s[sidx], "changed")) {
  107.              changed = TRUE;
  108.              goto do_rel;
  109.          } else if (is_ltgt_percentnumber(s[sidx])) {
  110.              tmp = s[sidx];
  111.              if (strchr(tmp, '%'))
  112.                 percent = TRUE;
  113.              if (strchr(tmp, '<'))
  114.                  lt = TRUE;
  115.              if (strchr(tmp, '>'))
  116.                  gt = TRUE;
  117.              (void) stripchars(tmpbuf, "%<>", tmp);
  118.              tmp = tmpbuf;
  119.              while (*tmp) {
  120.                  if (!index("0123456789", *tmp))
  121.                      return FALSE;
  122.                  tmp++;
  123.              }
  124.              numeric = TRUE;
  125.              tmp = tmpbuf;
  126.              if (strlen(tmp) > 0) {
  127.                  dt = initblstats[fld].anytype;
  128.                  if (percent)
  129.                      dt = ANY_INT;
  130.                  (void) s_to_anything(&hilite.value, tmp, dt);
  131.              } else
  132.                  return FALSE;
  133.              if (!hilite.value.a_void && (strcmp(tmp, "0") != 0))
  134.                 return FALSE;
  135.          } else if (initblstats[fld].anytype == ANY_STR) {
  136.              txt = s[sidx];
  137.              txtval = TRUE;
  138.              goto do_rel;
  139.          } else {
  140.              config_error_add(has_ltgt_percentnumber(s[sidx])
  141.                   ? "Wrong format '%s', expected a threshold number or percent"
  142.                   : "Unknown behavior '%s'", s[sidx]);
  143.              return FALSE;
  144.          }
  145.  do_rel:
  146.          /* relationships { LT_VALUE, GT_VALUE, EQ_VALUE} */
  147.          if (gt)
  148.              hilite.rel = GT_VALUE;
  149.          else if (eq)
  150.              hilite.rel = EQ_VALUE;
  151.          else if (lt)
  152.              hilite.rel = LT_VALUE;
  153.          else if (percent)
  154.              hilite.rel = EQ_VALUE;
  155.          else if (numeric)
  156.              hilite.rel = EQ_VALUE;
  157.          else if (down)
  158.              hilite.rel = LT_VALUE;
  159.          else if (up)
  160.              hilite.rel = GT_VALUE;
  161.          else if (changed)
  162.              hilite.rel = EQ_VALUE;
  163.          else if (txtval)
  164.              hilite.rel = TXT_VALUE;
  165.          else
  166.              hilite.rel = LT_VALUE;
  167.  
  168.          if (initblstats[fld].anytype == ANY_STR
  169.              && (percent || numeric)) {
  170.              config_error_add("Field '%s' does not support numeric values",
  171.                               initblstats[fld].fldname);
  172.              return FALSE;
  173.          }
  174.  
  175.          if (percent) {
  176.              if (initblstats[fld].idxmax <= BL_FLUSH) {
  177.                  config_error_add("Cannot use percent with '%s'",
  178.                                   initblstats[fld].fldname);
  179.                  return FALSE;
  180.              } else if ((hilite.value.a_int < 0)
  181.                         || (hilite.value.a_int == 0
  182.                             && hilite.rel == LT_VALUE)
  183.                         || (hilite.value.a_int > 100)
  184.                         || (hilite.value.a_int == 100
  185.                             && hilite.rel == GT_VALUE)) {
  186.                  config_error_add("Illegal percentage value");
  187.                  return FALSE;
  188.              }
  189.          }
  190.  
  191.          /* actions */
  192.          sidx++;
  193.          how = s[sidx];
  194.          if (!how) {
  195.              if (!successes)
  196.                  return FALSE;
  197.          }
  198.          coloridx = -1;
  199.          Strcpy(buf, how);
  200.          sf = splitsubfields(buf, &subfields, 0);
  201.  
  202.          if (sf < 1)
  203.              return FALSE;
  204.  
  205.          disp_attrib = HL_UNDEF;
  206.  
  207.          for (i = 0; i < sf; ++i) {
  208.              int a = match_str2attr(subfields[i], FALSE);
  209.              if (a == ATR_DIM)
  210.                  disp_attrib |= HL_DIM;
  211.              else if (a == ATR_BLINK)
  212.                  disp_attrib |= HL_BLINK;
  213.              else if (a == ATR_ULINE)
  214.                  disp_attrib |= HL_ULINE;
  215.              else if (a == ATR_INVERSE)
  216.                  disp_attrib |= HL_INVERSE;
  217.              else if (a == ATR_BOLD)
  218.                  disp_attrib |= HL_BOLD;
  219.              else if (a == ATR_NONE)
  220.                  disp_attrib = HL_NONE;
  221.              else {
  222.                  int c = match_str2clr(subfields[i]);
  223.  
  224.                  if (c >= CLR_MAX || coloridx != -1)
  225.                      return FALSE;
  226.                  coloridx = c;
  227.  	    }
  228.          }
  229.          if (coloridx == -1)
  230.              coloridx = NO_COLOR;
  231.  
  232.          /* Assign the values */
  233.          hilite.coloridx = coloridx | (disp_attrib << 8);
  234.  
  235.          if (always)
  236.              hilite.behavior = BL_TH_ALWAYS_HILITE;
  237.          else if (percent)
  238.              hilite.behavior = BL_TH_VAL_PERCENTAGE;
  239.          else if (changed)
  240.              hilite.behavior = BL_TH_UPDOWN;
  241.          else if (numeric)
  242.              hilite.behavior = BL_TH_VAL_ABSOLUTE;
  243.          else if (txtval)
  244.              hilite.behavior = BL_TH_TEXTMATCH;
  245.          else if (hilite.value.a_void)
  246.              hilite.behavior = BL_TH_VAL_ABSOLUTE;
  247.         else
  248.              hilite.behavior = BL_TH_NONE;
  249.  
  250.          hilite.anytype = dt;
  251.  
  252.          if (hilite.behavior == BL_TH_TEXTMATCH && txt
  253.              && strlen(txt) < QBUFSZ-1) {
  254.              Strcpy(hilite.textmatch, txt);
  255.              (void) trimspaces(hilite.textmatch);
  256.          }
  257.  
  258.          status_hilite_add_threshold(fld, &hilite);
  259.  
  260.          successes++;
  261.          sidx++;
  262.      }
  263.  
  264.      return TRUE;
  265.  }
  266.  
  267.  
  268.  
  269.  const struct condmap valid_conditions[] = {
  270.      {"stone",    BL_MASK_STONE},
  271.      {"slime",    BL_MASK_SLIME},
  272.      {"strngl",   BL_MASK_STRNGL},
  273.      {"foodPois", BL_MASK_FOODPOIS},
  274.      {"termIll",  BL_MASK_TERMILL},
  275.      {"blind",    BL_MASK_BLIND},
  276.      {"deaf",     BL_MASK_DEAF},
  277.      {"stun",     BL_MASK_STUN},
  278.      {"conf",     BL_MASK_CONF},
  279.      {"hallu",    BL_MASK_HALLU},
  280.      {"lev",      BL_MASK_LEV},
  281.      {"fly",      BL_MASK_FLY},
  282.      {"ride",     BL_MASK_RIDE},
  283.  };
  284.  
  285.  const struct condmap condition_aliases[] = {
  286.      {"strangled",      BL_MASK_STRNGL},
  287.      {"all",            BL_MASK_STONE | BL_MASK_SLIME | BL_MASK_STRNGL |
  288.                         BL_MASK_FOODPOIS | BL_MASK_TERMILL |
  289.                         BL_MASK_BLIND | BL_MASK_DEAF | BL_MASK_STUN |
  290.                         BL_MASK_CONF | BL_MASK_HALLU |
  291.                         BL_MASK_LEV | BL_MASK_FLY | BL_MASK_RIDE },
  292.      {"major_troubles", BL_MASK_STONE | BL_MASK_SLIME | BL_MASK_STRNGL |
  293.                         BL_MASK_FOODPOIS | BL_MASK_TERMILL},
  294.      {"minor_troubles", BL_MASK_BLIND | BL_MASK_DEAF | BL_MASK_STUN |
  295.                         BL_MASK_CONF | BL_MASK_HALLU},
  296.      {"movement",       BL_MASK_LEV | BL_MASK_FLY | BL_MASK_RIDE}
  297.  };
  298.  

query_conditions

  1.  unsigned long
  2.  query_conditions()
  3.  {
  4.      int i,res;
  5.      unsigned long ret = 0UL;
  6.      winid tmpwin;
  7.      anything any;
  8.      menu_item *picks = (menu_item *) 0;
  9.  
  10.      tmpwin = create_nhwindow(NHW_MENU);
  11.      start_menu(tmpwin);
  12.  
  13.      for (i = 0; i < SIZE(valid_conditions); i++) {
  14.          any = zeroany;
  15.          any.a_ulong = valid_conditions[i].bitmask;
  16.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  17.                   valid_conditions[i].id, MENU_UNSELECTED);
  18.      }
  19.  
  20.      end_menu(tmpwin, "Choose status conditions");
  21.  
  22.      res = select_menu(tmpwin, PICK_ANY, &picks);
  23.      destroy_nhwindow(tmpwin);
  24.      if (res > 0) {
  25.          for (i = 0; i < res; i++)
  26.              ret |= picks[i].item.a_ulong;
  27.          free((genericptr_t) picks);
  28.      }
  29.      return ret;
  30.  }
  31.  

conditionbitmask2str

  1.  STATIC_OVL char *
  2.  conditionbitmask2str(ul)
  3.  unsigned long ul;
  4.  {
  5.      static char buf[BUFSZ];
  6.      int i;
  7.      boolean first = TRUE;
  8.      const char *alias = (char *) 0;
  9.  
  10.  
  11.      buf[0] = '\0';
  12.      if (!ul)
  13.          return buf;
  14.  
  15.      for (i = 1; i < SIZE(condition_aliases); i++)
  16.          if (condition_aliases[i].bitmask == ul)
  17.              alias = condition_aliases[i].id;
  18.  
  19.      for (i = 0; i < SIZE(valid_conditions); i++)
  20.          if ((valid_conditions[i].bitmask & ul) != 0UL) {
  21.              Sprintf(eos(buf), "%s%s", (first) ? "" : "+",
  22.                      valid_conditions[i].id);
  23.              first = FALSE;
  24.          }
  25.  
  26.      if (!first && alias)
  27.          Sprintf(buf, "%s", alias);
  28.  
  29.      return buf;
  30.  }
  31.  

match_str2conditionbitmask

  1.  STATIC_OVL unsigned long
  2.  match_str2conditionbitmask(str)
  3.  const char *str;
  4.  {
  5.      int i, nmatches = 0;
  6.      unsigned long mask = 0UL;
  7.  
  8.      if (str && *str) {
  9.          /* check matches to canonical names */
  10.          for (i = 0; i < SIZE(valid_conditions); i++)
  11.              if (fuzzymatch(valid_conditions[i].id, str, " -_", TRUE)) {
  12.                  mask |= valid_conditions[i].bitmask;
  13.                  nmatches++;
  14.              }
  15.  
  16.          if (!nmatches) {
  17.              /* check aliases */
  18.              for (i = 0; i < SIZE(condition_aliases); i++)
  19.                  if (fuzzymatch(condition_aliases[i].id, str, " -_", TRUE)) {
  20.                      mask |= condition_aliases[i].bitmask;
  21.                      nmatches++;
  22.                  }
  23.          }
  24.  
  25.          if (!nmatches) {
  26.              /* check partial matches to aliases */
  27.              int len = (int) strlen(str);
  28.              for (i = 0; i < SIZE(condition_aliases); i++)
  29.                  if (!strncmpi(str, condition_aliases[i].id, len)) {
  30.                      mask |= condition_aliases[i].bitmask;
  31.                      nmatches++;
  32.                  }
  33.          }
  34.      }
  35.  
  36.      return mask;
  37.  }
  38.  

str2conditionbitmask

  1.  STATIC_OVL unsigned long
  2.  str2conditionbitmask(str)
  3.  char *str;
  4.  {
  5.      unsigned long conditions_bitmask = 0UL;
  6.      char **subfields;
  7.      int i, sf;
  8.  
  9.      sf = splitsubfields(str, &subfields, SIZE(valid_conditions));
  10.  
  11.      if (sf < 1)
  12.          return 0UL;
  13.  
  14.      for (i = 0; i < sf; ++i) {
  15.          unsigned long bm = match_str2conditionbitmask(subfields[i]);
  16.  
  17.          if (!bm) {
  18.              config_error_add("Unknown condition '%s'", subfields[i]);
  19.              return 0UL;
  20.          }
  21.          conditions_bitmask |= bm;
  22.      }
  23.      return conditions_bitmask;
  24.  }
  25.  

parse_condition

  1.  STATIC_OVL boolean
  2.  parse_condition(s, sidx)
  3.  char (*s)[QBUFSZ];
  4.  int sidx;
  5.  {
  6.      int i;
  7.      int coloridx = NO_COLOR;
  8.      char *tmp, *how;
  9.      unsigned long conditions_bitmask = 0UL;
  10.      boolean success = FALSE;
  11.  
  12.      if (!s)
  13.          return FALSE;
  14.  
  15.      /*3.6.1:
  16.        OPTION=hilite_status: condition/stone+slime+foodPois/red&inverse */
  17.  
  18.      sidx++;
  19.      while(s[sidx]) {
  20.          int sf = 0;     /* subfield count */
  21.          char buf[BUFSZ], **subfields;
  22.  
  23.          tmp = s[sidx];
  24.          if (!*tmp) {
  25.              if (!success)
  26.                  config_error_add("Missing condition(s)");
  27.              return success;
  28.  	}
  29.  
  30.          Strcpy(buf, tmp);
  31.          conditions_bitmask = str2conditionbitmask(buf);
  32.  
  33.          if (!conditions_bitmask)
  34.              return FALSE;
  35.  
  36.          /*
  37.           * We have the conditions_bitmask with bits set for
  38.           * each ailment we want in a particular color and/or
  39.           * attribute, but we need to assign it to an arry of
  40.           * bitmasks indexed by the color chosen
  41.           *        (0 to (CLR_MAX - 1))
  42.           * and/or attributes chosen
  43.           *        (HL_ATTCLR_DIM to (BL_ATTCLR_MAX - 1))
  44.           * We still have to parse the colors and attributes out.
  45.           */
  46.  
  47.          /* actions */
  48.          sidx++;
  49.          how = s[sidx];
  50.          if (!how || !*how) {
  51.              config_error_add("Missing color+attribute");
  52.              return FALSE;
  53.          }
  54.  
  55.          Strcpy(buf, how);
  56.          sf = splitsubfields(buf, &subfields, 0);
  57.  
  58.          /*
  59.           * conditions_bitmask now has bits set representing
  60.           * the conditions that player wants represented, but
  61.           * now we parse out *how* they will be represented.
  62.           *
  63.           * Only 1 colour is allowed, but potentially multiple
  64.           * attributes are allowed.
  65.           *
  66.           * We have the following additional array offsets to
  67.           * use for storing the attributes beyond the end of
  68.           * the color indexes, all of which are less than CLR_MAX.
  69.           * HL_ATTCLR_DIM        = CLR_MAX
  70.           * HL_ATTCLR_BLINK      = CLR_MAX + 1
  71.           * HL_ATTCLR_ULINE      = CLR_MAX + 2
  72.           * HL_ATTCLR_INVERSE    = CLR_MAX + 3
  73.           * HL_ATTCLR_BOLD       = CLR_MAX + 4
  74.           * HL_ATTCLR_MAX        = CLR_MAX + 5 (this is past array boundary)
  75.           *
  76.           */
  77.  
  78.          for (i = 0; i < sf; ++i) {
  79.              int a = match_str2attr(subfields[i], FALSE);
  80.              if (a == ATR_DIM)
  81.                  cond_hilites[HL_ATTCLR_DIM] |= conditions_bitmask;
  82.              else if (a == ATR_BLINK)
  83.                  cond_hilites[HL_ATTCLR_BLINK] |= conditions_bitmask;
  84.              else if (a == ATR_ULINE)
  85.                  cond_hilites[HL_ATTCLR_ULINE] |= conditions_bitmask;
  86.              else if (a == ATR_INVERSE)
  87.                  cond_hilites[HL_ATTCLR_INVERSE] |= conditions_bitmask;
  88.              else if (a == ATR_BOLD)
  89.                  cond_hilites[HL_ATTCLR_BOLD] |= conditions_bitmask;
  90.              else if (a == ATR_NONE) {
  91.                  cond_hilites[HL_ATTCLR_DIM]     = 0UL;
  92.                  cond_hilites[HL_ATTCLR_BLINK]   = 0UL;
  93.                  cond_hilites[HL_ATTCLR_ULINE]   = 0UL;
  94.                  cond_hilites[HL_ATTCLR_INVERSE] = 0UL;
  95.                  cond_hilites[HL_ATTCLR_BOLD]    = 0UL;
  96.              } else {
  97.                  int k = match_str2clr(subfields[i]);
  98.  
  99.                  if (k >= CLR_MAX)
  100.                      return FALSE;
  101.                  coloridx = k;
  102.  	    }
  103.          }
  104.          /* set the bits in the appropriate member of the
  105.             condition array according to color chosen as index */
  106.  
  107.          cond_hilites[coloridx] |= conditions_bitmask;
  108.          success = TRUE;
  109.          sidx++;
  110.      }
  111.      return TRUE;
  112.  }
  113.  

clear_status_hilites

  1.  void
  2.  clear_status_hilites()
  3.  {
  4.      int i;
  5.  
  6.      for (i = 0; i < MAXBLSTATS; ++i) {
  7.          if (blstats[0][i].thresholds) {
  8.              struct hilite_s *temp = blstats[0][i].thresholds,
  9.                              *next = (struct hilite_s *)0;
  10.              while (temp) {
  11.                  next = temp->next;
  12.                  free(temp);
  13.                  blstats[0][i].thresholds = (struct hilite_s *)0;
  14.                  blstats[1][i].thresholds = blstats[0][i].thresholds;
  15.                  temp = next;
  16.              }
  17.  	}
  18.      }
  19.  }
  20.  

hlattr2attrname

  1.  STATIC_OVL char *
  2.  hlattr2attrname(attrib, buf, bufsz)
  3.  int attrib, bufsz;
  4.  char *buf;
  5.  {
  6.      if (attrib && buf) {
  7.          char attbuf[BUFSZ];
  8.          int k, first = 0;
  9.  
  10.          attbuf[0] = '\0';
  11.          if (attrib & HL_NONE) {
  12.              Strcpy(buf, "normal");
  13.              return buf;
  14.          }
  15.  
  16.          if (attrib & HL_BOLD)
  17.              Strcat(attbuf, first++ ? "+bold" : "bold");
  18.          if (attrib & HL_INVERSE)
  19.              Strcat(attbuf, first++ ? "+inverse" : "inverse");
  20.          if (attrib & HL_ULINE)
  21.              Strcat(attbuf, first++ ? "+underline" : "underline");
  22.          if (attrib & HL_BLINK)
  23.              Strcat(attbuf, first++ ? "+blink" : "blink");
  24.          if (attrib & HL_DIM)
  25.              Strcat(attbuf, first++ ? "+dim" : "dim");
  26.  
  27.          k = strlen(attbuf);
  28.          if (k < (bufsz - 1))
  29.              Strcpy(buf, attbuf);
  30.          return buf;
  31.      }
  32.      return (char *) 0;
  33.  }
  34.  
  35.  
  36.  struct _status_hilite_line_str {
  37.      int id;
  38.      int fld;
  39.      struct hilite_s *hl;
  40.      unsigned long mask;
  41.      char str[BUFSZ];
  42.      struct _status_hilite_line_str *next;
  43.  };
  44.  
  45.  struct _status_hilite_line_str *status_hilite_str =
  46.      (struct _status_hilite_line_str *) 0;
  47.  static int status_hilite_str_id = 0;
  48.  

status_hilite_linestr_add

  1.  STATIC_OVL void
  2.  status_hilite_linestr_add(fld, hl, mask, str)
  3.  int fld;
  4.  struct hilite_s *hl;
  5.  unsigned long mask;
  6.  const char *str;
  7.  {
  8.      struct _status_hilite_line_str *tmp = (struct _status_hilite_line_str *)
  9.          alloc(sizeof(struct _status_hilite_line_str));
  10.      struct _status_hilite_line_str *nxt = status_hilite_str;
  11.  
  12.      (void) memset(tmp, 0, sizeof(struct _status_hilite_line_str));
  13.  
  14.      ++status_hilite_str_id;
  15.      tmp->fld = fld;
  16.      tmp->hl = hl;
  17.      tmp->mask = mask;
  18.      (void) stripchars(tmp->str, " ", str);
  19.  
  20.      tmp->id = status_hilite_str_id;
  21.  
  22.      if (nxt) {
  23.          while (nxt && nxt->next)
  24.              nxt = nxt->next;
  25.          nxt->next = tmp;
  26.      } else {
  27.          tmp->next = (struct _status_hilite_line_str *) 0;
  28.          status_hilite_str = tmp;
  29.      }
  30.  }
  31.  

status_hilite_linestr_done

  1.  STATIC_OVL void
  2.  status_hilite_linestr_done()
  3.  {
  4.      struct _status_hilite_line_str *tmp = status_hilite_str;
  5.      struct _status_hilite_line_str *nxt;
  6.  
  7.      while (tmp) {
  8.          nxt = tmp->next;
  9.          free(tmp);
  10.          tmp = nxt;
  11.      }
  12.      status_hilite_str = (struct _status_hilite_line_str *) 0;
  13.      status_hilite_str_id = 0;
  14.  }
  15.  

status_hilite_linestr_countfield

  1.  STATIC_OVL int
  2.  status_hilite_linestr_countfield(fld)
  3.  int fld;
  4.  {
  5.      struct _status_hilite_line_str *tmp = status_hilite_str;
  6.      int count = 0;
  7.  
  8.      while (tmp) {
  9.          if (tmp->fld == fld || fld == BL_FLUSH)
  10.              count++;
  11.          tmp = tmp->next;
  12.      }
  13.      return count;
  14.  }
  15.  

count_status_hilites

  1.  int
  2.  count_status_hilites(VOID_ARGS)
  3.  {
  4.      int count;
  5.      status_hilite_linestr_gather();
  6.      count = status_hilite_linestr_countfield(BL_FLUSH);
  7.      status_hilite_linestr_done();
  8.      return count;
  9.  }
  10.  

status_hilite_linestr_gather_conditions

  1.  STATIC_OVL void
  2.  status_hilite_linestr_gather_conditions()
  3.  {
  4.      int i;
  5.      struct _cond_map {
  6.          unsigned long bm;
  7.          unsigned long clratr;
  8.      } cond_maps[SIZE(valid_conditions)];
  9.  
  10.      (void)memset(cond_maps, 0,
  11.                   sizeof(struct _cond_map) * SIZE(valid_conditions));
  12.  
  13.      for (i = 0; i < SIZE(valid_conditions); i++) {
  14.          int clr = NO_COLOR;
  15.          int atr = HL_NONE;
  16.          int j;
  17.          for (j = 0; j < CLR_MAX; j++)
  18.              if (cond_hilites[j] & valid_conditions[i].bitmask)
  19.                  clr = j;
  20.          if (cond_hilites[HL_ATTCLR_DIM] & valid_conditions[i].bitmask)
  21.              atr |= HL_DIM;
  22.          if (cond_hilites[HL_ATTCLR_BOLD] & valid_conditions[i].bitmask)
  23.              atr |= HL_BOLD;
  24.          if (cond_hilites[HL_ATTCLR_BLINK] & valid_conditions[i].bitmask)
  25.              atr |= HL_BLINK;
  26.          if (cond_hilites[HL_ATTCLR_ULINE] & valid_conditions[i].bitmask)
  27.              atr |= HL_ULINE;
  28.          if (cond_hilites[HL_ATTCLR_INVERSE] & valid_conditions[i].bitmask)
  29.              atr |= HL_INVERSE;
  30.  
  31.          if (clr != NO_COLOR || atr != HL_NONE) {
  32.              unsigned long ca = clr | (atr << 8);
  33.              boolean added_condmap = FALSE;
  34.              for (j = 0; j < SIZE(valid_conditions); j++)
  35.                  if (cond_maps[j].clratr == ca) {
  36.                      cond_maps[j].bm |= valid_conditions[i].bitmask;
  37.                      added_condmap = TRUE;
  38.                      break;
  39.                  }
  40.              if (!added_condmap) {
  41.                  for (j = 0; j < SIZE(valid_conditions); j++)
  42.                      if (!cond_maps[j].bm) {
  43.                          cond_maps[j].bm = valid_conditions[i].bitmask;
  44.                          cond_maps[j].clratr = ca;
  45.                          break;
  46.                      }
  47.              }
  48.          }
  49.      }
  50.  
  51.      for (i = 0; i < SIZE(valid_conditions); i++)
  52.          if (cond_maps[i].bm) {
  53.              int clr = NO_COLOR, atr = HL_NONE;
  54.              split_clridx(cond_maps[i].clratr, &clr, &atr);
  55.              if (clr != NO_COLOR || atr != HL_NONE) {
  56.                  char clrbuf[BUFSZ];
  57.                  char attrbuf[BUFSZ];
  58.                  char condbuf[BUFSZ];
  59.                  char *tmpattr;
  60.                  (void) stripchars(clrbuf, " ", clr2colorname(clr));
  61.                  tmpattr = hlattr2attrname(atr, attrbuf, BUFSZ);
  62.                  if (tmpattr)
  63.                      Sprintf(eos(clrbuf), "&%s", tmpattr);
  64.                  Sprintf(condbuf, "condition/%s/%s",
  65.                          conditionbitmask2str(cond_maps[i].bm), clrbuf);
  66.                  status_hilite_linestr_add(BL_CONDITION, 0,
  67.                                            cond_maps[i].bm, condbuf);
  68.              }
  69.          }
  70.  }
  71.  

status_hilite_linestr_gather

  1.  STATIC_OVL void
  2.  status_hilite_linestr_gather()
  3.  {
  4.      int i;
  5.      struct hilite_s *hl;
  6.  
  7.      status_hilite_linestr_done();
  8.  
  9.      for (i = 0; i < MAXBLSTATS; i++) {
  10.          hl = blstats[0][i].thresholds;
  11.          while (hl) {
  12.              status_hilite_linestr_add(i, hl, 0UL, status_hilite2str(hl));
  13.              hl = hl->next;
  14.          }
  15.      }
  16.  
  17.      status_hilite_linestr_gather_conditions();
  18.  }
  19.  
  20.  

status_hilite2str

  1.  char *
  2.  status_hilite2str(hl)
  3.  struct hilite_s *hl;
  4.  {
  5.      static char buf[BUFSZ];
  6.      int clr = 0, attr = 0;
  7.      char behavebuf[BUFSZ];
  8.      char clrbuf[BUFSZ];
  9.      char attrbuf[BUFSZ];
  10.      char *tmpattr;
  11.  
  12.      if (!hl)
  13.          return (char *) 0;
  14.  
  15.      behavebuf[0] = '\0';
  16.      clrbuf[0] = '\0';
  17.  
  18.      switch (hl->behavior) {
  19.      case BL_TH_VAL_PERCENTAGE:
  20.          if (hl->rel == LT_VALUE)
  21.              Sprintf(behavebuf, "<%i%%", hl->value.a_int);
  22.          else if (hl->rel == GT_VALUE)
  23.              Sprintf(behavebuf, ">%i%%", hl->value.a_int);
  24.          else if (hl->rel == EQ_VALUE)
  25.              Sprintf(behavebuf, "%i%%", hl->value.a_int);
  26.          else
  27.              impossible("hl->behavior=percentage, rel error");
  28.          break;
  29.      case BL_TH_UPDOWN:
  30.          if (hl->rel == LT_VALUE)
  31.              Sprintf(behavebuf, "down");
  32.          else if (hl->rel == GT_VALUE)
  33.              Sprintf(behavebuf, "up");
  34.          else if (hl->rel == EQ_VALUE)
  35.              Sprintf(behavebuf, "changed");
  36.          else
  37.              impossible("hl->behavior=updown, rel error");
  38.          break;
  39.      case BL_TH_VAL_ABSOLUTE:
  40.          if (hl->rel == LT_VALUE)
  41.              Sprintf(behavebuf, "<%i", hl->value.a_int);
  42.          else if (hl->rel == GT_VALUE)
  43.              Sprintf(behavebuf, ">%i", hl->value.a_int);
  44.          else if (hl->rel == EQ_VALUE)
  45.              Sprintf(behavebuf, "%i", hl->value.a_int);
  46.          else
  47.              impossible("hl->behavior=absolute, rel error");
  48.          break;
  49.      case BL_TH_TEXTMATCH:
  50.          if (hl->rel == TXT_VALUE && hl->textmatch[0])
  51.              Sprintf(behavebuf, "%s", hl->textmatch);
  52.          else
  53.              impossible("hl->behavior=textmatch, rel or textmatch error");
  54.          break;
  55.      case BL_TH_CONDITION:
  56.          if (hl->rel == EQ_VALUE)
  57.              Sprintf(behavebuf, "%s", conditionbitmask2str(hl->value.a_ulong));
  58.          else
  59.              impossible("hl->behavior=condition, rel error");
  60.          break;
  61.      case BL_TH_ALWAYS_HILITE:
  62.          Sprintf(behavebuf, "always");
  63.          break;
  64.      case BL_TH_NONE:
  65.          break;
  66.      default:
  67.          break;
  68.      }
  69.  
  70.      split_clridx(hl->coloridx, &clr, &attr);
  71.      if (clr != NO_COLOR)
  72.          (void) stripchars(clrbuf, " ", clr2colorname(clr));
  73.      if (attr != HL_UNDEF) {
  74.          tmpattr = hlattr2attrname(attr, attrbuf, BUFSZ);
  75.          if (tmpattr)
  76.              Sprintf(eos(clrbuf), "%s%s",
  77.                      (clr != NO_COLOR) ? "&" : "",
  78.                      tmpattr);
  79.      }
  80.      Sprintf(buf, "%s/%s/%s", initblstats[hl->fld].fldname, behavebuf, clrbuf);
  81.  
  82.      return buf;
  83.  }
  84.  

status_hilite_menu_choose_field

  1.  int
  2.  status_hilite_menu_choose_field()
  3.  {
  4.      winid tmpwin;
  5.      int i, res, fld = BL_FLUSH;
  6.      anything any;
  7.      menu_item *picks = (menu_item *) 0;
  8.  
  9.      tmpwin = create_nhwindow(NHW_MENU);
  10.      start_menu(tmpwin);
  11.  
  12.      for (i = 0; i < MAXBLSTATS; i++) {
  13.          any = zeroany;
  14.          any.a_int = (i+1);
  15.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  16.                   initblstats[i].fldname, MENU_UNSELECTED);
  17.      }
  18.  
  19.      end_menu(tmpwin, "Select a hilite field:");
  20.  
  21.      res = select_menu(tmpwin, PICK_ONE, &picks);
  22.      destroy_nhwindow(tmpwin);
  23.      if (res > 0) {
  24.          fld = picks->item.a_int - 1;
  25.          free((genericptr_t) picks);
  26.      }
  27.      return fld;
  28.  }
  29.  

status_hilite_menu_choose_behavior

  1.  int
  2.  status_hilite_menu_choose_behavior(fld)
  3.  int fld;
  4.  {
  5.      winid tmpwin;
  6.      int res = 0, beh = BL_TH_NONE-1;
  7.      anything any;
  8.      menu_item *picks = (menu_item *) 0;
  9.      char buf[BUFSZ];
  10.      int at;
  11.      int onlybeh = BL_TH_NONE, nopts = 0;
  12.  
  13.      if (fld <= BL_FLUSH || fld >= MAXBLSTATS)
  14.          return BL_TH_NONE;
  15.  
  16.      at = initblstats[fld].anytype;
  17.  
  18.      tmpwin = create_nhwindow(NHW_MENU);
  19.      start_menu(tmpwin);
  20.  
  21.      if (fld != BL_CONDITION) {
  22.          any = zeroany;
  23.          any.a_int = onlybeh = BL_TH_ALWAYS_HILITE;
  24.          Sprintf(buf, "Always highlight %s", initblstats[fld].fldname);
  25.          add_menu(tmpwin, NO_GLYPH, &any, 'a', 0, ATR_NONE,
  26.                   buf, MENU_UNSELECTED);
  27.          nopts++;
  28.      }
  29.  
  30.      if (fld == BL_CONDITION) {
  31.          any = zeroany;
  32.          any.a_int = onlybeh = BL_TH_CONDITION;
  33.          add_menu(tmpwin, NO_GLYPH, &any, 'b', 0, ATR_NONE,
  34.                   "Bitmask of conditions", MENU_UNSELECTED);
  35.          nopts++;
  36.      }
  37.  
  38.      if (fld != BL_CONDITION) {
  39.          any = zeroany;
  40.          any.a_int = onlybeh = BL_TH_UPDOWN;
  41.          Sprintf(buf, "%s value changes", initblstats[fld].fldname);
  42.          add_menu(tmpwin, NO_GLYPH, &any, 'c', 0, ATR_NONE,
  43.                   buf, MENU_UNSELECTED);
  44.          nopts++;
  45.      }
  46.  
  47.      if (fld != BL_CAP && fld != BL_HUNGER && (at == ANY_INT || at == ANY_LONG || at == ANY_UINT)) {
  48.          any = zeroany;
  49.          any.a_int = onlybeh = BL_TH_VAL_ABSOLUTE;
  50.          add_menu(tmpwin, NO_GLYPH, &any, 'n', 0, ATR_NONE,
  51.                   "Number threshold", MENU_UNSELECTED);
  52.          nopts++;
  53.      }
  54.  
  55.      if (initblstats[fld].idxmax > BL_FLUSH) {
  56.          any = zeroany;
  57.          any.a_int = onlybeh = BL_TH_VAL_PERCENTAGE;
  58.          add_menu(tmpwin, NO_GLYPH, &any, 'p', 0, ATR_NONE,
  59.                   "Percentage threshold", MENU_UNSELECTED);
  60.          nopts++;
  61.      }
  62.  
  63.      if (initblstats[fld].anytype == ANY_STR || fld == BL_CAP || fld == BL_HUNGER) {
  64.          any = zeroany;
  65.          any.a_int = onlybeh = BL_TH_TEXTMATCH;
  66.          Sprintf(buf, "%s text match", initblstats[fld].fldname);
  67.          add_menu(tmpwin, NO_GLYPH, &any, 't', 0, ATR_NONE,
  68.                   buf, MENU_UNSELECTED);
  69.          nopts++;
  70.      }
  71.  
  72.      Sprintf(buf, "Select %s field hilite behavior:", initblstats[fld].fldname);
  73.      end_menu(tmpwin, buf);
  74.  
  75.      if (nopts > 1) {
  76.          res = select_menu(tmpwin, PICK_ONE, &picks);
  77.          if (res == 0) /* none chosen*/
  78.              beh = BL_TH_NONE;
  79.          else if (res == -1) /* menu cancelled */
  80.              beh = (BL_TH_NONE - 1);
  81.      } else if (onlybeh != BL_TH_NONE)
  82.          beh = onlybeh;
  83.      destroy_nhwindow(tmpwin);
  84.      if (res > 0) {
  85.          beh = picks->item.a_int;
  86.          free((genericptr_t) picks);
  87.      }
  88.      return beh;
  89.  }
  90.  

status_hilite_menu_choose_updownboth

  1.  int
  2.  status_hilite_menu_choose_updownboth(fld, str)
  3.  int fld;
  4.  const char *str;
  5.  {
  6.      int res, ret = -2;
  7.      winid tmpwin;
  8.      char buf[BUFSZ];
  9.      anything any;
  10.      menu_item *picks = (menu_item *) 0;
  11.  
  12.      tmpwin = create_nhwindow(NHW_MENU);
  13.      start_menu(tmpwin);
  14.  
  15.      if (str)
  16.          Sprintf(buf, "%s or less", str);
  17.      else
  18.          Sprintf(buf, "Value goes down");
  19.      any = zeroany;
  20.      any.a_int = 10 + LT_VALUE;
  21.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  22.               buf, MENU_UNSELECTED);
  23.  
  24.      if (str)
  25.          Sprintf(buf, "Exactly %s", str);
  26.      else
  27.          Sprintf(buf, "Value changes");
  28.      any = zeroany;
  29.      any.a_int = 10 + EQ_VALUE;
  30.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  31.               buf, MENU_UNSELECTED);
  32.  
  33.      if (str)
  34.          Sprintf(buf, "%s or more", str);
  35.      else
  36.          Sprintf(buf, "Value goes up");
  37.      any = zeroany;
  38.      any.a_int = 10 + GT_VALUE;
  39.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  40.               buf, MENU_UNSELECTED);
  41.  
  42.      Sprintf(buf, "Select field %s value:", initblstats[fld].fldname);
  43.      end_menu(tmpwin, buf);
  44.  
  45.      res = select_menu(tmpwin, PICK_ONE, &picks);
  46.      destroy_nhwindow(tmpwin);
  47.      if (res > 0) {
  48.          ret = picks->item.a_int - 10;
  49.          free((genericptr_t) picks);
  50.      }
  51.  
  52.      return ret;
  53.  }
  54.  

status_hilite_menu_add

  1.  STATIC_OVL boolean
  2.  status_hilite_menu_add(origfld)
  3.  int origfld;
  4.  {
  5.      int fld;
  6.      int behavior;
  7.      int lt_gt_eq = 0;
  8.      int clr = NO_COLOR, atr = HL_UNDEF;
  9.      struct hilite_s hilite;
  10.      unsigned long cond = 0UL;
  11.      char colorqry[BUFSZ];
  12.      char attrqry[BUFSZ];
  13.  
  14.  choose_field:
  15.      fld = origfld;
  16.      if (fld == BL_FLUSH) {
  17.          fld = status_hilite_menu_choose_field();
  18.          if (fld == BL_FLUSH)
  19.              return FALSE;
  20.      }
  21.  
  22.      if (fld == BL_FLUSH)
  23.          return FALSE;
  24.  
  25.      colorqry[0] = '\0';
  26.      attrqry[0] = '\0';
  27.  
  28.      memset((genericptr_t) &hilite, 0, sizeof(struct hilite_s));
  29.      hilite.set = FALSE; /* mark it "unset" */
  30.      hilite.fld = fld;
  31.  
  32.  choose_behavior:
  33.  
  34.      behavior = status_hilite_menu_choose_behavior(fld);
  35.  
  36.      if (behavior == (BL_TH_NONE-1)) {
  37.          return FALSE;
  38.      } else if (behavior == BL_TH_NONE) {
  39.          if (origfld == BL_FLUSH)
  40.              goto choose_field;
  41.          else
  42.              return FALSE;
  43.      }
  44.  
  45.      hilite.behavior = behavior;
  46.  
  47.  choose_value:
  48.  
  49.      if (behavior == BL_TH_VAL_PERCENTAGE
  50.          || behavior == BL_TH_VAL_ABSOLUTE) {
  51.          char inbuf[BUFSZ] = DUMMY, buf[BUFSZ];
  52.          int val;
  53.          boolean skipltgt = FALSE;
  54.          boolean gotnum = FALSE;
  55.          char *inp = inbuf;
  56.          char *numstart = inbuf;
  57.  
  58.          inbuf[0] = '\0';
  59.          Sprintf(buf, "Enter %svalue for %s threshold:",
  60.                  (behavior == BL_TH_VAL_PERCENTAGE) ? "percentage " : "",
  61.                  initblstats[fld].fldname);
  62.          getlin(buf, inbuf);
  63.          if (inbuf[0] == '\0' || inbuf[0] == '\033')
  64.              goto choose_behavior;
  65.  
  66.          inp = trimspaces(inbuf);
  67.          if (!*inp)
  68.              goto choose_behavior;
  69.  
  70.          /* allow user to enter "<50%" or ">50" or just "50" */
  71.          if (*inp == '>' || *inp == '<' || *inp == '=') {
  72.              lt_gt_eq = (*inp == '>') ? GT_VALUE
  73.                  : (*inp == '<') ? LT_VALUE : EQ_VALUE;
  74.              skipltgt = TRUE;
  75.              *inp = ' ';
  76.              inp++;
  77.              numstart++;
  78.          }
  79.          while (digit(*inp)) {
  80.              inp++;
  81.              gotnum = TRUE;
  82.          }
  83.          if (*inp == '%') {
  84.              behavior = BL_TH_VAL_PERCENTAGE;
  85.              *inp = '\0';
  86.          } else if (!*inp) {
  87.              behavior = BL_TH_VAL_ABSOLUTE;
  88.          } else {
  89.              /* some random characters */
  90.              pline("\"%s\" is not a recognized number.", inp);
  91.              goto choose_value;
  92.          }
  93.          if (!gotnum) {
  94.              pline("Is that an invisible number?");
  95.              goto choose_value;
  96.          }
  97.  
  98.          val = atoi(numstart);
  99.          if (behavior == BL_TH_VAL_PERCENTAGE) {
  100.              if (initblstats[fld].idxmax == -1) {
  101.                  pline("Field '%s' does not support percentage values.",
  102.                        initblstats[fld].fldname);
  103.                  behavior = BL_TH_VAL_ABSOLUTE;
  104.                  goto choose_value;
  105.              }
  106.              if (val < 0 || val > 100) {
  107.                  pline("Not a valid percent value.");
  108.                  goto choose_value;
  109.              }
  110.          }
  111.  
  112.          if (!skipltgt) {
  113.              lt_gt_eq = status_hilite_menu_choose_updownboth(fld, inbuf);
  114.              if (lt_gt_eq == -2)
  115.                  goto choose_value;
  116.          }
  117.  
  118.          Sprintf(colorqry, "Choose a color for when %s is %s%s:",
  119.                  initblstats[fld].fldname,
  120.                  numstart,
  121.                  (lt_gt_eq == EQ_VALUE) ? ""
  122.                  : (lt_gt_eq == LT_VALUE) ? " or less"
  123.                  : " or more");
  124.  
  125.          Sprintf(attrqry, "Choose attribute for when %s is %s%s:",
  126.                  initblstats[fld].fldname,
  127.                  inbuf,
  128.                  (lt_gt_eq == EQ_VALUE) ? ""
  129.                  : (lt_gt_eq == LT_VALUE) ? " or less"
  130.                  : " or more");
  131.  
  132.          hilite.rel = lt_gt_eq;
  133.          hilite.value.a_int = val;
  134.      } else if (behavior == BL_TH_UPDOWN) {
  135.          lt_gt_eq = status_hilite_menu_choose_updownboth(fld, (char *)0);
  136.          if (lt_gt_eq == -2)
  137.              goto choose_behavior;
  138.          Sprintf(colorqry, "Choose a color for when %s %s:",
  139.                  initblstats[fld].fldname,
  140.                  (lt_gt_eq == EQ_VALUE) ? "changes"
  141.                  : (lt_gt_eq == LT_VALUE) ? "decreases"
  142.                  : "increases");
  143.          Sprintf(attrqry, "Choose attribute for when %s %s:",
  144.                  initblstats[fld].fldname,
  145.                  (lt_gt_eq == EQ_VALUE) ? "changes"
  146.                  : (lt_gt_eq == LT_VALUE) ? "decreases"
  147.                  : "increases");
  148.          hilite.rel = lt_gt_eq;
  149.      } else if (behavior == BL_TH_CONDITION) {
  150.          cond = query_conditions();
  151.          if (!cond) {
  152.              if (origfld == BL_FLUSH)
  153.                  goto choose_field;
  154.              else
  155.                  return FALSE;
  156.          }
  157.          Sprintf(colorqry, "Choose a color for conditions %s:",
  158.                  conditionbitmask2str(cond));
  159.          Sprintf(attrqry, "Choose attribute for conditions %s:",
  160.                  conditionbitmask2str(cond));
  161.      } else if (behavior == BL_TH_TEXTMATCH) {
  162.          char qry_buf[BUFSZ];
  163.          Sprintf(qry_buf, "%s %s text value to match:",
  164.                  (fld == BL_CAP
  165.                   || fld == BL_ALIGN
  166.                   || fld == BL_HUNGER
  167.                   || fld == BL_TITLE) ? "Choose" : "Enter",
  168.                  initblstats[fld].fldname);
  169.          if (fld == BL_CAP) {
  170.              int rv = query_arrayvalue(qry_buf,
  171.                                        enc_stat,
  172.                                        SLT_ENCUMBER, OVERLOADED+1);
  173.              if (rv < SLT_ENCUMBER)
  174.                  goto choose_behavior;
  175.  
  176.              hilite.rel = TXT_VALUE;
  177.              Strcpy(hilite.textmatch, enc_stat[rv]);
  178.          } else if (fld == BL_ALIGN) {
  179.              const char *aligntxt[] = {"chaotic", "neutral", "lawful"};
  180.              int rv = query_arrayvalue(qry_buf,
  181.                                        aligntxt, 0, 3);
  182.              if (rv < 0)
  183.                  goto choose_behavior;
  184.  
  185.              hilite.rel = TXT_VALUE;
  186.              Strcpy(hilite.textmatch, aligntxt[rv]);
  187.          } else if (fld == BL_HUNGER) {
  188.              const char *hutxt[] = {"Satiated", (char *)0, "Hungry", "Weak",
  189.                                     "Fainting", "Fainted", "Starved"};
  190.              int rv = query_arrayvalue(qry_buf,
  191.                                        hutxt,
  192.                                        SATIATED, STARVED+1);
  193.              if (rv < SATIATED)
  194.                  goto choose_behavior;
  195.  
  196.              hilite.rel = TXT_VALUE;
  197.              Strcpy(hilite.textmatch, hutxt[rv]);
  198.          } else if (fld == BL_TITLE) {
  199.              const char *rolelist[9];
  200.              int i, rv;
  201.  
  202.              for (i = 0; i < 9; i++)
  203.                  rolelist[i] = (flags.female && urole.rank[i].f)
  204.                      ? urole.rank[i].f : urole.rank[i].m;
  205.  
  206.              rv = query_arrayvalue(qry_buf, rolelist, 0, 9);
  207.              if (rv < 0)
  208.                  goto choose_behavior;
  209.  
  210.              hilite.rel = TXT_VALUE;
  211.              Strcpy(hilite.textmatch, rolelist[rv]);
  212.          } else {
  213.              char inbuf[BUFSZ] = DUMMY;
  214.  
  215.              inbuf[0] = '\0';
  216.              getlin(qry_buf, inbuf);
  217.              if (inbuf[0] == '\0' || inbuf[0] == '\033')
  218.                  goto choose_behavior;
  219.  
  220.              hilite.rel = TXT_VALUE;
  221.              if (strlen(inbuf) < QBUFSZ-1)
  222.                  Strcpy(hilite.textmatch, inbuf);
  223.              else
  224.                  return FALSE;
  225.          }
  226.          Sprintf(colorqry, "Choose a color for when %s is '%s':",
  227.                  initblstats[fld].fldname, hilite.textmatch);
  228.          Sprintf(colorqry, "Choose attribute for when %s is '%s':",
  229.                  initblstats[fld].fldname, hilite.textmatch);
  230.      } else if (behavior == BL_TH_ALWAYS_HILITE) {
  231.          Sprintf(colorqry, "Choose a color to always hilite %s:",
  232.                  initblstats[fld].fldname);
  233.          Sprintf(attrqry, "Choose attribute to always hilite %s:",
  234.                  initblstats[fld].fldname);
  235.      }
  236.  
  237.  choose_color:
  238.  
  239.      clr = query_color(colorqry);
  240.      if (clr == -1) {
  241.          if (behavior != BL_TH_ALWAYS_HILITE)
  242.              goto choose_value;
  243.          else
  244.              goto choose_behavior;
  245.      }
  246.  
  247.      atr = query_attr(attrqry); /* FIXME: pick multiple attrs */
  248.      if (atr == -1)
  249.          goto choose_color;
  250.      if (atr == ATR_DIM)
  251.          atr = HL_DIM;
  252.      else if (atr == ATR_BLINK)
  253.          atr = HL_BLINK;
  254.      else if (atr == ATR_ULINE)
  255.          atr = HL_ULINE;
  256.      else if (atr == ATR_INVERSE)
  257.          atr = HL_INVERSE;
  258.      else if (atr == ATR_BOLD)
  259.          atr = HL_BOLD;
  260.      else if (atr == ATR_NONE)
  261.          atr = HL_NONE;
  262.      else
  263.          atr = HL_UNDEF;
  264.  
  265.      if (clr == -1)
  266.          clr = NO_COLOR;
  267.  
  268.      if (behavior == BL_TH_CONDITION) {
  269.          char clrbuf[BUFSZ];
  270.          char attrbuf[BUFSZ];
  271.          char *tmpattr;
  272.          if (atr == HL_DIM)
  273.              cond_hilites[HL_ATTCLR_DIM] |= cond;
  274.          else if (atr == HL_BLINK)
  275.              cond_hilites[HL_ATTCLR_BLINK] |= cond;
  276.          else if (atr == HL_ULINE)
  277.              cond_hilites[HL_ATTCLR_ULINE] |= cond;
  278.          else if (atr == HL_INVERSE)
  279.              cond_hilites[HL_ATTCLR_INVERSE] |= cond;
  280.          else if (atr == HL_BOLD)
  281.              cond_hilites[HL_ATTCLR_BOLD] |= cond;
  282.          else if (atr == HL_NONE) {
  283.              cond_hilites[HL_ATTCLR_DIM]     = 0UL;
  284.              cond_hilites[HL_ATTCLR_BLINK]   = 0UL;
  285.              cond_hilites[HL_ATTCLR_ULINE]   = 0UL;
  286.              cond_hilites[HL_ATTCLR_INVERSE] = 0UL;
  287.              cond_hilites[HL_ATTCLR_BOLD]    = 0UL;
  288.          }
  289.          cond_hilites[clr] |= cond;
  290.          (void) stripchars(clrbuf, " ", clr2colorname(clr));
  291.          tmpattr = hlattr2attrname(atr, attrbuf, BUFSZ);
  292.          if (tmpattr)
  293.              Sprintf(eos(clrbuf), "&%s", tmpattr);
  294.          pline("Added hilite condition/%s/%s",
  295.                conditionbitmask2str(cond), clrbuf);
  296.      } else {
  297.          hilite.coloridx = clr | (atr << 8);
  298.          hilite.anytype = initblstats[fld].anytype;
  299.  
  300.          status_hilite_add_threshold(fld, &hilite);
  301.          pline("Added hilite %s", status_hilite2str(&hilite));
  302.      }
  303.      reset_status_hilites();
  304.      return TRUE;
  305.  }
  306.  

status_hilite_remove

  1.  boolean
  2.  status_hilite_remove(id)
  3.  int id;
  4.  {
  5.      struct _status_hilite_line_str *hlstr = status_hilite_str;
  6.  
  7.      while (hlstr && hlstr->id != id) {
  8.          hlstr = hlstr->next;
  9.      }
  10.  
  11.      if (!hlstr)
  12.          return FALSE;
  13.  
  14.      if (hlstr->fld == BL_CONDITION) {
  15.          int i;
  16.  
  17.          for (i = 0; i < CLR_MAX; i++)
  18.              cond_hilites[i] &= ~hlstr->mask;
  19.          cond_hilites[HL_ATTCLR_DIM] &= ~hlstr->mask;
  20.          cond_hilites[HL_ATTCLR_BOLD] &= ~hlstr->mask;
  21.          cond_hilites[HL_ATTCLR_BLINK] &= ~hlstr->mask;
  22.          cond_hilites[HL_ATTCLR_ULINE] &= ~hlstr->mask;
  23.          cond_hilites[HL_ATTCLR_INVERSE] &= ~hlstr->mask;
  24.          return TRUE;
  25.      } else {
  26.          int fld = hlstr->fld;
  27.          struct hilite_s *hl = blstats[0][fld].thresholds;
  28.          struct hilite_s *hlprev = (struct hilite_s *) 0;
  29.  
  30.          if (hl) {
  31.              while (hl) {
  32.                  if (hlstr->hl == hl) {
  33.                      if (hlprev)
  34.                          hlprev->next = hl->next;
  35.                      else {
  36.                          blstats[0][fld].thresholds = hl->next;
  37.                          blstats[1][fld].thresholds =
  38.                              blstats[0][fld].thresholds;
  39.                      }
  40.                      free(hl);
  41.                      return TRUE;
  42.                  }
  43.                  hlprev = hl;
  44.                  hl = hl->next;
  45.              }
  46.          }
  47.      }
  48.      return FALSE;
  49.  }
  50.  

status_hilite_menu_fld

  1.  boolean
  2.  status_hilite_menu_fld(fld)
  3.  int fld;
  4.  {
  5.      winid tmpwin;
  6.      int i, res;
  7.      menu_item *picks = (menu_item *) 0;
  8.      anything any;
  9.      int count = status_hilite_linestr_countfield(fld);
  10.      struct _status_hilite_line_str *hlstr;
  11.      char buf[BUFSZ];
  12.      boolean acted = FALSE;
  13.  
  14.      if (!count) {
  15.          if (status_hilite_menu_add(fld)) {
  16.              status_hilite_linestr_done();
  17.              status_hilite_linestr_gather();
  18.              count = status_hilite_linestr_countfield(fld);
  19.          } else
  20.              return FALSE;
  21.      }
  22.  
  23.      tmpwin = create_nhwindow(NHW_MENU);
  24.      start_menu(tmpwin);
  25.  
  26.      if (count) {
  27.          hlstr = status_hilite_str;
  28.          while (hlstr) {
  29.              if (hlstr->fld == fld) {
  30.                  any = zeroany;
  31.                  any.a_int = hlstr->id;
  32.                  add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  33.                           hlstr->str, MENU_UNSELECTED);
  34.              }
  35.              hlstr = hlstr->next;
  36.          }
  37.      } else {
  38.          any = zeroany;
  39.          Sprintf(buf, "No current hilites for %s", initblstats[fld].fldname);
  40.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
  41.      }
  42.  
  43.      /* separator line */
  44.      any = zeroany;
  45.      add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
  46.  
  47.      if (count) {
  48.          any = zeroany;
  49.          any.a_int = -1;
  50.          add_menu(tmpwin, NO_GLYPH, &any, 'X', 0, ATR_NONE,
  51.                   "Remove selected hilites", MENU_UNSELECTED);
  52.      }
  53.  
  54.      any = zeroany;
  55.      any.a_int = -2;
  56.      add_menu(tmpwin, NO_GLYPH, &any, 'Z', 0, ATR_NONE,
  57.               "Add a new hilite", MENU_UNSELECTED);
  58.  
  59.  
  60.      Sprintf(buf, "Current %s hilites:", initblstats[fld].fldname);
  61.      end_menu(tmpwin, buf);
  62.  
  63.      if ((res = select_menu(tmpwin, PICK_ANY, &picks)) > 0) {
  64.          int mode = 0;
  65.          for (i = 0; i < res; i++) {
  66.              int idx = picks[i].item.a_int;
  67.              if (idx == -1) {
  68.                  /* delete selected hilites */
  69.                  if (mode)
  70.                      goto shlmenu_free;
  71.                  mode = -1;
  72.                  break;
  73.              } else if (idx == -2) {
  74.                  /* create a new hilite */
  75.                  if (mode)
  76.                      goto shlmenu_free;
  77.                  mode = -2;
  78.                  break;
  79.              }
  80.          }
  81.  
  82.          if (mode == -1) {
  83.              /* delete selected hilites */
  84.              for (i = 0; i < res; i++) {
  85.                  int idx = picks[i].item.a_int;
  86.                  if (idx > 0)
  87.                      (void) status_hilite_remove(idx);
  88.              }
  89.              reset_status_hilites();
  90.              acted = TRUE;
  91.          } else if (mode == -2) {
  92.              /* create a new hilite */
  93.              if (status_hilite_menu_add(fld))
  94.                  acted = TRUE;
  95.          }
  96.  
  97.          free((genericptr_t) picks);
  98.      }
  99.  
  100.  shlmenu_free:
  101.  
  102.      picks = (menu_item *) 0;
  103.      destroy_nhwindow(tmpwin);
  104.      return acted;
  105.  }
  106.  

status_hilites_viewall

  1.  void
  2.  status_hilites_viewall()
  3.  {
  4.      winid datawin;
  5.      struct _status_hilite_line_str *hlstr = status_hilite_str;
  6.      char buf[BUFSZ];
  7.  
  8.      datawin = create_nhwindow(NHW_TEXT);
  9.  
  10.      while (hlstr) {
  11.          Sprintf(buf, "OPTIONS=hilite_status: %.*s",
  12.                  (int)(BUFSZ - sizeof "OPTIONS=hilite_status: " - 1),
  13.                  hlstr->str);
  14.          putstr(datawin, 0, buf);
  15.          hlstr = hlstr->next;
  16.      }
  17.  
  18.      display_nhwindow(datawin, FALSE);
  19.      destroy_nhwindow(datawin);
  20.  }
  21.  

status_hilite_menu

  1.  boolean
  2.  status_hilite_menu()
  3.  {
  4.      winid tmpwin;
  5.      int i, res;
  6.      menu_item *picks = (menu_item *) 0;
  7.      anything any;
  8.      boolean redo;
  9.      int countall;
  10.  
  11.  shlmenu_redo:
  12.      redo = FALSE;
  13.  
  14.      tmpwin = create_nhwindow(NHW_MENU);
  15.      start_menu(tmpwin);
  16.  
  17.      status_hilite_linestr_gather();
  18.  
  19.      countall = status_hilite_linestr_countfield(BL_FLUSH);
  20.  
  21.      if (countall) {
  22.          any = zeroany;
  23.          any.a_int = -1;
  24.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  25.                   "View all hilites in config format", MENU_UNSELECTED);
  26.  
  27.          any = zeroany;
  28.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
  29.      }
  30.  
  31.      for (i = 0; i < MAXBLSTATS; i++) {
  32.          int count = status_hilite_linestr_countfield(i);
  33.          char buf[BUFSZ];
  34.  
  35.          any = zeroany;
  36.          any.a_int = (i+1);
  37.          if (count)
  38.              Sprintf(buf, "%-18s (%i defined)",
  39.                      initblstats[i].fldname, count);
  40.          else
  41.              Sprintf(buf, "%-18s", initblstats[i].fldname);
  42.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
  43.                   buf, MENU_UNSELECTED);
  44.      }
  45.  
  46.  
  47.      end_menu(tmpwin, "Status hilites:");
  48.      if ((res = select_menu(tmpwin, PICK_ONE, &picks)) > 0) {
  49.          i = picks->item.a_int - 1;
  50.          if (i < 0)
  51.              status_hilites_viewall();
  52.          else
  53.              (void) status_hilite_menu_fld(i);
  54.          free((genericptr_t) picks);
  55.          redo = TRUE;
  56.      }
  57.  
  58.      picks = (menu_item *) 0;
  59.      destroy_nhwindow(tmpwin);
  60.      status_hilite_linestr_done();
  61.  
  62.      if (redo)
  63.          goto shlmenu_redo;
  64.  
  65.      return TRUE;
  66.  }
  67.  
  68.  #endif /* STATUS_HILITES */
  69.  
  70.  /*botl.c*/