]> granicus.if.org Git - nethack/commitdiff
a couple of argrath pull requests
authornhmall <nhmall@nethack.org>
Thu, 9 Jun 2022 04:43:35 +0000 (00:43 -0400)
committernhmall <nhmall@nethack.org>
Thu, 9 Jun 2022 04:43:35 +0000 (00:43 -0400)
Closes #777 https://github.com/NetHack/NetHack/pull/777
Closes #793 https://github.com/NetHack/NetHack/pull/793

doc/fixes3-7-0.txt
doc/window2.txt [new file with mode: 0644]

index 9c42db9115669e6e815d3f08d55cb11b61a08a4e..bc9481d83188128c21276f506ea8c86208e19a64 100644 (file)
@@ -1831,6 +1831,8 @@ lua: instance cleanup should not be applied to classes (by ToxicFrog)
 fix memory leaks related to selection_new() (pr #782 by argrath)
 wished-for doors in wizmode always vertical (pr #788 by entrez)
 vampire shapeshifting in a door (pr #794 by entrez)
+split "act_on_act" into separate function (pr #777 by argrath)
+unnecessary null-check on parsesymbols() (pr #793 by argrath)
 
 
 Code Cleanup and Reorganization
diff --git a/doc/window2.txt b/doc/window2.txt
new file mode 100644 (file)
index 0000000..025a41b
--- /dev/null
@@ -0,0 +1,1167 @@
+NetHack 3.7  window.txt        $NHDT-Date: 1643491505 2022/01/29 21:25:05 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.0 $
+
+Introduction
+
+This file documents the support for various windowing systems in
+NetHack.  The support is through a standard interface, separating the
+main NetHack code from window-system specific code.  The implementation
+supports multiple window systems in the same binary.  Even if you only
+wish to support one window-port on your port, you will need to follow
+the instructions in Section IX to get a compilable binary.
+
+Copyright 2003, David Cohrs
+NetHack may be freely redistributed.  See license for details.
+
+Contents:
+       I.    Window Types and Terminology
+       II.   Interface Specification
+       III.  Global variables
+       IV.   WINCAP preferences support
+       V.    New or respecified common, high level routines
+       VI.   Game startup
+       VII.  Conventions
+       VIII. Implementation and Multi-window support
+       IX.   WINCHAIN
+
+I.  Window Types and Terminology
+
+There are 4 basic window types, used to call create_nhwindow():
+
+       NHW_MESSAGE     (top line)
+       NHW_MAP         (main dungeon)
+       NHW_MENU        (inventory or other "corner" windows)
+       NHW_TEXT        (help/text, full screen paged window)
+
+The tty window-port also uses NHW_BASE (the base display) internally.
+
+(The genl_status_* routines use NHW_STATUS for backward compatibility
+ when displaying status information on the bottom lines.  New code
+ should not use NHW_STATUS.  NHW_STATUS will be phased out over time.)
+
+NHW_MENU windows can be used for either menu or text display.  Their
+basic feature is that for the tty-port, if the window is small enough,
+it appears in the corner of the tty display instead of overwriting
+the whole screen.  The first call to add information to the window
+will decide if it is going to be used to display a menu or text.
+If start_menu() is called, then it will be used as a menu.  If
+putstr() is called, it will be used as text.  Once decided, there
+is no turning back.  For the tty-port, if the data is too large for
+a single screen then the data is paged (with --more--) between pages.
+Only NHW_MENU type windows can be used for menus.
+
+NHW_TEXT windows are used to display a large amount of textual data.
+This is the type of window one would use for displaying a help file,
+for example.  In the tty window-port, windows of type NHW_TEXT can
+page using the DEF_PAGER, if DEF_PAGER is defined.  There exists an
+assumption that the font for text windows is monospaced.  The help
+files are all formatted accordingly.
+
+"window" is always of type winid.  This is currently implemented as an
+integer, but doesn't necessarily have to be done that way.  There are
+a few fixed window names that are known throughout the code:
+
+       WIN_MESSAGE     (top line)
+       WIN_MAP         (main dungeon)
+       WIN_INVEN       (inventory)
+
+Other windows are created and destroyed as needed.
+
+(The genl_status_* routines use WIN_STATUS for backward compatibility
+ when displaying status information on the bottom lines.  New code
+ should not use WIN_STATUS, or assume its presence. NHW_STATUS will
+ be phased out over time.)
+
+"Port" in this document refers to a CPU/OS/hardware platform (UNIX, MSDOS
+TOS, etc.)  "window-port" refers to the windowing platform.  This is
+orthogonal (e.g.  UNIX might use either a tty window-port or an X11
+window-port).
+
+
+II.  Interface Specification
+
+All functions below are void unless otherwise noted.
+
+A.  Low-level routines:
+
+raw_print(str) -- Print directly to a screen, or otherwise guarantee that
+                  the user sees str.  raw_print() appends a newline to str.
+                  It need not recognize ASCII control characters.  This is
+                  used during startup (before windowing system initialization
+                  -- maybe this means only error startup messages are raw),
+                  for error messages, and maybe other "msg" uses.  E.g.
+                  updating status for micros (i.e, "saving").
+raw_print_bold(str)
+               -- Like raw_print(), but prints in bold/standout (if possible).
+curs(window, x, y)
+               -- Next output to window will start at (x,y), also moves
+                  displayable cursor to (x,y).  For backward compatibility,
+                  1 <= x < cols, 0 <= y < rows, where cols and rows are
+                  the size of window.
+               -- For variable sized windows, like the old status window, the
+                  behavior when curs() is called outside the window's limits
+                  is unspecified. The mac port wraps to 0, with the status
+                  window being 2 lines high and 80 columns wide.
+               -- Still used by curs_on_u(), obsolete status updates,
+                  screen locating (identify, teleport).
+               -- NHW_MESSAGE, NHW_MENU and NHW_TEXT windows do not
+                  currently support curs in the tty window-port.
+putstr(window, attr, str)
+               -- Print str on the window with the given attribute.  Only
+                  printable ASCII characters (040-0126) must be supported.
+                  Multiple putstr()s are output on separate lines.  Attributes
+                  can be one of
+                       ATR_NONE (or 0)
+                       ATR_ULINE
+                       ATR_BOLD
+                       ATR_BLINK
+                       ATR_INVERSE
+                  If a window-port does not support all of these, it may map
+                  unsupported attributes to a supported one (e.g. map them
+                  all to ATR_INVERSE).  putstr() may compress spaces out of
+                  str, break str, or truncate str, if necessary for the
+                  display.  Where putstr() breaks a line, it has to clear
+                  to end-of-line.
+               -- putstr should be implemented such that if two putstr()s
+                  are done consecutively the user will see the first and
+                  then the second.  In the tty port, pline() achieves this
+                  by calling more() or displaying both on the same line.
+putmixed(window, attr, str)
+               -- Print str on the window with the given attribute.  In
+                  addition to printable ASCII characters (040-0126),
+                  sequences of encoded glyph values are supported.
+                  The glyph encoding sequence is \GXXXXNNNN, where:
+                       XXXX is a hexadecimal value. The value must match
+                            the randomly generated value for the current
+                            game in progress in order to be decoded.
+                            The value for the game in progress is stored in
+                            context.rndencode.  This field minimizes
+                            unintentional decoding of player-supplied strings
+                            such as pet names, etc.
+                       NNNN is a hexadecimal value representing the glyph.
+                  If a window port does not yet support special handling of
+                  the glyph value, it can use genl_putmixed (windows.c)
+                  which converts the encoded glyph into a character symbol.
+
+                  Multiple putmixed()s are output on separate lines.
+                  Attributes can be one of
+                       ATR_NONE (or 0)
+                       ATR_ULINE
+                       ATR_BOLD
+                       ATR_BLINK
+                       ATR_INVERSE
+                  If a window-port does not support all of these, it may map
+                  unsupported attributes to a supported one (e.g. map them
+                  all to ATR_INVERSE).  putmixed() may compress spaces out of
+                  str, break str, or truncate str, if necessary for the
+                  display.  Where putmixed() breaks a line, it has to clear
+                  to end-of-line.
+               -- putstr should be implemented such that if two putmixed()s
+                  are done consecutively the user will see the first and
+                  then the second.
+get_nh_event() -- Does window event processing (e.g. exposure events).
+                  A noop for the tty and X window-ports.
+int nhgetch()  -- Returns a single character input from the user.
+               -- In the tty window-port, nhgetch() assumes that tgetch()
+                  will be the routine the OS provides to read a character.
+                  Returned character _must_ be non-zero and it must be
+                   non meta-zero too (zero with the meta-bit set).
+               -- If platform uses it, should check program_state.done_hup
+                  and immediately return ASCII 033 (escape) if it is.
+                  This is required if the window-port supports SAFERHANGUP.
+               -- ASCII 033 must also be returned rather than EOF (applies
+                  mainly to the tty window-port).
+               -- The program_state.done_hup flag can be set asynchronously
+                  when SAFERHANGUP is defined and in that case, nhgetch()
+                  needs to detect that the value of program_state.done_hup
+                  changed and also return ASCII 033 in this case.
+int nh_poskey(int *x, int *y, int *mod)
+               -- Returns a single character input from the user or a
+                  positioning event (perhaps from a mouse).  If the
+                  return value is non-zero, a character was typed, else,
+                  a position in the MAP window is returned in x, y and mod.
+                  mod may be one of
+
+                       CLICK_1         /* mouse click type 1 */
+                       CLICK_2         /* mouse click type 2 */
+
+                  The different click types can map to whatever the
+                  hardware supports.  If no mouse is supported, this
+                  routine always returns a non-zero character.
+               -- Otherwise follows the same behavior as nhgetch().
+
+B.  High-level routines:
+
+print_glyph(window, x, y, glyphinfo, bkglyphinfo)
+               -- Print a glyph found within the glyphinfo at (x,y) on the
+                   given window. The glyphs within the glyph_info struct are
+                   integers and can be mapped to whatever the window-
+                  port wants (symbol, font, color, attributes, ...there's
+                  a 1-1 map between glyphs and distinct things on the map).
+               -- bkglyphinfo contains a background glyph for potential use
+                  by some graphical or tiled environments to allow the
+                  depiction to fall against a background consistent with the
+                  grid around x,y.  If bkglyphinfo->glyph is NO_GLYPH, then
+                  the parameter should be ignored (do nothing with it).
+                -- glyph_info struct fields:
+                    int glyph;    /* the display entity */
+                    int color;    /* color for window ports not using a tile */
+                    int ttychar;  /* the character mapping for the original tty
+                                   * interface. Most or all window ports wanted
+                                   * and used this for various things so it is
+                                   * provided in 3.7+ */
+                    short int symidx;    /* offset into syms array */
+                    unsigned glyphflags; /* more detail about the entity */
+
+
+char yn_function(const char *ques, const char *choices, char default)
+               -- Print a prompt made up of ques, choices and default.
+                  Read a single character response that is contained in
+                  choices or default.  If choices is NULL, all possible
+                  inputs are accepted and returned.  This overrides
+                  everything else.  The choices are expected to be in
+                  lower case.  Entering ESC always maps to 'q', or 'n',
+                  in that order, if present in choices, otherwise it maps
+                  to default.  Entering any other quit character (SPACE,
+                  RETURN, NEWLINE) maps to default.
+               -- If the choices string contains ESC, then anything after
+                  it is an acceptable response, but the ESC and whatever
+                  follows is not included in the prompt.
+               -- If the choices string contains a '#' then accept a count.
+                  Place this value in the global "yn_number" and return '#'.
+               -- This uses the top line in the tty window-port, other
+                  ports might use a popup.
+               -- If choices is NULL, all possible inputs are accepted and
+                  returned, preserving case (upper or lower.) This means that
+                  if the calling function needs an exact match, it must handle
+                  user input correctness itself.
+               -- ques should not be more than QBUFSZ-1 characters long.
+getlin(const char *ques, char *input)
+               -- Prints ques as a prompt and reads a single line of text,
+                  up to a newline.  The string entered is returned without the
+                  newline.  ESC is used to cancel, in which case the string
+                  "\033\000" is returned.
+               -- getlin() must call flush_screen(1) before doing anything.
+               -- This uses the top line in the tty window-port, other
+                  ports might use a popup.
+               -- getlin() can assume the input buffer is at least BUFSZ
+                  bytes in size and must truncate inputs to fit, including
+                  the nul character.
+int get_ext_cmd(void)
+               -- Get an extended command in a window-port specific way.
+                  An index into extcmdlist[] is returned on a successful
+                  selection, -1 otherwise.
+player_selection()
+               -- Do a window-port specific player type selection.  If
+                  player_selection() offers a Quit option, it is its
+                  responsibility to clean up and terminate the process.
+                  You need to fill in pl_character[0].
+display_file(str, boolean complain)
+               -- Display the file named str.  Complain about missing files
+                  iff complain is TRUE.
+update_inventory(arg)
+               -- For an argument of 0:
+                  -- Indicate to the window port that the inventory has
+                     been changed.
+                  -- Merely calls display_inventory() for window-ports
+                     that leave the window up, otherwise empty.
+               -- or for a non-zero argument:
+                  -- Prompts the user for a menu scrolling action and
+                     executes that.
+                  -- May repeat until user finishes (typically by using
+                     <return> or <esc> but interface may use other means).
+doprev_message()
+               -- Display previous messages.  Used by the ^P command.
+               -- On the tty-port this scrolls WIN_MESSAGE back one line.
+
+update_positionbar(char *features)
+               -- Optional, POSITIONBAR must be defined. Provide some
+                  additional information for use in a horizontal
+                  position bar (most useful on clipped displays).
+                  Features is a series of char pairs.  The first char
+                  in the pair is a symbol and the second char is the
+                  column where it is currently located.
+                  A '<' is used to mark an upstairs, a '>'
+                  for a downstairs, and an '@' for the current player
+                  location. A zero char marks the end of the list.
+                       
+
+C.  Window Utility Routines
+
+init_nhwindows(int* argcp, char** argv)
+               -- Initialize the windows used by NetHack.  This can also
+                  create the standard windows listed at the top, but does
+                  not display them.
+               -- Any commandline arguments relevant to the windowport
+                  should be interpreted, and *argcp and *argv should
+                  be changed to remove those arguments.
+               -- When the message window is created, the variable
+                  iflags.window_inited needs to be set to TRUE.  Otherwise
+                  all plines() will be done via raw_print().
+               ** Why not have init_nhwindows() create all of the "standard"
+               ** windows?  Or at least all but WIN_INFO?      -dean
+exit_nhwindows(str)
+               -- Exits the window system.  This should dismiss all windows,
+                  except the "window" used for raw_print().  str is printed
+                  if possible.
+window = create_nhwindow(type)
+               -- Create a window of type "type."
+clear_nhwindow(window)
+               -- Clear the given window, when appropriate.
+display_nhwindow(window, boolean blocking)
+               -- Display the window on the screen.  If there is data
+                  pending for output in that window, it should be sent.
+                  If blocking is TRUE, display_nhwindow() will not
+                  return until the data has been displayed on the screen,
+                  and acknowledged by the user where appropriate.
+               -- All calls are blocking in the tty window-port.
+               -- Calling display_nhwindow(WIN_MESSAGE,???) will do a
+                  --more--, if necessary, in the tty window-port.
+destroy_nhwindow(window)
+               -- Destroy will dismiss the window if the window has not
+                  already been dismissed.
+start_menu(window, unsigned long mbehavior)
+               -- Start using window as a menu.  You must call start_menu()
+                  before add_menu().  After calling start_menu() you may not
+                  putstr() to the window.  Only windows of type NHW_MENU may
+                  be used for menus.
+               -- mbehavior allows flags to be passed to alter the appearance
+                   and/or behavior of the menu.
+add_menu(windid window, glyphinfo, const anything identifier, char accelerator,
+                                char groupacc, int attr, char *str,
+                                unsigned itemflags)
+               -- Add a text line str to the given menu window.  If identifier
+                  is 0, then the line cannot be selected (e.g. a title).
+                  Otherwise, identifier is the value returned if the line is
+                  selected.  Accelerator is a keyboard key that can be used
+                  to select the line.  If the accelerator of a selectable
+                  item is 0, the window system is free to select its own
+                  accelerator.  It is up to the window-port to make the
+                  accelerator visible to the user (e.g. put "a - " in front
+                  of str).  The value attr is the same as in putstr().
+               -- glyphinfo (glyph_info type) may optionally contain a glyph
+                   to accompany the line. If a window port cannot
+                   or does not want to display it, this is OK.  If there is no
+                   glyph provided, then the value of glyphinfo->glyph will
+                   be NO_GLYPH.
+               -- All accelerators should be in the range [A-Za-z],
+                  but there are a few exceptions such as the tty player
+                  selection code which uses '*'.
+               -- It is expected that callers do not mix accelerator
+                  choices.  Either all selectable items have an accelerator
+                  or let the window system pick them.  Don't do both.
+               -- Groupacc is a group accelerator.  It may be any character
+                  outside of the standard accelerator (see above) or a
+                  number.  If 0, the item is unaffected by any group
+                  accelerator.  If this accelerator conflicts with
+                  the menu command (or their user defined aliases), it loses.
+                  The menu commands and aliases take care not to interfere
+                  with the default object class symbols.
+               -- itemflags on this item (such as MENU_ITEMFLAGS_SELECTED etc.).
+
+end_menu(window, prompt)
+               -- Stop adding entries to the menu and flushes the window
+                  to the screen (brings to front?).  Prompt is a prompt
+                  to give the user.  If prompt is NULL, no prompt will
+                  be printed.
+               ** This probably shouldn't flush the window any more (if
+               ** it ever did).  That should be select_menu's job.  -dean
+int select_menu(windid window, int how, menu_item **selected)
+               -- Return the number of items selected; 0 if none were chosen,
+                  -1 when explicitly cancelled.  If items were selected, then
+                  selected is filled in with an allocated array of menu_item
+                  structures, one for each selected line.  The caller must
+                  free this array when done with it.  The "count" field
+                  of selected is a user supplied count.  If the user did
+                  not supply a count, then the count field is filled with
+                  -1 (meaning all).  A count of zero is equivalent to not
+                  being selected and should not be in the list.  If no items
+                  were selected, then selected is NULL'ed out.  How is the
+                  mode of the menu.  Three valid values are PICK_NONE,
+                  PICK_ONE, and PICK_ANY, meaning: nothing is selectable,
+                  only one thing is selectable, and any number valid items
+                  may selected.  If how is PICK_NONE, this function should
+                  never return anything but 0 or -1.
+               -- You may call select_menu() on a window multiple times --
+                  the menu is saved until start_menu() or destroy_nhwindow()
+                  is called on the window.
+               -- Note that NHW_MENU windows need not have select_menu()
+                  called for them. There is no way of knowing whether
+                  select_menu() will be called for the window at
+                  create_nhwindow() time.
+char message_menu(char let, int how, const char *mesg)
+               -- tty-specific hack to allow single line context-sensitive
+                  help to behave compatibly with multi-line help menus.
+               -- This should only be called when a prompt is active; it
+                  sends `mesg' to the message window.  For tty, it forces
+                  a --More-- prompt and enables `let' as a viable keystroke
+                  for dismissing that prompt, so that the original prompt
+                  can be answered from the message line "help menu".
+               -- Return value is either `let', '\0' (no selection was made),
+                  or '\033' (explicit cancellation was requested).
+               -- Interfaces which issue prompts and messages to separate
+                  windows typically won't need this functionality, so can
+                  substitute genl_message_menu (windows.c) instead.
+
+D.  Status Display Routines
+
+status_init()   -- core calls this to notify the window port that a status
+                  display is required. The window port should perform
+                  the necessary initialization in here, allocate memory, etc.
+status_enablefield(int fldindex, char fldname, char fieldfmt, boolean enable)
+                -- notifies the window port which fields it is authorized to
+                  display.
+               -- This may be called at any time, and is used
+                  to disable as well as enable fields, depending on the
+                  value of the final argument (TRUE = enable).
+               -- fldindex could be one of the following from botl.h:
+                  BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
+                  BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX,
+                  BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX,
+                  BL_LEVELDESC, BL_EXP, BL_CONDITION
+               -- There are MAXBLSTATS status fields (from botl.h)
+status_update(int fldindex, genericptr_t ptr, int chg, int percentage, \
+              int color, long *colormasks)
+               -- update the value of a status field.
+               -- the fldindex identifies which field is changing and
+                  is an integer index value from botl.h
+               -- fldindex could be any one of the following from botl.h:
+                  BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
+                  BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX,
+                  BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX,
+                  BL_LEVELDESC, BL_EXP, BL_CONDITION
+               -- fldindex could also be BL_FLUSH (-1), which is not really
+                  a field index, but is a special trigger to tell the
+                  windowport that it should output all changes received
+                   to this point. It marks the end of a bot() cycle.
+               -- fldindex could also be BL_RESET (-2), which is not really
+                  a field index, but is a special advisory to to tell the
+                  windowport that it should redisplay all its status fields,
+                  even if no changes have been presented to it.
+               -- ptr is usually a "char *", unless fldindex is BL_CONDITION.
+                  If fldindex is BL_CONDITION, then ptr is a long value with
+                  any or none of the following bits set (from botl.h):
+                        BL_MASK_BAREH        0x00000001L
+                        BL_MASK_BLIND        0x00000002L
+                        BL_MASK_BUSY         0x00000004L
+                        BL_MASK_CONF         0x00000008L
+                        BL_MASK_DEAF         0x00000010L
+                        BL_MASK_ELF_IRON     0x00000020L
+                        BL_MASK_FLY          0x00000040L
+                        BL_MASK_FOODPOIS     0x00000080L
+                        BL_MASK_GLOWHANDS    0x00000100L
+                        BL_MASK_GRAB         0x00000200L
+                        BL_MASK_HALLU        0x00000400L
+                        BL_MASK_HELD         0x00000800L
+                        BL_MASK_ICY          0x00001000L
+                        BL_MASK_INLAVA       0x00002000L
+                        BL_MASK_LEV          0x00004000L
+                        BL_MASK_PARLYZ       0x00008000L
+                        BL_MASK_RIDE         0x00010000L
+                        BL_MASK_SLEEPING     0x00020000L
+                        BL_MASK_SLIME        0x00040000L
+                        BL_MASK_SLIPPERY     0x00080000L
+                        BL_MASK_STONE        0x00100000L
+                        BL_MASK_STRNGL       0x00200000L
+                        BL_MASK_STUN         0x00400000L
+                        BL_MASK_SUBMERGED    0x00800000L
+                        BL_MASK_TERMILL      0x01000000L
+                        BL_MASK_TETHERED     0x02000000L
+                        BL_MASK_TRAPPED      0x04000000L
+                        BL_MASK_UNCONSC      0x08000000L
+                        BL_MASK_WOUNDEDL     0x10000000L
+                        BL_MASK_HOLDING      0x20000000L
+               -- The value passed for BL_GOLD includes a leading
+                  symbol for GOLD "$:nnn". If the window port needs to use
+                  the textual gold amount without the leading "$:" the port
+                  will have to add 2 to the passed "ptr" for the BL_GOLD case.
+                -- color is an unsigned int.
+                   int & 0x00FF = color CLR_*
+                   int >> 8 = attribute (if any)
+
+                   This contains the color and attribute that the field should
+                   be displayed in.
+
+                   This is relevant for everything except BL_CONDITION.
+                   If fldindex is BL_CONDITION, this parameter should be
+                   ignored, as condition hilighting is done via the next
+                   colormasks parameter instead.
+
+                -- colormasks - pointer to cond_hilites[] array of colormasks.
+                   Only relevant for BL_CONDITION fldindex. The window port
+                   should ignore this parameter for other fldindex values.
+
+                   Each condition bit must only ever appear in one of the
+                   CLR_ array members, but can appear in multiple HL_ATTCLR_
+                   offsets (because more than one attribute can co-exist).
+
+                   For the user's chosen set of BL_MASK_ condition bits,
+                   They are stored internally in the cond_hilites[] array,
+                   at the array offset aligned to the color those condition
+                   bits should display in.
+
+                   For example, if the user has chosen to display strngl
+                   and stone and termill in red and inverse,
+
+                        BL_MASK_SLIME           0x00000002
+                        BL_MASK_STRNGL          0x00000004
+                        BL_MASK_TERMILL         0x00000010
+
+                   The bitmask corresponding to those conditions is
+                   0x00000016 (or 00010110 in binary) and the color
+                   is at offset 1 (CLR_RED).
+
+                   Here is how that is stored in the cond_hilites[] array:
+
+                   +------+----------------------+--------------------+
+                   |array |                      |                    |
+                   |offset| macro for indexing   |   bitmask          |
+                   |------+----------------------+--------------------+
+                   |   0  |   CLR_BLACK          |                    |
+                   +------+----------------------+--------------------+
+                   |   1  |   CLR_RED            |   00010110         |
+                   +------+----------------------+--------------------+
+                   |   2  |   CLR_GREEN          |                    |
+                   +------+----------------------+--------------------+
+                   |   3  |   CLR_BROWN          |                    |
+                   +------+----------------------+--------------------+
+                   |   4  |   CLR_BLUE           |                    |
+                   +------+----------------------+--------------------+
+                   |   5  |   CLR_MAGENTA        |                    |
+                   +------+----------------------+--------------------+
+                   |   6  |   CLR_CYAN           |                    |
+                   +------+----------------------+--------------------+
+                   |   7  |   CLR_GRAY           |                    |
+                   +------+----------------------+--------------------+
+                   |   8  |   NO_COLOR           |                    |
+                   +------+----------------------+--------------------+
+                   |   9  |   CLR_ORANGE         |                    |
+                   +------+----------------------+--------------------+
+                   |  10  |   CLR_BRIGHT_GREEN   |                    |
+                   +------+----------------------+--------------------+
+                   |  11  |   CLR_BRIGHT_YELLOW  |                    |
+                   +------+----------------------+--------------------+
+                   |  12  |   CLR_BRIGHT_BLUE    |                    |
+                   +------+----------------------+--------------------+
+                   |  13  |   CLR_BRIGHT_MAGENTA |                    |
+                   +------+----------------------+--------------------+
+                   |  14  |   CLR_BRIGHT_CYAN    |                    |
+                   +------+----------------------+--------------------+
+                   |  15  |   CLR_WHITE          |                    |
+                   +------+----------------------+--------------------+
+                   |  16  |   HL_ATTCLR_DIM      |                    | CLR_MAX
+                   +------+----------------------+--------------------+
+                   |  17  |   HL_ATTCLR_BLINK    |                    |
+                   +------+----------------------+--------------------+
+                   |  18  |   HL_ATTCLR_ULINE    |                    |
+                   +------+----------------------+--------------------+
+                   |  19  |   HL_ATTCLR_INVERSE  |   00010110         |
+                   +------+----------------------+--------------------+
+                   |  20  |   HL_ATTCLR_BOLD     |                    |
+                   +------+----------------------+--------------------+
+                   |  21  | beyond array boundary|              | BL_ATTCLR_MAX
+
+                   The window port can AND (&) the bits passed in the
+                   ptr argument to status_update() with any non-zero
+                   entries in the cond_hilites[] array to determine
+                   the color and attributes for displaying the
+                   condition on the screen for the user.
+
+                   If the bit for a particular condition does not
+                   appear in any of the cond_hilites[] array offsets,
+                   that condition should be displayed in the default
+                   color and attributes.
+
+status_finish() -- called when it is time for the window port to tear down
+                  the status display and free allocated memory, etc.
+
+
+E.  Misc. Routines
+
+make_sound(???) -- To be determined later.  THIS IS CURRENTLY UN-IMPLEMENTED.
+nhbell()       -- Beep at user.  [This will exist at least until sounds are
+                  redone, since sounds aren't attributable to windows anyway.]
+mark_synch()   -- Don't go beyond this point in I/O on any channel until
+                  all channels are caught up to here.  Can be an empty call
+                  for the moment
+wait_synch()   -- Wait until all pending output is complete (*flush*() for
+                  streams goes here).
+               -- May also deal with exposure events etc. so that the
+                  display is OK when return from wait_synch().
+delay_output() -- Causes a visible delay of 50ms in the output.
+                  Conceptually, this is similar to wait_synch() followed
+                  by a nap(50ms), but allows asynchronous operation.
+askname()      -- Ask the user for a player name.
+cliparound(x, y)-- Make sure that the user is more-or-less centered on the
+                  screen if the playing area is larger than the screen.
+               -- This function is only defined if CLIPPING is defined.
+number_pad(state)
+               -- Initialize the number pad to the given state.
+suspend_nhwindows(str)
+               -- Prepare the window to be suspended.
+resume_nhwindows()
+               -- Restore the windows after being suspended.
+can_suspend()   -- Tell the core if the window system will allow the game
+                   to be suspended now.  If unconditionally yes or no, use
+                  genl_can_suspend_yes() or genl_can_suspend_no().
+
+start_screen() -- Only used on Unix tty ports, but must be declared for
+                  completeness.  Sets up the tty to work in full-screen
+                  graphics mode.  Look at win/tty/termcap.c for an
+                  example.  If your window-port does not need this function
+                  just declare an empty function.
+end_screen()   -- Only used on Unix tty ports, but must be declared for
+                  completeness.  The complement of start_screen().
+
+outrip(winid, int, time_t)
+               -- The tombstone code.  If you want the traditional code use
+                  genl_outrip for the value and check the #if in rip.c.
+
+preference_update(preference)
+               -- The player has just changed one of the wincap preference
+                  settings, and the NetHack core is notifying your window
+                  port of that change.  If your window-port is capable of
+                  dynamically adjusting to the change then it should do so.
+                  Your window-port will only be notified of a particular
+                  change if it indicated that it wants to be by setting the
+                  corresponding bit in the wincap mask.
+
+getmsghistory(init)
+               -- This is used to preserve message history between games by
+                  obtaining the messages from the window port so that the
+                  core can put them into the savefile.
+                  The routine is called repeatedly from the core save routine,
+                  and the window port routine is expected to successively
+                  return each message that it wants the game to store in the
+                  savefile,  starting with the oldest message first, finishing
+                  with the most recent.
+                  If init is TRUE, start over again from most recent message.
+
+putmsghistory(msg)
+               -- This is the counterpart to getmsghistory() for restores
+                  used to reload the port's message recall buffer.
+                  The routine is called repeatedly from the core restore
+                  routine, starting with the oldest message first, and
+                  finishing with the most recent one that it read from the
+                  savefile.  The window port routine is expected to load the
+                  message recall buffers in such a way that the ordering
+                  remains correct.  The window port routine should make no
+                  assumptions about how
+                  many messages are forthcoming, nor should it assume that
+                  another message will follow this one, so it must be careful
+                  to keep all pointers/indexes intact at the end of each call.
+                  If the window port receives more messages that can fit in
+                  its buffers, it is expected to scroll away the oldest from
+                  its buffers, much like it would with new messages being
+                  produced.
+
+
+III.  Global variables
+
+The following global variables are defined in decl.c and must be used by
+the window interface to the rest of NetHack.
+
+char toplines[BUFSZ]   Contains the last message printed to the WIN_MESSAGE
+                       window, used by Norep().
+winid WIN_MESSAGE, WIN_MAP, WIN_INVEN
+                       The three standard windows.
+                       There is also a window called WIN_STATUS that is used
+                       only for backward compatibility in the genl_status_*
+                       set of generic status display functions.
+char *AE, *AS;         Checked in options.c to see if we should load and
+                       switch to DECGraphics symset.  It is #ifdefed VMS
+                       and UNIX.
+int LI, CO;            Set in sys/unix/ioctl.c.
+
+The following appears to be Unix specific.  Other ports using the tty
+window-port should also declare this variable in one of your sys/*.c files.
+
+short ospeed;          Set and declared in sys/unix/unixtty.c (don't
+                       know about other sys files).
+
+The following global variable is defined in options.c. It equates a
+list of wincap option names with their associated bit-mask [see
+section IV WINCAP preferences support].  The array is zero-terminated.
+
+struct wc_Opt wc_options[];
+                       One entry for each available WINCAP option.
+                       Each entry has a wc_name field and a wc_bit
+                       field.
+
+IV. WINCAP preferences support
+
+Starting with NetHack 3.4.0, the window interface was enhanced to provide
+a common way of setting window port user preferences from the config file,
+and from the command line for some settings.
+
+The wincap preference settings all have their underlying values stored
+in iflags fields.  The names of the wincap related fields are all pre-
+fixed with wc_ or wc2_ to make it easy to identify them.  Your window
+port can access the fields directly.
+
+Your window port identifies what options it will react to and support
+by setting bits in the window_procs wincap mask and/or wincap2 mask.
+Your window port can also fill in the color-availability table for
+the window port, has_color[CLR_MAX] to flag the colors it supports
+1 it does, or 0 it doesn't. [CLR_MAX is 16 as of 3.6.3.]
+
+See section IX for details of where the wincap masks reside.
+
+Two things control whether any preference setting appears in the
+'O' command options menu during the game:
+ 1. The option must be marked as being supported by having its
+    bit set in the window_procs wincap or wincap2 mask.
+ 2. The option must have its optflag field set to set_in_game in order
+    to be able to set the option, or marked set_gameview if you just
+    want to reveal what the option is set to.
+Both conditions must be true to be able to see or set the option from
+within NetHack.
+
+The default values for the optflag field for all the options are
+hard-coded into the option in options.c.  The default value for
+the wc_ options can be altered by calling
+       set_wc_option_mod_status(optmask, status)
+The default value for the wc2_ options can be altered by calling
+       set_wc2_option_mod_status(optmask, status)
+In each case, set the option modification status to one of set_in_config,
+set_gameview, or set_in_game.
+
+The setting of any wincap or wincap2 option is handled by the NetHack
+core option processing code. You do not have to provide a parser in
+your window port, nor should you set the values for the
+iflags.wc_* and iflags.wc2_* fields directly within the port code.
+The port code should honor whatever values were put there by the core
+when processing options, either in the config file, or by the 'O' command.
+
+You may be wondering what values your window port will find in the
+iflags.wc_* and iflags.wc2_* fields for options that the user has not
+specified in his/her config file. Put another way, how does your port code
+tell if an option has not been set? The next paragraph explains that.
+
+If the core does not set an option, it will still be initialized
+to its default value. Those default values for the
+iflags.wc_* and iflags.wc_* fields are:
+
+ o All boolean fields are initialized to the starting
+   value specified for that option in the boolopt array in
+   options.c.  The window-port should respect that setting
+   unless it has a very good reason for not doing so.
+ o All int fields are initialized to zero. Zero is not a valid
+   setting for any of the int options, so if your port code
+   encounters a zero there, it can assume that the preference
+   option was not specified.  In that case, the window-port code
+   should use a default setting that the port is comfortable with.
+   It should write the default setting back into the iflags.wc_*
+   field.  That is the only time that your window-port could should
+   update those fields.
+ o All "char *" fields will be null pointers. Be sure to check for
+   that in your window-port code before using such a pointer, or
+   you'll end up triggering a nasty fault.
+
+Here are the wincap and wincap2 preference settings that your port can choose
+to support:
+
+  wincap
+  +--------------------+--------------------+--------------------+--------+
+  |                    |                    | iflags field       | data   |
+  | player option      | bit in wincap mask |   for value        | type   |
+  |--------------------+--------------------+--------------------+--------+
+  |  align_message     | WC_ALIGN_MESSAGE   | wc_align_message   |int     |
+  |  align_status      | WC_ALIGN_STATUS    | wc_align_status    |int     |
+  |  ascii_map         | WC_ASCII_MAP       | wc_ascii_map       |boolean |
+  |  color             | WC_COLOR           | wc_color           |boolean |
+  |  eight_bit_tty     | WC_EIGHT_BIT_IN    | wc_eight_bit_input |boolean |
+  |  font_map          | WC_FONT_MAP        | wc_font_map        |char *  |
+  |  font_menu         | WC_FONT_MENU       | wc_font_menu       |char *  |
+  |  font_message      | WC_FONT_MESSAGE    | wc_font_message    |char *  |
+  |  font_status       | WC_FONT_STATUS     | wc_font_status     |char *  |
+  |  font_text         | WC_FONT_TEXT       | wc_font_text       |char *  |
+  |  font_size_map     | WC_FONTSIZ_MAP     | wc_fontsiz_map     |int     |
+  |  font_size_menu    | WC_FONTSIZ_MENU    | wc_fontsiz_menu    |int     |
+  |  font_size_message | WC_FONTSIZ_MESSAGE | wc_fontsiz_message |int     |
+  |  font_size_status  | WC_FONTSIZ_STATUS  | wc_fontsiz_status  |int     |
+  |  font_size_text    | WC_FONTSIZ_TEXT    | wc_fontsiz_text    |int     |
+  |  hilite_pet        | WC_HILITE_PET      | wc_hilite_pet      |boolean |
+  |  map_mode          | WC_MAP_MODE        | wc_map_mode        |int     |
+  |  perm_invent       | WC_PERM_INVENT     | wc_perm_invent     |boolean |
+  |  player_selection  | WC_PLAYER_SELECTION| wc_player_selection|int     |
+  |  popup_dialog      | WC_POPUP_DIALOG    | wc_popup_dialog    |boolean |
+  |  preload_tiles     | WC_PRELOAD_TILES   | wc_preload_tiles   |boolean |
+  |  scroll_amount     | WC_SCROLL_AMOUNT   | wc_scroll_amount   |int     |
+  |  scroll_margin     | WC_SCROLL_MARGIN   | wc_scroll_margin   |int     |
+  |  splash_screen     | WC_SPLASH_SCREEN   | wc_splash_screen   |boolean |
+  |  tiled_map         | WC_TILED_MAP       | wc_tiled_map       |boolean |
+  |  tile_width        | WC_TILE_WIDTH      | wc_tile_width      |int     |
+  |  tile_height       | WC_TILE_HEIGHT     | wc_tile_height     |int     |
+  |  tile_file         | WC_TILE_FILE       | wc_tile_file       |char *  |
+  |  use_inverse       | WC_INVERSE         | wc_inverse         |boolean |
+  |  vary_msgcount     | WC_VARY_MSGCOUNT   | wc_vary_msgcount   |int     |
+  |  windowcolors      | WC_WINDOWCOLORS    | wc_foregrnd_menu   |char *  |
+  |                    |                    | wc_backgrnd_menu   |char *  |
+  |                    |                    | wc_foregrnd_message|char *  |
+  |                    |                    | wc_backgrnd_message|char *  |
+  |                    |                    | wc_foregrnd_status |char *  |
+  |                    |                    | wc_backgrnd_status |char *  |
+  |                    |                    | wc_foregrnd_text   |char *  |
+  |                    |                    | wc_backgrnd_text   |char *  |
+  |  mouse             | WC_MOUSE_SUPPORT   | wc_mouse_support   |boolean |
+  +--------------------+--------------------+--------------------+--------+
+
+  wincap2
+  +--------------------+--------------------+--------------------+--------+
+  |                    |                    | iflags field       | data   |
+  | player option      | bit in wincap mask |   for value        | type   |
+  |--------------------+--------------------+--------------------+--------+
+  |  fullscreen        | WC2_FULLSCREEN     | wc2_fullscreen     |boolean |
+  |  guicolor          | WC2_GUICOLOR       | wc2_guicolor       |boolean |
+  |  hilite_status     | WC2_HILITE_STATUS  | wc2_hilite_status  |strings |
+  |  hitpointbar       | WC2_HITPOINTBAR    | wc2_hitpointbar    |boolean |
+  |  menu_shift_left   | WC2_MENU_SHIFT     |  n/a               |char    |
+  |  menu_shift_right  | WC2_MENU_SHIFT     |  n/a               |char    |
+  |  petattr           | WC2_PETATTR        | wc2_petattr        |int     |
+  |  selectsaved       | WC2_SELECTSAVED    | wc2_selectsaved    |boolean |
+  |  softkeyboard      | WC2_SOFTKEYBOARD   | wc2_softkeyboard   |boolean |
+  |  statuslines       | WC2_STATUSLINES    | wc2_statuslines    |int     |
+  |  term_cols         | WC2_TERM_SIZE      | wc2_term_cols      |int     |
+  |  term_rows         | WC2_TERM_SIZE      | wc2_term_rows      |int     |
+  |  use_darkgray      | WC2_DARKGRAY       | wc2_darkgray       |boolean |
+  |  windowborders     | WC2_WINDOWBORDERS  | wc2_windowborders  |int     |
+  |  wraptext          | WC2_WRAPTEXT       | wc2_wraptext       |boolean |
+  +--------------------+--------------------+--------------------+--------+
+
+  more wincap2 for STATUS_HILITES support and control
+  +--------------------------------- +---------------------------+
+  | To inform the game engine        |                           |
+  | that the window port is equipped | bit to set in wincap mask |
+  | to receive the following in its  |                           |
+  | x_status_update() routine        |                           |
+  |----------------------------------+---------------------------+
+  | BL_FLUSH to render buffered      | WC2_FLUSH_STATUS          |
+  |          field changes now       |                           |
+  |----------------------------------+---------------------------+
+  | BL_RESET to indicate that all    | WC2_RESET_STATUS          |
+  |          fields should be redone |                           |
+  +----------------------------------+---------------------------+
+
+  additional wincap2 flag bits for supported putstr() attributes
+  +----------------------------------+---------------------------+
+  |  avoid putting message into      | WC2_SUPPRESS_HIST         |
+  |          recall history          |                           |
+  |  draw extra attention to message | WC2_URGENT_MESG           |
+  +----------------------------------+---------------------------+
+
+align_message  -- where to place message window (top, bottom, left, right)
+align_status   -- where to place status display (top, bottom, left, right).
+ascii_map      -- port should display an ascii map if it can.
+color          -- port should display color if it can.
+eight_bit_tty  -- port should allow eight bit input.
+font_map       -- port should use a font by this name for map window.
+font_menu      -- port should use a font by this name for menu windows.
+font_message   -- port should use a font by this name for message window.
+font_size_map  -- port should use this size font for the map window.
+font_size_menu -- port should use this size font for menu windows.
+font_size_message
+               -- port should use this size font for the message window.
+font_size_status-- port should use this size font for the status display.
+font_size_text -- port should use this size font for text windows.
+font_status    -- port should use a font by this name for status display.
+font_text      -- port should use a font by this name for text windows.
+fullscreen      -- port should try to use the whole screen.
+hilite_pet     -- port should mark pets in some special way on the map.
+hitpointbar    -- port should show a graphical bar representing hit points
+map_mode       -- port should display the map in the manner specified.
+player_selection
+               -- dialog or prompts for choosing character.
+popup_dialog   -- port should pop up dialog boxes for input.
+preload_tiles  -- port should preload tiles into memory.
+scroll_amount   -- scroll this amount when scroll_margin is reached.
+scroll_margin  -- port should scroll the display when the hero or cursor
+                  is this number of cells away from the edge of the window.
+selectsaved     -- if port can display a menu of the user's saved games do so.
+softkeyboard    -- handhelds should display an on-screen keyboard if possible.
+splash_screen   -- port should/should not display an opening splashscreen.
+term_cols       -- Terminal should size itself to specified width, if possible.
+term_rows       -- Terminal should size to specified height, if possible.
+tiled_map      -- port should display a tiled map if it can.
+tile_width     -- port should display tiles with this width or round to
+                  closest if it can.
+tile_height    -- port should display tiles with this height or round to
+                  closest if it can.
+tile_file      -- open this alternative tile file.  The file name is likely to
+                  be window-port or platform specific.
+use_inverse    -- port should display inverse when NetHack asks for it.
+vary_msgcount  -- port should display this number of messages at a time in
+                  the message window.
+windowborders   -- port should display borders around main NetHack windows.
+                Can be set to (1) on, (2) off, or (3) auto.
+windowcolors
+               -- port should use these colors for window foreground/background
+                  colors.  Syntax:
+                    menu fore/back message fore/back status fore/back text fore/back
+wraptext       -- port should wrap long lines of text if they don't fit in
+                  the visible area of the window
+mouse_support  -- port should enable mouse support if possible
+
+Whenever one of these settings is adjusted, the port is notified of a change
+to the setting by calling the port's preference_update() routine. The port
+is only notified if it has indicated that it supports that option by setting
+the option's bit in the port's wincap mask.  The port can choose to adjust
+for the change to an option that it receives notification about, or ignore it.
+The former approach is recommended.  If you don't want to deal with a
+user-initiated setting change, then the port should call
+set_wc_option_mod_status(mask, set_in_config) to make the option invisible to
+the user.
+
+Functions available for the window port to call:
+
+set_wc_option_mod_status(optmask, status)
+               -- Adjust the optflag field for a set of wincap options to
+                  specify whether the port wants the option to appear
+                  in the 'O' command options menu, The second parameter,
+                  "status" can be set to set_in_config, set_gameview,
+                  or set_in_game (set_in_config implies that the option
+                  is completely hidden during the game).
+
+set_wc2_option_mod_status(optmask, status)
+               -- Adjust the optflag field for a set of wincap2 options to
+                  specify whether the port wants the option to appear
+                  in the 'O' command options menu, The second parameter,
+                  "status" can be set to set_in_config, set_gameview,
+                  or set_in_game (set_in_config implies that the option
+                  is completely hidden during the game).
+
+set_option_mod_status(optnam, status)
+               -- Adjust the optflag field for one of the core options
+                  that is not part of the wincap suite.  A port might use
+                  this to override the default initialization setting for
+                  status specified in options.c.  Note that you have to
+                  specify the option by name and that you can only set
+                  one option per call unlike set_wc_option_mod_status().
+
+
+Adding a new wincap option:
+
+To add a new wincap option, please follow all these steps:
+       1. Add the option to the wincap preference settings table above. Since
+          wincap is full, your option will likely target wincap2 field.
+       2. Add the description to the paragraph below the chart.
+       3. Add the WC_ or WC2_ to the bit list in include/winprocs.h
+          (in wincap2 if there is no room in wincap).
+       4. Add the wc_ or wc2_ field(s) to the iflags structure in flag.h.
+       5. Add the name and value to wc_options[] or wc2_options[] in options.c
+       6. Add an appropriate parser to parseoptions() in options.c.
+       7. Add code to display current value to get_compopt_value() in options.c.
+       8. Document the option in Guidebook.mn and Guidebook.tex.
+       9. Add the bit name to the OR'd values in your window port's winprocs struct
+          wincap mask if your port supports the option.
+
+V.  New or respecified common, high level routines
+
+These are not part of the interface, but mentioned here for your information.
+
+char display_inventory(lets, want_reply)
+               -- Calls a start_menu()/add_menu()/select_menu() sequence.
+                  It returns the item selected, or '\0' if none is selected.
+                  Returns '\033' if the menu was canceled.
+raw_printf(str, ...)
+               -- Like raw_print(), but accepts arguments like printf().  This
+                  routine processes the arguments and then calls raw_print().
+               -- The mac version #defines error raw_printf.  I think this
+                  is a reasonable thing to do for most ports.
+pline(str, ...)
+               -- Prints a string to WIN_MESSAGE using a printf() interface.
+                  It has the variants You(), Your(), Norep(), and others
+                  in pline.c which all use the same mechanism.  pline()
+                  requires the variable "char toplines[]" be defined; Every
+                  putstr() on WIN_MESSAGE must copy str to toplines[] for use
+                  by Norep() and pline().  If the window system is not active
+                  (!iflags.window_inited) pline() uses raw_print().
+
+VI.  Game startup
+
+The following is the general order in which calls from main() should be made,
+as they relate to the window system.  The actual code may differ, but the
+order of the calls should be the same.
+
+
+choose_windows(DEFAULT_WINDOW_SYS) /* choose a default window system */
+initoptions()                     /* read the resource file */
+init_nhwindows()                  /* initialize the window system */
+process_options(argc, argv)       /* process command line options or equiv */
+if(save file is present) {
+  display_gamewindows()                   /* create & display the game windows */
+  dorestore()                     /* restore old game; pline()s are OK */
+} else {
+  player_selection()              /* select a player type using a window */
+  display_gamewindows()                   /* create & display the game windows */
+}
+pline("Hello, welcome...");
+
+Choose_windows() is a common routine, and calling it in main() is necessary
+to initialize the function pointer table to _something_ so that calls to
+raw_print() will not fail.  Choose_windows() should be called almost
+immediately upon entering main().  Look at unixmain.c for an example.
+Choose_windows will call an (optional) ini_routine with a single argument
+of WININIT to allow any needed setup.  Because choose_windows() may be called
+multiple times during argument and option processing, to handle the case where
+ini_routines have side effects that need to be undone, the old ini_routine (if
+any) will be called with an argument of WININIT_UNDO before the new
+ini_routine (if any) is called (with WININIT).
+
+Display_gamewindows() is a common routine that displays the two standard
+game windows (WIN_MESSAGE, WIN_MAP), and the status display.  It is normally
+called just before the "Hello, welcome" message.
+
+Process_options() is currently still unique to each port.  There may be need
+in the future to make it possible to replace this on a per window-port basis.
+
+
+VII.  Conventions
+
+init_nhwindows() is expected to display a gee-whiz banner window, including
+the Copyright message.  It is recommended that the COPYRIGHT_BANNER_A macro
+from patchlevel.h, COPYRIGHT_BANNER_B from patchlevel.h, 
+nomakedefs.copyright_banner_c internal global variable, and
+COPYRIGHT_BANNER_D macros from patchlevel.h be used for constructing the
+Copyright message.
+COPYRIGHT_BANNER_A is a quoted string that has NetHack copyright declaration,
+COPYRIGHT_BANNER_B is a quoted string that states who the copyright belongs to,
+nomakedefs.copyright_banner_c is a quoted string produced at runtime that
+includes version and build information, and
+COPYRIGHT_BANNER_D simply says "See License for details."
+Be sure to #include "patchlevel.h" to define these macros.  Using
+the macros will prevent having to update the Copyright information in each
+window-port prior to each release.
+
+Ports (MSDOS, TOS, MAC, etc) _may_ use window-port specific routines in
+their port specific files, _AT_THEIR_OWN_RISK_.  Since "port" and
+"window-port" are orthogonal, you make your "port" code less portable by
+using "window-port" specific routines.  Every effort should be made to
+use window-port interface routines, unless there is something port
+specific that is better suited (e.g. msmsg() for MSDOS).
+
+The tty window-port is contained in win/tty, the X window port is contained
+in win/X11.  The files in these directories contain _only_ window port code,
+and may be replaced completely by other window ports.
+
+
+VIII.  Implementation and Multi-window support
+
+NetHack 3.2 and higher support multiple window systems in the same binary.
+When writing a new window-port, you need to follow the following guidelines:
+
+1) Pick a unique prefix to identify your window-port.  For example, the tty
+   window port uses "tty"; the X11 window-port uses "X11".
+2) When declaring your interface function, precede the function names with
+   your unique prefix.  E.g:
+
+       void tty_init_nhwindows()
+       {
+               /* code for initializing windows in the tty port */
+       }
+
+   When calling window functions from within your port code, we suggest
+   calling the prefixed version to avoid unnecessary overhead.  However,
+   you may safely call the non-prefixed version (e.g. putstr() rather than
+   tty_putstr()) as long as you #include "hack.h".  If you do not
+   include hack.h and use the non-prefixed names, you will get compile
+   or link-time errors.
+
+   We also suggest declaring all functions and port-specific data with
+   this prefix to avoid unexpected overlaps with other window-ports.
+   The tty and X11 ports do not currently follow this suggestion, but do
+   use separate non-overlapping convention for naming data and internal
+   functions.
+
+3) Declare a structure, "struct window_procs prefix_procs", (with your
+   prefix instead of "prefix") and fill in names of all of your
+   interface functions.  The first entry in this structure is the name
+   of your window-port, which should be the prefix.  The second entry
+   is the wincap mask that identifies what window port preference
+   settings your port will react to and support.  The other entries
+   are the function addresses.
+
+   Assuming that you followed the convention in (2), you can safely copy
+   the structure definition from an existing window-port and just change
+   the prefixes.  That will guarantee that you get the order of your
+   initializations correct (not all compilers will catch out-of-order
+   function pointer declarations).
+
+4) Add a #define to config.h identifying your window-port in the
+   "Windowing systems" section.  Follow the "prefix_GRAPHICS" convention
+   for your window-port.
+
+5) Add your prefix to the list of valid prefixes listed in the "Known
+   systems are" comment.
+
+6) Edit makedefs.c and add a string for your windowing system to window_opts
+   inside an #ifdef prefix_GRAPHICS.
+
+7) Edit windows.c and add an external reference to your prefix_procs inside
+   an #ifdef prefix_GRAPHICS.  Also add an entry to the win_choices
+   structure for your window-port of the form:
+
+    #ifdef prefix_GRAPHICS
+       { &prefix_procs, prefix_init_function },
+    #endif
+
+   The init_function is necessary for some compilers and systems to force
+   correct linking.  If your system does not need such massaging, you
+   may put a null pointer here.
+
+   You should declare prefix_procs and prefix_init_function as extern's
+   in your win*.h file, and #include that file at the beginning of
+   windows.c, also inside an #ifdef prefix_GRAPHICS.  Some win*.h files
+   are rather sensitive, and you might have to duplicate your
+   prefix_procs and prefix_init_function's instead of including win*.h.
+   The tty port includes wintty.h, the X11 port duplicates the declarations.
+
+8) If your port uses Makefile.src, add the .c and .o files and an
+   appropriate comment in the section on "WINSRC" and "WINOBJ".  See
+   Makefile.src for the style to use.  If you don't use Makefile.src,
+   we suggest using a similar convention for the make-equivalent used
+   on your system.  Also add your new source and binaries to WINSRC and
+   WINOBJ (if you want the NetHack binary to include them, that is).
+
+9) Look at your port's portmain.c (the file containing main()) and make
+   sure that all of the calls match the requirements laid out in
+   Section VII.
+
+Now, proceed with compilation and installation as usual.  Don't forget
+to edit Makefile.src (or its equivalent) and config.h to set the
+window-ports you want in your binary, the default window-port to use,
+and the .o's needed to build a valid game.
+
+One caveat.  Unfortunately, if you incorrectly specify the
+DEFAULT_WINDOW_SYS, NetHack will dump core (or whatever) without
+printing any message, because raw_print() cannot function without first
+setting the window-port.
+
+
+IX. WINCHAIN
+
+WINCHAIN is an optional facility that allows the SYSCF_FILE to specify a
+series of processors that will see each call from the core to the window
+port (and the resulting return chain).  Processors are specified one at a
+time from the start of the chain (the core end) towards the window port as:
+    OPTIONS=windowchain:+PROC
+where PROC is the name of the processor to add to the chain.  The '+' is
+required and is part of the name of the processor (this distinguishes
+processors from window ports; in addition the '-' character is reserved for
+WINCHAIN internals).
+
+If WINCHAIN is not compiled into the NetHack binary, there is no overhead.
+
+If WINCHAIN is compiled into the NetHack binary but not used, overhead is
+limited to one function call during game setup and a trivial amount of data.
+
+Note that raw_print* calls will not go through the chain until initialization
+is complete (when *main.c calls commit_windowchain()).
+
+The only processor currently available is '+trace' which is a debugging
+facility for window ports.  See the code in win/chain/wc_trace.c for
+details on where to find the log file and how to write to it from other parts
+of the code.
+
+A processor may be specified more than once; this is expected to be most
+useful for surrounding a processor being developed with before and after
+calls to +trace.