1 /* NetHack 3.6 winstat.c $NHDT-Date: 1543447325 2018/11/28 23:22:05 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.20 $ */
2 /* Copyright (c) Dean Luick, 1992 */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* JNetHack Copyright */
6 /* (c) Issei Numata 1994-1999 */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020 */
8 /* JNetHack may be freely redistributed. See license for details. */
11 * Status window routines. This file supports both the "traditional"
12 * tty status display and a "fancy" status display. A tty status is
13 * made if a popup window is requested, otherewise a fancy status is
14 * made. This code assumes that only one fancy status will ever be made.
15 * Currently, only one status window (of any type) is _ever_ made.
19 #define PRESERVE_NO_SYSV /* X11 include files may define SYSV */
22 #include <X11/Intrinsic.h>
23 #include <X11/IntrinsicP.h>
24 #include <X11/StringDefs.h>
25 #include <X11/Shell.h>
26 #include <X11/Xaw/AsciiText.h>
27 #include <X11/Xaw/Cardinals.h>
28 #include <X11/Xaw/Form.h>
29 #include <X11/Xaw/Paned.h>
30 #include <X11/Xaw/Label.h>
31 #include <X11/Xaw/Viewport.h>
32 #include <X11/Xatom.h>
34 #ifdef PRESERVE_NO_SYSV
38 #undef PRESERVE_NO_SYSV
46 * Fancy status form entry storage indices.
70 /* status conditions grouped by columns; tty orders these differently */
91 static void FDECL(update_fancy_status, (struct xwindow *));
92 static void FDECL(update_fancy_status_field, (int));
93 static Widget FDECL(create_fancy_status, (Widget, Widget));
94 static void FDECL(destroy_fancy_status, (struct xwindow *));
95 static void FDECL(create_status_window_fancy, (struct xwindow *, BOOLEAN_P, Widget));
96 static void FDECL(create_status_window_tty, (struct xwindow *, BOOLEAN_P, Widget));
97 static void FDECL(destroy_status_window_fancy, (struct xwindow *));
98 static void FDECL(destroy_status_window_tty, (struct xwindow *));
99 static void FDECL(adjust_status_fancy, (struct xwindow *, const char *));
100 static void FDECL(adjust_status_tty, (struct xwindow *, const char *));
102 extern const char *status_fieldfmt[MAXBLSTATS];
103 extern char *status_vals[MAXBLSTATS];
104 extern boolean status_activefields[MAXBLSTATS];
105 static long X11_condition_bits;
106 static int X11_status_colors[MAXBLSTATS];
107 static int hpbar_percent, hpbar_color;
109 #define X11_NUM_STATUS_LINES 2
110 #define X11_NUM_STATUS_FIELD 15
112 static enum statusfields X11_fieldorder[X11_NUM_STATUS_LINES][X11_NUM_STATUS_FIELD] = {
113 { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN,
114 BL_SCORE, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH,
116 { BL_LEVELDESC, BL_GOLD, BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX,
117 BL_AC, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_HUNGER,
118 BL_CAP, BL_CONDITION, BL_FLUSH }
121 static Widget X11_status_widget;
122 static Widget X11_status_labels[MAXBLSTATS];
123 static Widget X11_cond_labels[32]; /* Ugh */
125 struct xwindow *xw_status_win;
126 static Pixel X11_status_widget_fg, X11_status_widget_bg;
130 condcolor(bm, bmarray)
132 unsigned long *bmarray;
137 for (i = 0; i < CLR_MAX; ++i) {
138 if (bmarray[i] && (bm & bmarray[i]))
145 condattr(bm, bmarray)
147 unsigned long *bmarray;
153 for (i = HL_ATTCLR_DIM; i < BL_ATTCLR_MAX; ++i) {
154 if (bmarray[i] && (bm & bmarray[i])) {
159 case HL_ATTCLR_BLINK:
162 case HL_ATTCLR_ULINE:
165 case HL_ATTCLR_INVERSE:
181 #ifdef STATUS_HILITES
184 for (i = 0; i < MAXBLSTATS; ++i)
185 X11_status_colors[i] = NO_COLOR; /* no color */
186 X11_condition_bits = 0L;
187 hpbar_percent = 0, hpbar_color = NO_COLOR;
188 #endif /* STATUS_HILITES */
189 /* let genl_status_init do most of the initialization */
200 X11_status_enablefield(fieldidx, nm, fmt, enable)
206 genl_status_enablefield(fieldidx, nm, fmt, enable);
215 for (i = 0; i < 32; i++)
222 MaybeDisplayCond(bm, colormasks, text)
224 unsigned long *colormasks;
227 int idx = cond_bm2idx(bm);
231 Pixel fg = X11_status_widget_fg, bg = X11_status_widget_bg;
234 Dimension lbl_border_wid;
235 Dimension lbl_iwidth;
240 label = X11_cond_labels[idx];
241 if ((X11_condition_bits & bm) != 0) {
242 int attrmask, coloridx;
248 coloridx = condcolor(bm, colormasks);
252 attrmask = condattr(bm, colormasks);
254 XtSetArg(args[num_args], nhStr(XtNfont), &font); num_args++;
255 XtSetArg(args[num_args], nhStr(XtNx), &lbl_x); num_args++;
256 XtSetArg(args[num_args], nhStr(XtNy), &lbl_y); num_args++;
257 XtSetArg(args[num_args], nhStr(XtNwidth), &lbl_wid); num_args++;
258 XtSetArg(args[num_args], nhStr(XtNheight), &lbl_hei); num_args++;
259 XtSetArg(args[num_args], nhStr(XtNinternalWidth), &lbl_iwidth); num_args++;
260 XtSetArg(args[num_args], nhStr(XtNborderWidth), &lbl_border_wid); num_args++;
261 XtGetValues(label, args, num_args);
264 lbl_wid = lbl_iwidth + font->max_bounds.width * strlen(text);
269 XtSetArg(args[num_args], nhStr(XtNlabel), (text && *text) ? text : ""); num_args++;
270 XtSetArg(args[num_args], nhStr(XtNwidth), lbl_wid); num_args++;
272 fg = (coloridx != NO_COLOR) ? get_nhcolor(xw_status_win, coloridx).pixel
273 : X11_status_widget_fg;
274 if (attrmask & HL_INVERSE) {
280 if (attrmask & HL_BOLD) {
281 load_boldfont(xw_status_win, label);
282 XtSetArg(args[num_args], nhStr(XtNfont),
283 xw_status_win->boldfs); num_args++;
287 fg = get_nhcolor(xw_status_win, CLR_GRAY).pixel;
289 XtSetArg(args[num_args], nhStr(XtNforeground), fg); num_args++;
290 XtSetArg(args[num_args], nhStr(XtNbackground), bg); num_args++;
291 XtSetValues(label, args, num_args);
292 XtResizeWidget(label, lbl_wid, lbl_hei, lbl_border_wid);
295 XtSetArg(args[num_args], nhStr(XtNwidth), &lbl_wid); num_args++;
296 XtSetArg(args[num_args], nhStr(XtNheight), &lbl_hei); num_args++;
297 XtSetArg(args[num_args], nhStr(XtNinternalWidth), &lbl_iwidth); num_args++;
298 XtSetArg(args[num_args], nhStr(XtNborderWidth), &lbl_border_wid); num_args++;
299 XtGetValues(label, args, num_args);
302 XtSetArg(args[num_args], nhStr(XtNlabel), ""); num_args++;
303 XtSetArg(args[num_args], nhStr(XtNwidth), 1); num_args++;
304 XtSetArg(args[num_args], nhStr(XtNforeground), fg); num_args++;
305 XtSetArg(args[num_args], nhStr(XtNbackground), bg); num_args++;
306 XtSetValues(label, args, num_args);
308 XtResizeWidget(label, lbl_wid, lbl_hei, lbl_border_wid);
314 X11_status_update_tty(fld, ptr, chg, percent, color, colormasks)
315 int fld, chg UNUSED, percent, color;
317 unsigned long *colormasks;
319 static boolean oncearound = FALSE; /* prevent premature partial display */
320 long *condptr = (long *) ptr;
321 int coloridx = NO_COLOR;
322 const char *text = (char *) ptr;
333 Dimension lbl_border_wid;
334 Dimension lbl_iwidth;
336 Pixel fg = X11_status_widget_fg, bg = X11_status_widget_bg;
342 if (fld < BL_RESET || fld >= MAXBLSTATS)
345 if ((fld >= 0 && fld < MAXBLSTATS) && !status_activefields[fld])
348 if (fld != BL_FLUSH && fld != BL_RESET) {
349 if (!status_activefields[fld])
353 X11_condition_bits = *condptr;
357 Sprintf(status_vals[fld],
358 (fld == BL_TITLE && iflags.wc2_hitpointbar) ? "%-30s" :
359 status_fieldfmt[fld] ? status_fieldfmt[fld] : "%s",
361 X11_status_colors[fld] = color;
362 if (iflags.wc2_hitpointbar && fld == BL_HP) {
363 hpbar_percent = percent;
368 if (fld == BL_CONDITION) {
369 MaybeDisplayCond(BL_MASK_STONE, colormasks, "Stone");
370 MaybeDisplayCond(BL_MASK_SLIME, colormasks, "Slime");
371 MaybeDisplayCond(BL_MASK_STRNGL, colormasks, "Strngl");
372 MaybeDisplayCond(BL_MASK_FOODPOIS, colormasks, "FoodPois");
373 MaybeDisplayCond(BL_MASK_TERMILL, colormasks, "TermIll");
374 MaybeDisplayCond(BL_MASK_BLIND, colormasks, "Blind");
375 MaybeDisplayCond(BL_MASK_DEAF, colormasks, "Deaf");
376 MaybeDisplayCond(BL_MASK_STUN, colormasks, "Stun");
377 MaybeDisplayCond(BL_MASK_CONF, colormasks, "Conf");
378 MaybeDisplayCond(BL_MASK_HALLU, colormasks, "Hallu");
379 MaybeDisplayCond(BL_MASK_LEV, colormasks, "Lev");
380 MaybeDisplayCond(BL_MASK_FLY, colormasks, "Fly");
381 MaybeDisplayCond(BL_MASK_RIDE, colormasks, "Ride");
383 label = X11_status_labels[fld];
384 text = status_vals[fld];
386 text = decode_mixed(tmpbuf, text);
388 coloridx = X11_status_colors[fld] & 0x00FF;
390 attridx = (X11_status_colors[fld] & 0xFF00) >> 8;
393 XtSetArg(args[num_args], nhStr(XtNfont), &font); num_args++;
394 XtSetArg(args[num_args], nhStr(XtNx), &lbl_x); num_args++;
395 XtSetArg(args[num_args], nhStr(XtNy), &lbl_y); num_args++;
396 XtSetArg(args[num_args], nhStr(XtNwidth), &lbl_wid); num_args++;
397 XtSetArg(args[num_args], nhStr(XtNheight), &lbl_hei); num_args++;
398 XtSetArg(args[num_args], nhStr(XtNinternalWidth), &lbl_iwidth); num_args++;
399 XtSetArg(args[num_args], nhStr(XtNborderWidth), &lbl_border_wid); num_args++;
400 XtGetValues(label, args, num_args);
402 /*raw_printf("font: %i-%i",
403 font->min_bounds.width, font->max_bounds.width);*/
406 lbl_wid = lbl_iwidth + font->max_bounds.width * strlen(text);
410 /*raw_printf("1:lbl_wid=%i('%s')", lbl_wid, text);*/
413 XtSetArg(args[num_args], nhStr(XtNlabel),
414 (text && *text) ? text : ""); num_args++;
415 XtSetArg(args[num_args], nhStr(XtNwidth), lbl_wid); num_args++;
417 fg = (coloridx != NO_COLOR) ? get_nhcolor(xw_status_win, coloridx).pixel
418 : X11_status_widget_fg;
419 if (attridx & HL_INVERSE) {
426 if (attridx & HL_BOLD) {
427 load_boldfont(xw_status_win, label);
428 XtSetArg(args[num_args], nhStr(XtNfont),
429 xw_status_win->boldfs); num_args++;
433 fg = get_nhcolor(xw_status_win, CLR_GRAY).pixel;
435 XtSetArg(args[num_args], nhStr(XtNforeground), fg); num_args++;
436 XtSetArg(args[num_args], nhStr(XtNbackground), bg); num_args++;
437 XtSetValues(label, args, num_args);
438 XtResizeWidget(label, lbl_wid, lbl_hei, lbl_border_wid);
443 for (y = 0; y < X11_NUM_STATUS_LINES; y++) {
446 for (x = 0; x < X11_NUM_STATUS_FIELD; x++) {
447 int f = X11_fieldorder[y][x];
451 if (!status_activefields[f])
454 if (f == BL_CONDITION) {
457 for (i = 0; i < 32; i++) {
458 label = X11_cond_labels[i];
461 XtSetArg(args[num_args], nhStr(XtNx), &lbl_x); num_args++;
462 XtSetArg(args[num_args], nhStr(XtNy), &lbl_y); num_args++;
463 XtSetArg(args[num_args], nhStr(XtNwidth), &lbl_wid); num_args++;
464 XtSetArg(args[num_args], nhStr(XtNheight), &lbl_hei); num_args++;
465 XtSetArg(args[num_args], nhStr(XtNborderWidth),
466 &lbl_border_wid); num_args++;
467 XtGetValues(label, args, num_args);
472 XtSetArg(args[num_args], nhStr(XtNx), lbl_x); num_args++;
473 XtSetValues(label, args, num_args);
474 XtConfigureWidget(label, lbl_x, lbl_y,
475 lbl_wid, lbl_hei, lbl_border_wid);
482 label = X11_status_labels[f];
484 text = status_vals[f];
486 text = decode_mixed(tmpbuf, text);
489 XtSetArg(args[num_args], nhStr(XtNx), &lbl_x); num_args++;
490 XtSetArg(args[num_args], nhStr(XtNy), &lbl_y); num_args++;
491 XtSetArg(args[num_args], nhStr(XtNwidth), &lbl_wid); num_args++;
492 XtSetArg(args[num_args], nhStr(XtNheight), &lbl_hei); num_args++;
493 XtSetArg(args[num_args], nhStr(XtNborderWidth),
494 &lbl_border_wid); num_args++;
495 XtGetValues(label, args, num_args);
498 /*raw_printf("2:lbl_wid=%i('%s')", lbl_wid, text);*/
501 XtSetArg(args[num_args], nhStr(XtNx), lbl_x); num_args++;
502 XtSetArg(args[num_args], nhStr(XtNlabel), text); num_args++;
503 XtSetValues(label, args, num_args);
504 XtConfigureWidget(label, lbl_x, lbl_y,
505 lbl_wid, lbl_hei, lbl_border_wid);
515 X11_status_update_fancy(fld, ptr, chg, percent, color, colormasks)
516 int fld, chg UNUSED, percent UNUSED, color UNUSED;
518 unsigned long *colormasks UNUSED;
520 static const struct {
522 } bl_to_fancyfield[] = {
523 { BL_TITLE, F_NAME },
530 { BL_ALIGN, F_ALIGN },
531 { BL_SCORE, F_SCORE },
532 { BL_CAP, F_ENCUMBER },
535 { BL_ENEMAX, F_MAXPOWER },
540 { BL_HUNGER, F_HUNGER },
542 { BL_HPMAX, F_MAXHP },
543 { BL_LEVELDESC, F_DLEVEL },
546 static const struct {
549 } mask_to_fancyfield[] = {
550 { BL_MASK_STONE, F_STONE },
551 { BL_MASK_SLIME, F_SLIME },
552 { BL_MASK_STRNGL, F_STRNGL },
553 { BL_MASK_FOODPOIS, F_FOODPOIS },
554 { BL_MASK_TERMILL, F_TERMILL },
555 { BL_MASK_BLIND, F_BLIND },
556 { BL_MASK_DEAF, F_DEAF },
557 { BL_MASK_STUN, F_STUN },
558 { BL_MASK_CONF, F_CONF },
559 { BL_MASK_HALLU, F_HALLU },
560 { BL_MASK_LEV, F_LEV },
561 { BL_MASK_FLY, F_FLY },
562 { BL_MASK_RIDE, F_RIDE }
566 if (fld == BL_RESET || fld == BL_FLUSH) {
567 if (WIN_STATUS != WIN_ERR) {
568 struct xwindow *wp = &window_list[WIN_STATUS];
570 update_fancy_status(wp);
575 if (fld == BL_CONDITION) {
576 unsigned long mask = (unsigned long) ptr;
578 for (i = 0; i < SIZE(mask_to_fancyfield); i++)
579 if (mask_to_fancyfield[i].mask == mask)
580 update_fancy_status_field(mask_to_fancyfield[i].ff);
582 for (i = 0; i < SIZE(bl_to_fancyfield); i++)
583 if (bl_to_fancyfield[i].bl == fld)
584 update_fancy_status_field(bl_to_fancyfield[i].ff);
589 X11_status_update(fld, ptr, chg, percent, color, colormasks)
590 int fld, chg UNUSED, percent UNUSED, color;
592 unsigned long *colormasks;
594 if (appResources.fancy_status)
595 X11_status_update_fancy(fld, ptr, chg, percent, color, colormasks);
597 X11_status_update_tty(fld, ptr, chg, percent, color, colormasks);
601 create_tty_status(parent, top)
604 Widget form; /* The form that surrounds everything. */
611 if (top != (Widget) 0) {
612 XtSetArg(args[num_args], nhStr(XtNfromVert), top);
615 XtSetArg(args[num_args], nhStr(XtNdefaultDistance), 0);
617 XtSetArg(args[num_args], XtNborderWidth, 0);
619 XtSetArg(args[num_args], XtNwidth, 400); num_args++;
620 XtSetArg(args[num_args], XtNheight, 100); num_args++;
621 form = XtCreateManagedWidget("status_viewport", viewportWidgetClass,
622 parent, args, num_args);
625 XtSetArg(args[num_args], XtNwidth, 400); num_args++;
626 XtSetArg(args[num_args], XtNheight, 100); num_args++;
627 w = XtCreateManagedWidget("status_form", formWidgetClass,
628 form, args, num_args);
629 for (y = 0; y < X11_NUM_STATUS_LINES; y++) {
630 for (x = 0; x < X11_NUM_STATUS_FIELD; x++) {
631 int fld = X11_fieldorder[y][x];
632 char labelname[BUFSZ];
637 Sprintf(labelname, "label_%s", bl_idx_to_fldname(fld));
640 prevfld = X11_fieldorder[y-1][0];
641 XtSetArg(args[num_args], nhStr(XtNfromVert),
642 X11_status_labels[prevfld]); num_args++;
645 prevfld = X11_fieldorder[y][x-1];
646 XtSetArg(args[num_args], nhStr(XtNfromHoriz),
647 X11_status_labels[prevfld]); num_args++;
650 XtSetArg(args[num_args], nhStr(XtNhorizDistance), 0); num_args++;
651 XtSetArg(args[num_args], nhStr(XtNvertDistance), 0); num_args++;
653 XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
654 XtSetArg(args[num_args], nhStr(XtNbottomMargin), 0); num_args++;
655 XtSetArg(args[num_args], nhStr(XtNleftMargin), 0); num_args++;
656 XtSetArg(args[num_args], nhStr(XtNrightMargin), 0); num_args++;
657 XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
658 XtSetArg(args[num_args], nhStr(XtNborderWidth), 0); num_args++;
660 XtSetArg(args[num_args], nhStr(XtNlabel),
661 bl_idx_to_fldname(fld)); num_args++;
663 XtSetArg(args[num_args], nhStr(XtNlabel), ""); num_args++;
664 X11_status_labels[fld] = XtCreateManagedWidget(labelname,
670 for (i = 0; i < 32; i++) {
671 char condname[BUFSZ];
674 Sprintf(condname, "cond_%i", i);
677 prevfld = X11_fieldorder[0][0];
678 XtSetArg(args[num_args], nhStr(XtNfromVert),
679 X11_status_labels[prevfld]); num_args++;
681 XtSetArg(args[num_args], nhStr(XtNfromHoriz),
682 (i == 0) ? X11_status_labels[BL_CONDITION]
683 : X11_cond_labels[i-1]); num_args++;
685 XtSetArg(args[num_args], nhStr(XtNhorizDistance), 0); num_args++;
686 XtSetArg(args[num_args], nhStr(XtNvertDistance), 0); num_args++;
687 XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
688 XtSetArg(args[num_args], nhStr(XtNbottomMargin), 0); num_args++;
689 XtSetArg(args[num_args], nhStr(XtNleftMargin), 0); num_args++;
690 XtSetArg(args[num_args], nhStr(XtNrightMargin), 0); num_args++;
691 XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
692 XtSetArg(args[num_args], nhStr(XtNborderWidth), 0); num_args++;
693 XtSetArg(args[num_args], nhStr(XtNlabel), ""); num_args++;
694 X11_cond_labels[i] = XtCreateManagedWidget(condname,
704 create_status_window_tty(wp, create_popup, parent)
705 struct xwindow *wp; /* window pointer */
706 boolean create_popup UNUSED;
712 wp->type = NHW_STATUS;
713 X11_status_widget = wp->w = create_tty_status(parent, (Widget) 0);
716 XtSetArg(args[num_args], nhStr(XtNforeground), &X11_status_widget_fg); num_args++;
717 XtSetArg(args[num_args], nhStr(XtNbackground), &X11_status_widget_bg); num_args++;
718 XtGetValues(X11_status_widget, args, num_args);
722 destroy_status_window_tty(wp)
725 /* If status_information is defined, then it a "text" status window. */
726 if (wp->status_information) {
728 nh_XtPopdown(wp->popup);
729 if (!wp->keep_window)
730 XtDestroyWidget(wp->popup), wp->popup = (Widget) 0;
732 free((genericptr_t) wp->status_information);
733 wp->status_information = 0;
736 if (!wp->keep_window)
742 adjust_status_tty(wp, str)
743 struct xwindow *wp UNUSED;
744 const char *str UNUSED;
750 create_status_window(wp, create_popup, parent)
751 struct xwindow *wp; /* window pointer */
752 boolean create_popup;
756 if (appResources.fancy_status)
757 create_status_window_fancy(wp, create_popup, parent);
759 create_status_window_tty(wp, create_popup, parent);
763 destroy_status_window(wp)
766 if (appResources.fancy_status)
767 destroy_status_window_fancy(wp);
769 destroy_status_window_tty(wp);
773 adjust_status(wp, str)
777 if (appResources.fancy_status)
778 adjust_status_fancy(wp, str);
780 adjust_status_tty(wp, str);
783 extern const char *hu_stat[]; /* from eat.c */
784 extern const char *enc_stat[]; /* from botl.c */
787 create_status_window_fancy(wp, create_popup, parent)
788 struct xwindow *wp; /* window pointer */
789 boolean create_popup;
797 Position top_margin, bottom_margin, left_margin, right_margin;
800 XFontSetExtents *extent;
803 wp->type = NHW_STATUS;
807 * If we are not creating a popup, then we must be the "main" status
811 panic("create_status_window_fancy: no parent for fancy status");
812 wp->status_information = 0;
813 wp->w = create_fancy_status(parent, (Widget) 0);
817 wp->status_information =
818 (struct status_info_t *) alloc(sizeof(struct status_info_t));
820 init_text_buffer(&wp->status_information->text);
823 XtSetArg(args[num_args], XtNallowShellResize, False);
825 XtSetArg(args[num_args], XtNinput, False);
828 wp->popup = parent = XtCreatePopupShell(
829 "status_popup", topLevelShellWidgetClass, toplevel, args, num_args);
831 * If we're here, then this is an auxiliary status window. If we're
832 * cancelled via a delete window message, we should just pop down.
836 XtSetArg(args[num_args], nhStr(XtNdisplayCaret), False);
838 XtSetArg(args[num_args], nhStr(XtNscrollHorizontal),
839 XawtextScrollWhenNeeded);
841 XtSetArg(args[num_args], nhStr(XtNscrollVertical),
842 XawtextScrollWhenNeeded);
846 #if defined(X11R6) && defined(XI18N)
847 XtSetArg(args[num_args], XtNinternational, True);
850 wp->w = XtCreateManagedWidget("status", /* name */
851 asciiTextWidgetClass,
852 parent, /* parent widget */
853 args, /* set some values */
854 num_args); /* number of values to set */
857 * Adjust the height and width of the message window so that it
858 * is two lines high and COLNO of the widest characters wide.
861 /* Get the font and margin information. */
864 XtSetArg(args[num_args], XtNfont, &fs);
866 XtSetArg(args[num_args], XtNfontSet, &fontset);
869 XtSetArg(args[num_args], nhStr(XtNtopMargin), &top_margin);
871 XtSetArg(args[num_args], nhStr(XtNbottomMargin), &bottom_margin);
873 XtSetArg(args[num_args], nhStr(XtNleftMargin), &left_margin);
875 XtSetArg(args[num_args], nhStr(XtNrightMargin), &right_margin);
877 XtGetValues(wp->w, args, num_args);
880 wp->pixel_height = 2 * nhFontHeight(wp->w) + top_margin + bottom_margin;
882 COLNO * fs->max_bounds.width + left_margin + right_margin;
884 extent = XExtentsOfFontSet(fontset);
885 wp->pixel_height = 2 * extent->max_logical_extent.height + top_margin + bottom_margin;
887 COLNO / 2 * extent->max_logical_extent.width + left_margin + right_margin;
890 /* Set the new width and height. */
892 XtSetArg(args[num_args], XtNwidth, wp->pixel_width);
894 XtSetArg(args[num_args], XtNheight, wp->pixel_height);
896 XtSetValues(wp->w, args, num_args);
900 destroy_status_window_fancy(wp)
903 /* If status_information is defined, then it a "text" status window. */
904 if (wp->status_information) {
906 nh_XtPopdown(wp->popup);
907 if (!wp->keep_window)
908 XtDestroyWidget(wp->popup), wp->popup = (Widget) 0;
910 free((genericptr_t) wp->status_information);
911 wp->status_information = 0;
913 destroy_fancy_status(wp);
915 if (!wp->keep_window)
920 * This assumes several things:
921 * + Status has only 2 lines
922 * + That both lines are updated in succession in line order.
923 * + We didn't set stringInPlace on the widget.
926 adjust_status_fancy(wp, str)
933 if (!wp->status_information) {
934 update_fancy_status(wp);
938 if (wp->cursy == 0) {
939 clear_text_buffer(&wp->status_information->text);
940 append_text_buffer(&wp->status_information->text, str, FALSE);
943 append_text_buffer(&wp->status_information->text, str, FALSE);
945 /* Set new buffer as text. */
947 XtSetArg(args[num_args], XtNstring, wp->status_information->text.text);
949 XtSetValues(wp->w, args, num_args);
953 * -------------------------------------------------------------*/
954 static int hilight_time = 1; /* number of turns to hilight a changed value */
956 struct X_status_value {
957 /* we have to cast away 'const' when assigning new names */
958 const char *name; /* text name */
959 int type; /* status type */
960 Widget w; /* widget of name/value pair */
961 long last_value; /* value displayed */
962 int turn_count; /* last time the value changed */
963 boolean set; /* if highlighted */
964 boolean after_init; /* don't highlight on first change (init) */
967 /* valid type values */
968 #define SV_VALUE 0 /* displays a label:value pair */
969 #define SV_LABEL 1 /* displays a changable label */
970 #define SV_NAME 2 /* displays an unchangeable name */
972 static void FDECL(hilight_label, (Widget));
973 static void FDECL(update_val, (struct X_status_value *, long));
974 static const char *FDECL(width_string, (int));
975 static void FDECL(create_widget, (Widget, struct X_status_value *, int));
976 static void FDECL(get_widths, (struct X_status_value *, int *, int *));
977 static void FDECL(set_widths, (struct X_status_value *, int, int));
978 static Widget FDECL(init_column, (const char *, Widget, Widget, Widget,
980 static void NDECL(fixup_cond_widths);
981 static Widget FDECL(init_info_form, (Widget, Widget, Widget));
985 * + Alignment needs a different init value, because -1 is an alignment.
986 * + Armor Class is an schar, so 256 is out of range.
987 * + Blank value is 0 and should never change.
989 static struct X_status_value shown_stats[NUM_STATS] = {
990 { "", SV_NAME, (Widget) 0, -1, 0, FALSE, FALSE }, /* 0*/
993 { "Strength", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
994 { "Dexterity", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
995 { "Constitution", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
996 { "Intelligence", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
997 { "Wisdom", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /* 5*/
998 { "Charisma", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1000 { "
\8b
\82³", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /* 0*/
1001 { "
\91f
\91\81\82³", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1002 { "
\91Ï
\8bv
\97Í", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1003 { "
\92m
\97Í", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1004 { "
\8c«
\82³", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1005 { "
\96£
\97Í", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /* 5*/
1008 { "", SV_LABEL, (Widget) 0, -1, 0, FALSE, FALSE }, /* name */
1009 { "", SV_LABEL, (Widget) 0, -1, 0, FALSE, FALSE }, /* dlvl */
1011 { "Gold", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1012 { "Hit Points", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /*10*/
1013 { "Max HP", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1014 { "Power", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1015 { "Max Power", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1016 { "Armor Class", SV_VALUE, (Widget) 0, 256, 0, FALSE, FALSE },
1017 { "Level", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /*15*/
1018 { "Experience", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1019 { "Alignment", SV_VALUE, (Widget) 0, -2, 0, FALSE, FALSE },
1020 { "Time", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1021 { "Score", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1023 { "
\8bà", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1024 { "
\91Ì
\97Í", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1025 { "
\8dÅ
\91å
\91Ì
\97Í", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /*10*/
1026 { "
\96\82\97Í", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1027 { "
\8dÅ
\91å
\96\82\97Í", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1028 { "
\8aZ", SV_VALUE, (Widget) 0,256, 0, FALSE, FALSE },
1029 { "
\83\8c\83x
\83\8b", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1030 { "
\8co
\8c±", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /*15*/
1031 { "
\91®
\90«", SV_VALUE, (Widget) 0, -2, 0, FALSE, FALSE },
1032 { "
\8e\9e\8aÔ", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1033 { "
\83X
\83R
\83A", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
1037 { "Petrifying", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE }, /*20*/
1038 { "Slimed", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1039 { "Strangled", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1040 { "Food Pois", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1041 { "Term Ill", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1043 { "
\90Î
\89»", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE }, /*20*/
1044 { "
\83X
\83\89\83C
\83\80", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1045 { "
\92\82\91§", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1046 { "
\90H
\93Å", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1047 { "
\95a
\8bC", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1050 { "", SV_NAME, (Widget) 0, -1, 0, FALSE, TRUE }, /*25*/ /* hunger */
1051 { "", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE }, /*encumbr */
1053 { "Levitating", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1054 { "Flying", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1055 { "Riding", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1057 { "
\95\82\97V", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1058 { "
\94ò
\8ds", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1059 { "
\8bR
\8fæ", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1063 { "Blind", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE }, /*30*/
1064 { "Deaf", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1065 { "Stunned", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1066 { "Confused", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1067 { "Hallucinating", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1069 { "
\96Ó
\96Ú", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE }, /*30*/
1070 { "
\8e¨
\98W", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1071 { "á¿
\9dò", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1072 { "
\8d¬
\97\90", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1073 { "
\8c¶
\8ao", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
1078 * Set all widget values to a null string. This is used after all spacings
1079 * have been calculated so that when the window is popped up we don't get all
1080 * kinds of funny values being displayed.
1086 struct X_status_value *sv;
1089 for (i = 0, sv = shown_stats; i < NUM_STATS; i++, sv++) {
1092 set_value(sv->w, "");
1097 XtSetArg(args[0], XtNlabel, "");
1098 XtSetValues(sv->w, args, ONE);
1102 impossible("null_out_status: unknown type %d\n", sv->type);
1108 /* This is almost an exact duplicate of hilight_value() */
1111 Widget w; /* label widget */
1116 XtSetArg(args[0], XtNforeground, &fg);
1117 XtSetArg(args[1], XtNbackground, &bg);
1118 XtGetValues(w, args, TWO);
1120 XtSetArg(args[0], XtNforeground, bg);
1121 XtSetArg(args[1], XtNbackground, fg);
1122 XtSetValues(w, args, TWO);
1126 update_val(attr_rec, new_value)
1127 struct X_status_value *attr_rec;
1133 if (attr_rec->type == SV_LABEL) {
1134 if (attr_rec == &shown_stats[F_NAME]) {
1135 Strcpy(buf, plname);
1136 buf[0] = highc(buf[0]);
1138 Strcat(buf, " the ");
1146 Strcpy(mname, mons[u.umonnum].mname);
1147 #if 0 /*JP*//*
\83L
\83\83\83s
\83^
\83\89\83C
\83Y
\95s
\97v*/
1148 for (k = 0; mname[k] != '\0'; k++) {
1149 if (k == 0 || mname[k - 1] == ' ')
1150 mname[k] = highc(mname[k]);
1155 Strcat(buf, rank_of(u.ulevel, pl_character[0], flags.female));
1157 } else if (attr_rec == &shown_stats[F_DLEVEL]) {
1158 if (!describe_level(buf)) {
1159 Strcpy(buf, dungeons[u.uz.dnum].dname);
1161 Sprintf(eos(buf), ", level %d", depth(&u.uz));
1163 Sprintf(eos(buf), "
\92n
\89º%d
\8aK", depth(&u.uz));
1166 impossible("update_val: unknown label type \"%s\"",
1171 if (strcmp(buf, attr_rec->name) == 0)
1174 /* Set the label. 'name' field is const for most entries;
1175 we need to cast away that const for this assignment */
1176 Strcpy((char *) attr_rec->name, buf);
1177 XtSetArg(args[0], XtNlabel, buf);
1178 XtSetValues(attr_rec->w, args, ONE);
1180 } else if (attr_rec->type == SV_NAME) {
1181 if (attr_rec->last_value == new_value)
1182 return; /* no change */
1184 attr_rec->last_value = new_value;
1186 /* special cases: hunger, encumbrance, sickness */
1187 if (attr_rec == &shown_stats[F_HUNGER]) {
1188 XtSetArg(args[0], XtNlabel, hu_stat[new_value]);
1189 } else if (attr_rec == &shown_stats[F_ENCUMBER]) {
1190 XtSetArg(args[0], XtNlabel, enc_stat[new_value]);
1191 } else if (new_value) {
1192 XtSetArg(args[0], XtNlabel, attr_rec->name);
1194 XtSetArg(args[0], XtNlabel, "");
1196 XtSetValues(attr_rec->w, args, ONE);
1198 } else { /* a value pair */
1199 boolean force_update = FALSE;
1201 /* special case: time can be enabled & disabled */
1202 if (attr_rec == &shown_stats[F_TIME]) {
1203 static boolean flagtime = TRUE;
1205 if (flags.time && !flagtime) {
1206 set_name(attr_rec->w, shown_stats[F_TIME].name);
1207 force_update = TRUE;
1208 flagtime = flags.time;
1209 } else if (!flags.time && flagtime) {
1210 set_name(attr_rec->w, "");
1211 set_value(attr_rec->w, "");
1212 flagtime = flags.time;
1218 /* special case: exp can be enabled & disabled */
1219 else if (attr_rec == &shown_stats[F_EXP]) {
1220 static boolean flagexp = TRUE;
1222 if (flags.showexp && !flagexp) {
1223 set_name(attr_rec->w, shown_stats[F_EXP].name);
1224 force_update = TRUE;
1225 flagexp = flags.showexp;
1226 } else if (!flags.showexp && flagexp) {
1227 set_name(attr_rec->w, "");
1228 set_value(attr_rec->w, "");
1229 flagexp = flags.showexp;
1235 /* special case: score can be enabled & disabled */
1236 else if (attr_rec == &shown_stats[F_SCORE]) {
1237 static boolean flagscore = TRUE;
1238 #ifdef SCORE_ON_BOTL
1240 if (flags.showscore && !flagscore) {
1241 set_name(attr_rec->w, shown_stats[F_SCORE].name);
1242 force_update = TRUE;
1243 flagscore = flags.showscore;
1244 } else if (!flags.showscore && flagscore) {
1245 set_name(attr_rec->w, "");
1246 set_value(attr_rec->w, "");
1247 flagscore = flags.showscore;
1253 set_name(attr_rec->w, "");
1254 set_value(attr_rec->w, "");
1261 /* special case: when polymorphed, show "HD", disable exp */
1262 else if (attr_rec == &shown_stats[F_LEVEL]) {
1263 static boolean lev_was_poly = FALSE;
1265 if (Upolyd && !lev_was_poly) {
1266 force_update = TRUE;
1267 set_name(attr_rec->w, "HD");
1268 lev_was_poly = TRUE;
1269 } else if (Upolyd && lev_was_poly) {
1270 force_update = TRUE;
1271 set_name(attr_rec->w, shown_stats[F_LEVEL].name);
1272 lev_was_poly = FALSE;
1274 } else if (attr_rec == &shown_stats[F_EXP]) {
1275 static boolean exp_was_poly = FALSE;
1277 if (Upolyd && !exp_was_poly) {
1278 force_update = TRUE;
1279 set_name(attr_rec->w, "");
1280 set_value(attr_rec->w, "");
1281 exp_was_poly = TRUE;
1282 } else if (Upolyd && exp_was_poly) {
1283 force_update = TRUE;
1284 set_name(attr_rec->w, shown_stats[F_EXP].name);
1285 exp_was_poly = FALSE;
1288 return; /* no display for exp when poly */
1291 if (attr_rec->last_value == new_value && !force_update) /* same */
1294 attr_rec->last_value = new_value;
1296 /* Special cases: strength, alignment and "clear". */
1297 if (attr_rec == &shown_stats[F_STR]) {
1298 if (new_value > 18) {
1299 if (new_value > 118)
1300 Sprintf(buf, "%ld", new_value - 100);
1301 else if (new_value < 118)
1302 Sprintf(buf, "18/%02ld", new_value - 18);
1304 Strcpy(buf, "18/**");
1306 Sprintf(buf, "%ld", new_value);
1308 } else if (attr_rec == &shown_stats[F_ALIGN]) {
1311 (new_value == A_CHAOTIC)
1313 : (new_value == A_NEUTRAL) ? "Neutral" : "Lawful");
1316 (new_value == A_CHAOTIC)
1318 : (new_value == A_NEUTRAL)
1319 ? "
\92\86\97§" : "
\92\81\8f\98");
1322 Sprintf(buf, "%ld", new_value);
1324 set_value(attr_rec->w, buf);
1328 * Now hilight the changed information. Names, time and score don't
1329 * hilight. If first time, don't hilight. If already lit, don't do
1332 if (attr_rec->type != SV_NAME && attr_rec != &shown_stats[F_TIME]) {
1333 if (attr_rec->after_init) {
1334 if (!attr_rec->set) {
1335 if (attr_rec->type == SV_LABEL)
1336 hilight_label(attr_rec->w);
1338 hilight_value(attr_rec->w);
1339 attr_rec->set = TRUE;
1341 attr_rec->turn_count = 0;
1343 attr_rec->after_init = TRUE;
1349 * Update the displayed status. The current code in botl.c updates
1350 * two lines of information. Both lines are always updated one after
1351 * the other. So only do our update when we update the second line.
1353 * Information on the first line:
1354 * name, attributes, alignment, score
1356 * Information on the second line:
1357 * dlvl, gold, hp, power, ac, {level & exp or HD **}, time,
1358 * status * (stone, slime, strngl, foodpois, termill,
1359 * hunger, encumbrance, lev, fly, ride,
1360 * blind, deaf, stun, conf, hallu)
1362 * [*] order of status fields is different on tty.
1363 * [**] HD is shown instead of level and exp if Upolyd.
1366 update_fancy_status_field(i)
1369 struct X_status_value *sv = &shown_stats[i];
1377 val = (long) ACURR(A_STR);
1380 val = (long) ACURR(A_DEX);
1383 val = (long) ACURR(A_CON);
1386 val = (long) ACURR(A_INT);
1389 val = (long) ACURR(A_WIS);
1392 val = (long) ACURR(A_CHA);
1395 * Label stats. With the exceptions of hunger, encumbrance, sick
1396 * these are either on or off. Pleae leave the ternary operators
1397 * the way they are. I want to specify 0 or 1, not a boolean.
1403 val = (long) near_capacity();
1406 val = Levitation ? 1L : 0L;
1409 val = Flying ? 1L : 0L;
1412 val = u.usteed ? 1L : 0L;
1414 /* fatal status conditions */
1416 val = Stoned ? 1L : 0L;
1419 val = Slimed ? 1L : 0L;
1422 val = Strangled ? 1L : 0L;
1425 val = (Sick && (u.usick_type & SICK_VOMITABLE)) ? 1L : 0L;
1428 val = (Sick && (u.usick_type & SICK_NONVOMITABLE)) ? 1L : 0L;
1430 /* non-fatal status conditions */
1432 val = Blind ? 1L : 0L;
1435 val = Deaf ? 1L : 0L;
1438 val = Stunned ? 1L : 0L;
1441 val = Confusion ? 1L : 0L;
1444 val = Hallucination ? 1L : 0L;
1449 break; /* special */
1452 break; /* special */
1454 val = money_cnt(invent);
1456 val = 0L; /* ought to issue impossible() and discard gold */
1459 val = (long) (Upolyd ? (u.mh > 0 ? u.mh : 0)
1460 : (u.uhp > 0 ? u.uhp : 0));
1463 val = (long) (Upolyd ? u.mhmax : u.uhpmax);
1469 val = (long) u.uenmax;
1475 val = (long) (Upolyd ? mons[u.umonnum].mlevel : u.ulevel);
1478 val = flags.showexp ? u.uexp : 0L;
1481 val = (long) u.ualign.type;
1484 val = flags.time ? (long) moves : 0L;
1487 #ifdef SCORE_ON_BOTL
1488 val = flags.showscore ? botl_score() : 0L;
1495 * There is a possible infinite loop that occurs with:
1497 * impossible->pline->flush_screen->bot->bot{1,2}->
1498 * putstr->adjust_status->update_other->impossible
1500 * Break out with this.
1502 static boolean active = FALSE;
1506 impossible("update_other: unknown shown value");
1513 update_val(sv, val);
1518 update_fancy_status(wp)
1519 struct xwindow *wp UNUSED;
1523 /*if (wp->cursy != 0)
1524 return;*/ /* do a complete update when line 0 is done */
1526 for (i = 0; i < NUM_STATS; i++)
1527 update_fancy_status_field(i);
1532 * Turn off hilighted status values after a certain amount of turns.
1538 struct X_status_value *sv;
1540 for (sv = shown_stats, i = 0; i < NUM_STATS; i++, sv++) {
1544 if (sv->turn_count++ >= hilight_time) {
1545 if (sv->type == SV_LABEL)
1546 hilight_label(sv->w);
1548 hilight_value(sv->w);
1554 /* Initialize alternate status =============================================
1557 /* Return a string for the initial width. */
1559 width_string(sv_index)
1573 return "088"; /* all but str never get bigger */
1578 return "Overloaded";
1593 return shown_stats[sv_index].name;
1609 /* strongest hero can pick up roughly 30% of this much */
1610 return "999999"; /* same limit as tty */
1614 return "123456789"; /* a tenth digit will still fit legibly */
1618 impossible("width_string: unknown index %d\n", sv_index);
1623 create_widget(parent, sv, sv_index)
1625 struct X_status_value *sv;
1633 sv->w = create_value(parent, sv->name);
1634 set_value(sv->w, width_string(sv_index));
1637 /* Labels get their own buffer. */
1638 sv->name = (char *) alloc(BUFSZ);
1639 /* we need to cast away 'const' when assigning a value */
1640 *(char *) (sv->name) = '\0';
1643 XtSetArg(args[num_args], XtNborderWidth, 0);
1645 XtSetArg(args[num_args], XtNinternalHeight, 0);
1647 #if defined(X11R6) && defined(XI18N)
1648 XtSetArg(args[num_args], XtNinternational, True);
1651 sv->w = XtCreateManagedWidget((sv_index == F_NAME)
1654 labelWidgetClass, parent,
1659 XtSetArg(args[0], XtNlabel, width_string(sv_index)); num_args++;
1660 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
1661 XtSetArg(args[num_args], XtNinternalHeight, 0); num_args++;
1662 #if defined(X11R6) && defined(XI18N)
1663 XtSetArg(args[num_args], XtNinternational, True); num_args++;
1665 sv->w = XtCreateManagedWidget(sv->name, labelWidgetClass, parent,
1669 panic("create_widget: unknown type %d", sv->type);
1674 * Get current width of value. width2p is only valid for SV_VALUE types.
1677 get_widths(sv, width1p, width2p)
1678 struct X_status_value *sv;
1679 int *width1p, *width2p;
1686 *width1p = get_name_width(sv->w);
1687 *width2p = get_value_width(sv->w);
1691 XtSetArg(args[0], XtNwidth, &width);
1692 XtGetValues(sv->w, args, ONE);
1697 panic("get_widths: unknown type %d", sv->type);
1702 set_widths(sv, width1, width2)
1703 struct X_status_value *sv;
1710 set_name_width(sv->w, width1);
1711 set_value_width(sv->w, width2);
1715 XtSetArg(args[0], XtNwidth, (width1 + width2));
1716 XtSetValues(sv->w, args, ONE);
1719 panic("set_widths: unknown type %d", sv->type);
1724 init_column(name, parent, top, left, col_indices)
1726 Widget parent, top, left;
1732 int max_width1, width1, max_width2, width2;
1734 struct X_status_value *sv;
1737 if (top != (Widget) 0) {
1738 XtSetArg(args[num_args], nhStr(XtNfromVert), top);
1741 if (left != (Widget) 0) {
1742 XtSetArg(args[num_args], nhStr(XtNfromHoriz), left);
1745 XtSetArg(args[num_args], nhStr(XtNdefaultDistance), 0);
1747 form = XtCreateManagedWidget(name, formWidgetClass, parent,
1750 max_width1 = max_width2 = 0;
1751 for (ip = col_indices; *ip >= 0; ip++) {
1752 sv = &shown_stats[*ip];
1753 create_widget(form, sv, *ip); /* will set init width */
1754 if (ip != col_indices) { /* not first */
1756 XtSetArg(args[num_args], nhStr(XtNfromVert),
1757 shown_stats[*(ip - 1)].w);
1759 XtSetValues(sv->w, args, num_args);
1761 get_widths(sv, &width1, &width2);
1762 if (width1 > max_width1)
1763 max_width1 = width1;
1764 if (width2 > max_width2)
1765 max_width2 = width2;
1767 for (ip = col_indices; *ip >= 0; ip++) {
1768 set_widths(&shown_stats[*ip], max_width1, max_width2);
1771 /* There is room behind the end marker for the two widths. */
1779 * These are the orders of the displayed columns. Change to suit. The -1
1780 * indicates the end of the column. The two numbers after that are used
1781 * to store widths that are calculated at run-time.
1783 static int attrib_indices[] = { F_STR, F_DEX, F_CON, F_INT, F_WIS, F_CHA,
1785 /* including F_DUMMY makes the three status condition columns evenly
1786 spaced with regard to the adjacent characteristics (Str,Dex,&c) column;
1787 we lose track of the Widget pointer for them, each use clobbering the
1788 one before, leaving the one from leftover_indices[]; since they're never
1789 updated, that shouldn't matter */
1790 static int status_indices[3][9] = { { F_STONE, F_SLIME, F_STRNGL,
1791 F_FOODPOIS, F_TERMILL, F_DUMMY,
1793 { F_HUNGER, F_ENCUMBER,
1794 F_LEV, F_FLY, F_RIDE, F_DUMMY,
1796 { F_BLIND, F_DEAF, F_STUN,
1797 F_CONF, F_HALLU, F_DUMMY,
1799 /* used to fill up the empty space to right of 3rd status condition column */
1800 static int leftover_indices[] = { F_DUMMY, -1, 0, 0 };
1802 static int col1_indices[] = { F_HP, F_POWER, F_AC, F_LEVEL, F_GOLD,
1803 F_SCORE, -1, 0, 0 };
1804 static int col2_indices[] = { F_MAXHP, F_MAXPOWER, F_ALIGN, F_EXP, F_TIME,
1807 * Produce a form that looks like the following:
1811 * col1_indices[0] col2_indices[0]
1812 * col1_indices[1] col2_indices[1]
1815 * col1_indices[n] col2_indices[n]
1817 * TODO: increase the space between the two columns.
1820 init_info_form(parent, top, left)
1821 Widget parent, top, left;
1824 struct X_status_value *sv_name, *sv_dlevel;
1827 int total_width, *ip;
1830 if (top != (Widget) 0) {
1831 XtSetArg(args[num_args], nhStr(XtNfromVert), top);
1834 if (left != (Widget) 0) {
1835 XtSetArg(args[num_args], nhStr(XtNfromHoriz), left);
1838 XtSetArg(args[num_args], nhStr(XtNdefaultDistance), 0);
1840 form = XtCreateManagedWidget("status_info", formWidgetClass, parent, args,
1844 sv_name = &shown_stats[F_NAME];
1845 create_widget(form, sv_name, F_NAME);
1848 sv_dlevel = &shown_stats[F_DLEVEL];
1849 create_widget(form, sv_dlevel, F_DLEVEL);
1852 XtSetArg(args[num_args], nhStr(XtNfromVert), sv_name->w);
1854 XtSetValues(sv_dlevel->w, args, num_args);
1856 /* two columns beneath */
1857 col1 = init_column("name_col1", form, sv_dlevel->w, (Widget) 0,
1859 (void) init_column("name_col2", form, sv_dlevel->w, col1, col2_indices);
1861 /* Add calculated widths. */
1862 for (ip = col1_indices; *ip >= 0; ip++)
1864 total_width = *++ip;
1865 total_width += *++ip;
1866 for (ip = col2_indices; *ip >= 0; ip++)
1868 total_width += *++ip;
1869 total_width += *++ip;
1871 XtSetArg(args[0], XtNwidth, total_width);
1872 XtSetValues(sv_name->w, args, ONE);
1873 XtSetArg(args[0], XtNwidth, total_width);
1874 XtSetValues(sv_dlevel->w, args, ONE);
1879 /* give the three status condition columns the same width */
1883 int pass, i, *ip, w1, w2;
1886 for (pass = 1; pass <= 2; ++pass) { /* two passes... */
1887 for (i = 0; i < 3; i++) { /* three columns */
1888 for (ip = status_indices[i]; *ip != -1; ++ip) { /* X fields */
1889 /* pass 1: find -1; pass 2: update field widths, find -1 */
1891 set_widths(&shown_stats[*ip], w1, w2);
1893 /* found -1; the two slots beyond it contain column widths */
1894 if (pass == 1) { /* pass 1: collect maxima */
1899 } else { /* pass 2: update column widths with maxima */
1904 /* ascetics: expand the maximum width to make cond columns wider */
1914 * Create the layout for the fancy status. Return a form widget that
1915 * contains everything.
1918 create_fancy_status(parent, top)
1921 Widget form; /* The form that surrounds everything. */
1929 if (top != (Widget) 0) {
1930 XtSetArg(args[num_args], nhStr(XtNfromVert), top);
1933 XtSetArg(args[num_args], nhStr(XtNdefaultDistance), 0);
1935 XtSetArg(args[num_args], XtNborderWidth, 0);
1937 XtSetArg(args[num_args], XtNorientation, XtorientHorizontal);
1939 form = XtCreateManagedWidget("fancy_status", panedWidgetClass, parent,
1942 w = init_info_form(form, (Widget) 0, (Widget) 0);
1943 w = init_column("status_attributes", form, (Widget) 0, w, attrib_indices);
1944 for (i = 0; i < 3; i++) {
1945 Sprintf(buf, "status_condition%d", i + 1);
1946 w = init_column(buf, form, (Widget) 0, w, status_indices[i]);
1948 fixup_cond_widths(); /* make all 3 status_conditionN columns same width */
1949 w = init_column("status_leftover", form, (Widget) 0, w, leftover_indices);
1955 destroy_fancy_status(wp)
1959 struct X_status_value *sv;
1961 if (!wp->keep_window)
1962 XtDestroyWidget(wp->w), wp->w = (Widget) 0;
1964 for (i = 0, sv = shown_stats; i < NUM_STATS; i++, sv++)
1965 if (sv->type == SV_LABEL) {
1966 free((genericptr_t) sv->name);