  
  [1X6 Examples of Applications based on [10XNCurses.BrowseGeneric[1X[0X
  
  This  chapter  introduces  the  operation  [2XBrowse[0m  ([14X6.1-1[0m) and lists several
  examples  how the function [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m) can be utilized for
  rendering  [5XGAP[0m related data or for playing games. Each section describes the
  relevant  [5XGAP[0m  functions  and  briefly sketches the technical aspects of the
  implementation;  more  details  can  be  found  in the [5XGAP[0m files, in the [11Xapp[0m
  directory of the package.
  
  Only  Section  [14X6.3[0m  describes  a  standard  application  in the sense of the
  introduction  to  Chapter  [14X4[0m,  perhaps except for a special function that is
  needed  to compare table entries. The other examples in this chapter require
  some of the programming described in Chapter [14X5[0m.
  
  
  [1X6.1 The Operation [10XBrowse[1X[0X
  
  [1X6.1-1 Browse[0m
  
  [2X> Browse( [0X[3Xobj[, arec][0X[2X ) ___________________________________________[0Xoperation
  
  This operation displays the [5XGAP[0m object [3Xobj[0m in a nice, formatted way, similar
  to the operation [2XDisplay[0m ([14XReference: Display[0m). The difference is that [2XBrowse[0m
  is intended to use [10Xncurses[0m facilities.
  
  Currently  there  are  methods for character tables (see [2XBrowse[0m ([14X6.2-1[0m)) and
  for tables of marks (see [2XBrowse[0m ([14X6.3-1[0m)).
  
  
  [1X6.2 Character Table Display[0X
  
  The [5XGAP[0m library provides a [2XDisplay[0m ([14XReference: Display[0m) method for character
  tables  that  breaks  the  table  into columns fitting on the screen. [5XBrowse[0m
  provides  an  alternative,  using  the  standard  facilities of the function
  [2XNCurses.BrowseGeneric[0m  ([14X4.3-1[0m),  i. e.,  one  can  scroll  in  the matrix of
  character values, searching and sorting are provided etc.
  
  The  [2XBrowse[0m  ([14X6.1-1[0m)  method  for  character tables can be called instead of
  [2XDisplay[0m  ([14XReference:  Display[0m).  For  convenience, one can additionally make
  this  function the default [2XDisplay[0m ([14XReference: Display[0m) method for character
  tables,  by  assigning  it  to  the  [10XDisplay[0m  component in the global record
  [10XCharacterTableDisplayDefaults.User[0m,   see [14X'Reference:   Printing   Character
  Tables'[0m;  for example, one can do this in one's [11X.gaprc[0m file, see [14X'Reference:
  The   .gaprc   file'[0m.  (This  can  be  undone  by  unbinding  the  component
  [10XCharacterTableDisplayDefaults.User.Display[0m.)
  
  [1X6.2-1 Browse[0m
  
  [2X> Browse( [0X[3Xtbl[, options][0X[2X ) ___________________________________________[0Xmethod
  
  This  method  displays  the  character  table  [3Xtbl[0m in a window. The optional
  record  [3Xoptions[0m  describes what shall be displayed, the supported components
  and  the  default  values  are  described  in [14X'Reference: Printing Character
  Tables'[0m.
  
  The  full  functionality  of  the  function [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m) is
  available.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> BrowseData.SetReplay( Concatenation([0X
    [4X>         # scroll in the table[0X
    [4X>         "DRULdddddrrrrrlluu",[0X
    [4X>         # select an entry and move it around[0X
    [4X>         "seddrruuuddlll",[0X
    [4X>         # search for the pattern 135 (six times)[0X
    [4X>         "/135", [ NCurses.keys.ENTER ], "nnnnn",[0X
    [4X>         # deselect the entry, select the first column[0X
    [4X>         "qLsc",[0X
    [4X>         # sort and categorize by this column[0X
    [4X>         "sc",[0X
    [4X>         # select the first row, move down the selection[0X
    [4X>         "srdddd",[0X
    [4X>         # expand the selected category, scroll the selection down[0X
    [4X>         "xd",[0X
    [4X>         # and quit the application[0X
    [4X>         "Q" ) );[0X
    [4Xgap> Browse( CharacterTable( "HN" ) );[0X
    [4Xgap> BrowseData.SetReplay( false );[0X
  [4X------------------------------------------------------------------[0X
  
  [13XImplementation  remarks[0m:  The  first  part of the code in the [2XBrowse[0m ([14X6.1-1[0m)
  method for character tables is almost identical with the code for extracting
  the  data  to  be  displayed from the input data in the [5XGAP[0m library function
  [10XCharacterTableDisplayDefault[0m.  The  second part of the code transforms these
  data  into  a  browse  table.  Character names and (if applicable) indicator
  values are used as row labels, and centralizer orders, power maps, and class
  names  are used as column labels. The identifier of the table is used as the
  static  header.  When an irrational entry is selected, a description of this
  entry is shown in the dynamic footer.
  
  The  standard  modes  in  [2XBrowseData[0m ([14X5.4-1[0m) have been extended by three new
  actions.  The  first  two  of  them  open  pagers  giving an overview of all
  irrationalities in the table, or of all those irrationalities that have been
  shown  on  the  screen  in the current call, respectively. The corresponding
  user  inputs  are  the  [12XI[0m  and  the  [12Xi[0m  key.  (The  names  assigned  to  the
  irrationalities  are  generated column-wise. If one just scrolls through the
  table,  without  jumping, then these names coincide with the names generated
  by  the  default  [2XDisplay[0m  ([14XReference: Display[0m) method for character tables;
  this  is  in general [13Xnot[0m the case, for example when a row-wise search in the
  table  is  performed.)  The third new action, which is associated with the [12Xp[0m
  key,  toggles the visibility status of the column label rows for centralizer
  orders and power maps.
  
  An  individual  [10Xminyx[0m function does not only check whether the desired table
  fits  into  the  window but also whether a table with too high column labels
  (centralizer  orders and power maps) would fit if these labels get collapsed
  via the [12Xp[0m key. In this case, the labels are automatically collapsed, and the
  [12Xp[0m key is disabled.
  
  In  order  to keep the required space small also for large character tables,
  caching  of  formatted  matrix  entries  is  disabled, and the strings to be
  displayed  are computed on demand with a [10XMain[0m function in the [10Xwork[0m component
  of  the  browse  table. For the same reason, the constant height one for all
  table  rows  is set in advance, so one need not inspect a whole character if
  only a few values of it shall be shown.
  
  Special  functions  are  provided  for sorting (concerning the comparison of
  character values, which can be integers or irrationalities) and categorizing
  the table by a column (the value in the category row involves the class name
  of the column in question).
  
  The code can be found in the file [11Xapp/ctbldisp.g[0m of the package.
  
  
  [1X6.3 Table of Marks Display[0X
  
  The [5XGAP[0m library provides a [2XDisplay[0m ([14XReference: Display[0m) method for tables of
  marks  that  breaks the table into columns fitting on the screen. Similar to
  the  situation  with  character  tables,  see  Section [14X6.2[0m,  but with a much
  simpler implementation, [5XBrowse[0m provides an alternative based on the function
  [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m).
  
  [2XBrowse[0m  ([14X6.1-1[0m)  can  be  called instead of [2XDisplay[0m ([14XReference: Display[0m) for
  tables of marks, cf. [14X'Reference: Printing Tables of Marks'[0m.
  
  [1X6.3-1 Browse[0m
  
  [2X> Browse( [0X[3Xtom[, options][0X[2X ) ___________________________________________[0Xmethod
  
  This method displays the table of marks [3Xtom[0m in a window. The optional record
  [3Xoptions[0m  describes what shall be displayed, the supported components and the
  default values are described in [14X'Reference: Printing Tables of Marks'[0m.
  
  The  full  functionality  of  the  function [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m) is
  available.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> BrowseData.SetReplay( Concatenation([0X
    [4X>         # scroll in the table[0X
    [4X>         "DDRRR",[0X
    [4X>         # search for the (exact) value 100 (three times)[0X
    [4X>         "/100",[0X
    [4X>         [ NCurses.keys.DOWN, NCurses.keys.DOWN, NCurses.keys.RIGHT ],[0X
    [4X>         [ NCurses.keys.DOWN, NCurses.keys.DOWN, NCurses.keys.DOWN ],[0X
    [4X>         [ NCurses.keys.RIGHT, NCurses.keys.ENTER ], "nn",[0X
    [4X>         # no more occurrences of 100, confirm[0X
    [4X>         [ NCurses.keys.ENTER ],[0X
    [4X>         # and quit the application[0X
    [4X>         "Q" ) );[0X
    [4Xgap> Browse( TableOfMarks( "A10" ) );[0X
    [4Xgap> BrowseData.SetReplay( false );[0X
  [4X------------------------------------------------------------------[0X
  
  [13XImplementation remarks[0m: Rows and columns are indexed by their positions. The
  identifier of the table is used as the static header, there is no footer.
  
  In  order  to  keep the required space small also for large tables of marks,
  caching  of  formatted  matrix  entries  is  disabled, and the strings to be
  displayed  are computed on demand with a [10XMain[0m function in the [10Xwork[0m component
  of  the  browse  table. For the same reason, the constant height one for the
  table  rows is set in advance. (For example, the table of marks of the group
  with  identifier  [10X"O8+(2)"[0m,  with  11171 rows and columns, can be shown with
  [2XBrowse[0m ([14X6.1-1[0m) in a [5XGAP[0m session requiring about 100 MB.)
  
  The code can be found in the file [11Xapp/tomdisp.g[0m of the package.
  
  
  [1X6.4 Table of Contents of [5XAtlasRep[1X[0X
  
  The  [5XGAP[0m  package  [5XAtlasRep[0m (see [WPNBB07]) is an interface to a database of
  representations and related data. The table of contents of this database can
  be  displayed via the function [2XDisplayAtlasInfo[0m ([14XAtlasRep: DisplayAtlasInfo[0m)
  of  this  package.  The  [5XBrowse[0m package provides an alternative based on the
  function  [2XNCurses.BrowseGeneric[0m  ([14X4.3-1[0m);  one can scroll, search, and fetch
  representations for later use.
  
  [1X6.4-1 BrowseAtlasInfo[0m
  
  [2X> BrowseAtlasInfo( [0X[3X[0X[2X ) ______________________________________________[0Xfunction
  [6XReturns:[0X  the list of "clicked" representations.
  
  This  function  shows the table of contents of the [5XGAP[0m package [5XAtlasRep[0m in a
  browse table, cf. Section [14X'AtlasRep: Accessing Data of the AtlasRep Package'[0m
  in the package manual. When one "clicks" on one of the table rows or entries
  then  a  browse  table with an overview of the available representations for
  this  group  is  shown,  and  "clicking"  on  one  of  its  rows  adds  this
  representation to the list of return values of [2XBrowseAtlasInfo[0m.
  
  The  full  functionality  of  the  function [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m) is
  available.
  
  The  following  example  shows  how  [2XBrowseAtlasInfo[0m  can  be  used to fetch
  permutation representations of the alternating groups A_5 and A_6: We search
  for  the  group  name  [10X"A5"[0m in the overview table, and the first cell in the
  table  row  for  A_5  becomes  selected;  hitting the [12XEnter[0m key causes a new
  window  to  be opened, with an overview of the available representations for
  A_5;  moving  down  by  one  row  and hitting the [12XEnter[0m key again causes the
  second  representation  to be added to the result list, the second window is
  closed,  and  we  are back in the overview table; we move the selection down
  twice  (to  the  row for the group A_6), and choose the first representation
  for this group; finally we leave the table, and the return value is the list
  with the data for the two representations.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> d:= [ NCurses.keys.DOWN ];;  r:= [ NCurses.keys.RIGHT ];;[0X
    [4Xgap> c:= [ NCurses.keys.ENTER ];;[0X
    [4Xgap> BrowseData.SetReplay( Concatenation([0X
    [4X>        "/A5",         # Find the string A5 ...[0X
    [4X>        d, d, r,       # ... such that just the word matches,[0X
    [4X>        c,             # start the search,[0X
    [4X>        c,             # click the table entry A5,[0X
    [4X>        d,             # move down by one row,[0X
    [4X>        c,             # click the row for this representation,[0X
    [4X>        d, d,          # move down by two rows,[0X
    [4X>        c,             # click the table entry A6,[0X
    [4X>        c,             # click the first row,[0X
    [4X>        "Q" ) );       # and quit the application.[0X
    [4Xgap> tworeps:= BrowseAtlasInfo();;[0X
    [4Xgap> BrowseData.SetReplay( false );[0X
    [4Xgap> if fail in tworeps then[0X
    [4X>      Print( "no access to the Web ATLAS\n" );[0X
    [4X>    else[0X
    [4X>      Print( List( tworeps, x -> x.identifier[1] ), "\n" );[0X
    [4X[ "A5", "A6" ][0X
    [4X>    fi;[0X
  [4X------------------------------------------------------------------[0X
  
  [13XImplementation remarks[0m: The first browse table shown has a static header, no
  footer  and row labels, one row of column labels describing the type of data
  summarized in the columns.
  
  Row  and  column  separators  are  drawn as grids (cf. [2XNCurses.Grid[0m ([14X2.2-8[0m))
  composed  from  the special characters described in Section [14X2.1-6[0m, using the
  component [10Xwork.SpecialGrid[0m of the browse table, see [2XBrowseData[0m ([14X5.4-1[0m).
  
  When  a row is selected, the "click" functionality opens a new window (via a
  second level call to [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m)), in which a browse table
  with  the list of available representations for the given group is shown; in
  this  table,  "click"  results  in adding the selected representation to the
  result list, and leaving the second level table, So one returns to the first
  browse  table  and  can  choose  further  representations,  perhaps of other
  groups.   When   the   first  level  table  is  left,  the  list  of  chosen
  representations is returned.
  
  This function is available only if the [5XGAP[0m package [5XAtlasRep[0m is available.
  
  The code can be found in the file [11Xapp/atlasbrowse.g[0m of the package.
  
  
  [1X6.5 Access to [5XGAP[1X Manuals–a Variant[0X
  
  A  [5XBrowse[0m  adapted way to access several manuals is to show the hierarchy of
  books, chapters, sections, and subsections as collapsible category rows, and
  to  regard  the  contents  of each subsection as a data row of a matrix with
  only one column.
  
  This  application  is  mainly  intended  as an example with table cells that
  exceed the screen, and as an example with several category levels.
  
  [1X6.5-1 BrowseGapManuals[0m
  
  [2X> BrowseGapManuals( [0X[3X[start][0X[2X ) ______________________________________[0Xfunction
  
  This function displays the contents of the [5XGAP[0m manuals (the main [5XGAP[0m manuals
  as  well  as  the loaded package manuals) in a window. The optional argument
  [3Xstart[0m  describes  the  initial  status,  admissible  values  are the strings
  [10X"inline/collapsed"[0m,      [10X"inline/expanded"[0m,      [10X"pager/collapsed"[0m,      and
  [10X"pager/expanded"[0m.
  
  In the [10Xinline[0m cases, the parts of the manuals are shown in the browse table,
  and  in  the  [10Xpager[0m  case, the parts of the manuals are shown in a different
  window  when they are "clicked", using the user's favourite help viewer, see
  [14X'Reference: Changing the Help Viewer'[0m.
  
  In  the  [10Xcollapsed[0m cases, all category rows are collapsed, and the first row
  is  selected; typical next steps are moving down the selection and expanding
  single category rows. In the [10Xexpanded[0m cases, all category rows are expanded,
  and  nothing is selected; a typical next step in the [10Xinline/expanded[0m case is
  a  search  for  a string in the manuals. (Note that searching in quite slow:
  For  viewing  a part of a manual, the file with the corresponding section is
  read  into [5XGAP[0m, the text is formatted, the relevant part is cut out from the
  section, perhaps markup is stripped off, and finally the search is performed
  in the resulting strings.)
  
  If  no  argument  is  given  then the user is asked for selecting an initial
  status, using [2XNCurses.Select[0m ([14X3.1-2[0m).
  
  The  full  functionality  of  the  function [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m) is
  available.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> n:= [ 14, 14, 14 ];;  # ``do nothing''[0X
    [4Xgap> BrowseData.SetReplay( Concatenation([0X
    [4X>        "xdxd",                             # expand a Tutorial section[0X
    [4X>        n, "Q" ) );                         # and quit[0X
    [4Xgap> BrowseGapManuals( "inline/collapsed" );[0X
    [4Xgap> BrowseData.SetReplay( Concatenation([0X
    [4X>        "/Browse", [ NCurses.keys.ENTER ],  # search for "Browse"[0X
    [4X>        "xdxddxd",                          # expand a section[0X
    [4X>        n, "Q" ) );                         # and quit[0X
    [4Xgap> BrowseGapManuals( "inline/collapsed" );[0X
    [4Xgap> BrowseData.SetReplay( false );[0X
  [4X------------------------------------------------------------------[0X
  
  [13XImplementation  remarks[0m:  The  browse table has a dynamic header showing the
  name  of  the currently selected manual, no footer, no row or column labels,
  and  exactly  one  column  of  fixed  width  equal  to the screen width. The
  category rows are precomputed, i. e., they do not arise from a table column;
  this  way, the contents of each data cell can be computed on demand, as soon
  as  it  is  shown  on  the  screen,  in particular the category hierarchy is
  computed  without  reading the manuals into [5XGAP[0m. Also, the data rows are not
  cached.  There is no return value. The heights of many cells are bigger than
  the  screen  height, so scrolling is a mixture of scrolling to the next cell
  and  scrolling  inside a cell. The different initial states are realized via
  executing different initial steps before the table is shown to the user.
  
  For  the  variants  that  show  the manuals in a pager, the code temporarily
  replaces  the  [10Xshow[0m function of the default viewer [10X"screen"[0m (see [14X'Reference:
  Changing  the  Help  Viewer'[0m) by a function that uses [2XNCurses.Pager[0m ([14X3.1-4[0m).
  Note  that in the case that the manual bit in question fits into one screen,
  the  default [10Xshow[0m function writes this text directly to the screen, but this
  is used already by the browse table.
  
  The implementation should be regarded as a sketch.
  
  For  example, the markup available in the text file format of [5XGAPDoc[0m manuals
  (using  [12XEsc[0m  sequences)  is stripped off instead of being transferred to the
  attribute lines that arise, because of the highlighting problem mentioned in
  Section [14X2.2-3[0m.
  
  Some  heuristics  used  in  the  code  are due to deficiencies of the manual
  formats.
  
  For  the  inline  variant  of  the  browse  table,  the  titles of chapters,
  sections, and subsections are [13Xnot[0m regarded as parts of the actual text since
  they appear already as category rows; however, the functions of the [5XGAP[0m help
  system  deliver  the text [13Xtogether with[0m these titles, so these lines must be
  stripped off afterwards.
  
  The  category  hierarchy representing the tables of contents is created from
  the  [11Xmanual.six[0m  files  of  the  manuals.  These files do not contain enough
  information  for  determining  whether  several  functions  define  the same
  subsection,  in  the  sense  that there is a common description text after a
  series  of  manual lines introducing different functions. In such cases, the
  browse  table  contains a category row for each of these functions (with its
  own number), but the corresponding text appears only under the [13Xlast[0m of these
  category  rows,  the  data rows for the others are empty. (This problem does
  not  occur  in  the  [5XGAPDoc[0m  manual  format because this introduces explicit
  subsection   titles,   involving   only   the   [13Xfirst[0m  of  several  function
  definitions.)
  
  Also, index entries and sectioning entries in [11Xmanual.six[0m files of manuals in
  [5XGAPDoc[0m format are not explicitly distinguished.
  
  The code can be found in the file [11Xapp/manual.g[0m of the package.
  
  
  [1X6.6 Overview of the [5XGAP[1X Bibliography[0X
  
  The  [5XGAP[0m  documentation contains a bibliography of [5XGAP[0m related publications,
  see [GAP].  [5XBrowse[0m  provides  access  to  this information in [5XGAP[0m, using the
  standard  facilities  of  the function [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m), i. e.,
  one  can  scroll  in  the  list,  search for entries, sort by year, sort and
  categorize by authors etc.
  
  The   [5XBrowse[0m   package   contains  a  (perhaps  outdated)  version  of  this
  bibliography. One can get an updated version as follows.
  
  [10Xwget -N http://www.gap-system.org/Doc/Bib/gap-publishednicer.bib[0m
  
  [1X6.6-1 BrowseBibliography[0m
  
  [2X> BrowseBibliography( [0X[3X[bibfiles][0X[2X ) _________________________________[0Xfunction
  [6XReturns:[0X  a    record    as   returned   by   [2XParseBibXMLExtFiles[0m   ([14XGAPDoc:
            ParseBibXMLextFiles[0m).
  
  This  function  shows the list of bibliography entries in the files given by
  [3Xbibfiles[0m, which may be a string or a list of strings (denoting a filename or
  a  list of filenames, respectively) or a record (see below for the supported
  components).
  
  If  no  argument  is  given then the file [11Xbibl/gap-publishednicer.bib[0m in the
  [5XBrowse[0m  package  directory  is  taken, and [10X"GAP Bibliography"[0m is used as the
  header.
  
  Another  perhaps  interesting  data file that should be available in the [5XGAP[0m
  distribution is [11Xdoc/manualbib.xml[0m. This file can be located as follows.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> file:= Filename( DirectoriesLibrary( "doc" ), "manualbib.xml" );;[0X
  [4X------------------------------------------------------------------[0X
  
  Both  BibTeX format and the [5XXML[0m based extended format provided by the [5XGAPDoc[0m
  package  are supported by [2XBrowseBibliography[0m, see Chapter [14X'GAPDoc: Utilities
  for Bibliographies'[0m.
  
  In  the  case  of  BibTeX  format  input, first a conversion to the extended
  format  takes  place,  via [2XStringBibAsXMLext[0m ([14XGAPDoc: StringBibAsXMLext[0m) and
  [2XParseBibXMLextString[0m ([14XGAPDoc: ParseBibXMLextString[0m). Note that syntactically
  incorrect  entries  are  rejected  in this conversion –this is signaled with
  [2XInfoBibTools[0m  ([14XGAPDoc: InfoBibTools[0m) warnings– and that only a subset of the
  possible  LaTeX  markup  is  recognized  –other markup appears in the browse
  table except that the leading backslash is removed.
  
  In both cases of input, the problem arises that in visual mode, currently we
  can  show  only  ASCII  characters (and the symbols in [10XNCurses.lineDraw[0m, but
  these  are  handled  differently,  see Section [14X2.1-6[0m). Therefore, we use the
  function   [2XSimplifiedUnicodeString[0m   ([14XGAPDoc:  SimplifiedUnicodeString[0m)  for
  replacing other unicode characters by ASCII text.
  
  The  return  value  is  a record as returned by [2XParseBibXMLExtFiles[0m ([14XGAPDoc:
  ParseBibXMLextFiles[0m),  its [10Xentries[0m component corresponds to the bibliography
  entries  that have been "clicked" in visual mode. This record can be used as
  input for [2XWriteBibFile[0m ([14XGAPDoc: WriteBibFile[0m) or [2XWriteBibXMLextFile[0m ([14XGAPDoc:
  WriteBibXMLextFile[0m),  in  order to produce a bibliography file, or it can be
  used as input for [2XStringBibXMLEntry[0m ([14XGAPDoc: StringBibXMLEntry[0m), in order to
  produce strings from the entries, in various formats.
  
  The  full  functionality  of  the  function [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m) is
  available.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> # sort and categorize by year, scroll down, expand a category row[0X
    [4Xgap> BrowseData.SetReplay( "scrrscsedddddxdddddQ" );[0X
    [4Xgap> BrowseBibliography();;[0X
    [4Xgap> # sort & categorize by authors, expand all category rows, scroll down[0X
    [4Xgap> BrowseData.SetReplay( "scscXseddddddQ" );[0X
    [4Xgap> BrowseBibliography();;[0X
    [4Xgap> # sort and categorize by journal, search for a journal name, expand[0X
    [4Xgap> BrowseData.SetReplay( Concatenation( "scrrrsc/J. Algebra",[0X
    [4X>        [ NCurses.keys.ENTER ], "nxdddQ" ) );[0X
    [4Xgap> BrowseBibliography();;[0X
    [4Xgap> BrowseData.SetReplay( false );[0X
  [4X------------------------------------------------------------------[0X
  
  [13XImplementation  remarks[0m:  The browse table has a dynamic header (showing the
  number  of  entries, which can vary when the table is restricted), no footer
  and row labels; one row of column labels is given by the descriptions of the
  table columns (authors, title, year, journal).
  
  Row  and  column  separators  are  drawn as grids (cf. [2XNCurses.Grid[0m ([14X2.2-8[0m))
  composed  from  the special characters described in Section [14X2.1-6[0m, using the
  component [10Xwork.SpecialGrid[0m of the browse table, see [2XBrowseData[0m ([14X5.4-1[0m).
  
  For categorizing by authors, the sort parameter [10X"split rows on categorizing"[0m
  is  set to [10X"yes"[0m, so the authors are distributed to different category rows,
  hence  each  entry  appears  once for each of its authors in the categorized
  table.  When  a data row or an entry in a data row is selected, "click" adds
  the corresponding bibliographhy entry to the result.
  
  The width of the title column is preset; usually titles are too long for one
  line, and the contents of this column is formatted as a paragraph, using the
  function  [2XFormatParagraph[0m  ([14XGAPDoc:  FormatParagraph[0m).  For  the authors and
  journal columns, maximal widths are prescribed, and [2XFormatParagraph[0m ([14XGAPDoc:
  FormatParagraph[0m) is used for longer entries.
  
  For  three  columns, the sort parameters are defined as follows: The [13Xauthors[0m
  column  does  not  become  hidden when the table is categorized according to
  this column, sorting by the [13Xyear[0m yields a [13Xde[0mscending order, and the category
  rows  arising  from these columns and the [13Xjournal[0m column show the numbers of
  the data rows that belong to them.
  
  Those  standard  modes  in [2XBrowseData[0m ([14X5.4-1[0m) where an entry or a row of the
  table  is  selected  have  been  extended by three new actions, which open a
  pager  showing  the  BibTeX,  HTML,  and  Text format of the selected entry,
  respectively. The corresponding user inputs are the [12Xvb[0m, [12Xvh[0m, and [12Xvt[0m.
  
  This  function  requires  some  of the utilities provided by the [5XGAP[0m package
  [5XGAPDoc[0m  (see [LN07]),  such  as  [2XFormatParagraph[0m  ([14XGAPDoc: FormatParagraph[0m),
  [2XNormalizeNameAndKey[0m   ([14XGAPDoc:   NormalizeNameAndKey[0m),  [2XNormalizedNameAndKey[0m
  ([14XGAPDoc:   NormalizedNameAndKey[0m),   [2XParseBibFiles[0m  ([14XGAPDoc:  ParseBibFiles[0m),
  [2XParseBibXMLextFiles[0m   ([14XGAPDoc:   ParseBibXMLextFiles[0m),  [2XParseBibXMLextString[0m
  ([14XGAPDoc: ParseBibXMLextString[0m), [2XRecBibXMLEntry[0m ([14XGAPDoc: RecBibXMLEntry[0m), and
  [2XStringBibAsXMLext[0m ([14XGAPDoc: StringBibAsXMLext[0m).
  
  The code can be found in the file [11Xapp/gapbibl.g[0m of the package.
  
  The  browse  table can be customized by entering a record as the argument of
  [2XBrowseBibliography[0m, with the following supported components.
  
  [8X[10Xfiles[0m[8X[0m
        a nonempty list of filenames containing the data to be shown; there is
        no default for this component.
  
  [8X[10Xfilesshort[0m[8X[0m
        a  list  of  the  same  length as the [10Xfiles[0m component, the entries are
        strings  which  are  shown in the [10X"sourcefilename"[0m column of the table
        (if this column is present); the default is the list of filenames.
  
  [8X[10Xfilecontents[0m[8X[0m
        a  list  of  the  same  length as the [10Xfiles[0m component, the entries are
        strings  which  are  shown  as  category  values  when  the  table  is
        categorized by the [10X"sourcefilename"[0m column; the default is the list of
        filenames.
  
  [8X[10Xheader[0m[8X[0m
        is  the  constant part of the header shown above the browse table, the
        default is the first filename.
  
  [8X[10Xcolumns[0m[8X[0m
        is  a  list  of  records  that  are  valid  as  the second argument of
        [2XDatabaseAttributeAdd[0m  ([14XA.1-5[0m),  where the first argument is a database
        id  enumerator  created  from the bibliography entries in the files in
        question.  Each  entry (and also the corresponding identifier) of this
        database   id   enumerator   is   a  list  of  records  obtained  from
        [2XParseBibXMLextFiles[0m  ([14XGAPDoc:  ParseBibXMLextFiles[0m) and [2XRecBibXMLEntry[0m
        ([14XGAPDoc:    RecBibXMLEntry[0m),    or    from    [2XParseBibFiles[0m   ([14XGAPDoc:
        ParseBibFiles[0m),  such that the list elements are regarded as equal, in
        the  sense  that their fingerprints (see below) are equal. The records
        in  the [10Xcolumns[0m list are available for constructing the desired browse
        table,  the  actual  appearance  is controlled by the [10Xchoice[0m component
        described  below.  Columns  showing authors, title, year, journal, and
        filename are predefined and need not be listed here.
  
  [8X[10Xchoice[0m[8X[0m
        a  list of strings denoting the [10Xidentifier[0m components of those columns
        that shall actually be shown in the table, the default is [10X[ "authors",
        "title", "year", "journal" ][0m.
  
  [8X[10Xfingerprint[0m[8X[0m
        a  list  of  strings  denoting  component  names of the entries of the
        database  id enumerator that is constructed from the data (see above);
        two  data  records  are  regarded  as  equal  if  the  values of these
        components   are   equal;   the  default  is  [10X[  "mrnumber",  "title",
        "authorAsList", "editorAsList", "author" ][0m.
  
  [8X[10XsortKeyFunction[0m[8X[0m
        either  [9Xfail[0m  or  a  function  that  takes  a  record  as  returned by
        [2XRecBibXMLEntry[0m  ([14XGAPDoc:  RecBibXMLEntry[0m)  and  returns a list that is
        used  for comparing and thus sorting the records; the default is [9Xfail[0m,
        which  means that the rows of the table appear in the same ordering as
        in the source files.
  
  
  [1X6.7 Overview of [5XGAP[1X Data[0X
  
  The [5XGAP[0m system contains several data collections such as libraries of groups
  and character tables. Clearly the function [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m) can
  be used to visualize interesting information about such data collections, in
  the  form of an "overview table" whose rows correspond to the objects in the
  collection;  each column of the table shows a piece of information about the
  objects.   (One   possibility   to   create   such  overviews  is  given  by
  [2XBrowseTableFromDatabaseIdEnumerator[0m ([14XA.2-2[0m).)
  
  [1X6.7-1 BrowseGapData[0m
  
  [2X> BrowseGapData( [0X[3X[0X[2X ) ________________________________________________[0Xfunction
  [6XReturns:[0X  the return value of the chosen application if there is one.
  
  The    function    [2XBrowseGapData[0m    shows    the   choices   in   the   list
  [10XBrowseData.GapDataOverviews[0m,  in  a  browse  table  with one column. When an
  entry  is "clicked" then the associated function is called, and the table of
  choices is closed.
  
  The  idea  is  that  each  entry of [10XBrowseData.GapDataOverviews[0m describes an
  overview of a [5XGAP[0m data collection.
  
  The  [5XBrowse[0m package provides overviews of the Conway polynomials in [5XGAP[0m, the
  [5XGAP[0m  bibliography  (see Section [14X6.6[0m), the [5XGAP[0m manuals (see Section [14X6.5[0m), [5XGAP[0m
  operations and methods, and the installed [5XGAP[0m packages.
  
  Other [5XGAP[0m packages may add more overviews to the choices, using the function
  [2XBrowseGapDataAdd[0m ([14X6.7-2[0m).
  
  Except that always one table cell is selected, the full functionality of the
  function [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m) is available.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> n:= [ 14, 14, 14 ];;  # ``do nothing''[0X
    [4Xgap> # open the overview of Conway polynomials[0X
    [4Xgap> BrowseData.SetReplay( Concatenation( "/Conway Polynomials",[0X
    [4X>      [ NCurses.keys.ENTER, NCurses.keys.ENTER ], "srdddd", n, "Q" ) );[0X
    [4Xgap> BrowseGapData();;[0X
    [4Xgap> # open the overview of GAP packages[0X
    [4Xgap> BrowseData.SetReplay( Concatenation( "/GAP Packages",[0X
    [4X>      [ NCurses.keys.ENTER, NCurses.keys.ENTER ], "/Browse",[0X
    [4X>      [ NCurses.keys.ENTER ], "n", n, "Q" ) );[0X
    [4Xgap> BrowseGapData();;[0X
    [4Xgap> BrowseData.SetReplay( false );[0X
  [4X------------------------------------------------------------------[0X
  
  [13XImplementation  remarks[0m:  The  browse  table  has a static header, a dynamic
  footer  showing  the  description of the currently selected entry, no row or
  column  labels,  and  exactly  one column of fixed width equal to the screen
  width. If the chosen application has a return value then this is returned by
  [2XBrowseGapData[0m, otherwise nothing is returned. The component [10Xwork.SpecialGrid[0m
  of  the browse table is used to draw a border around the list of choices and
  another  border around the footer. Only one mode is needed in which an entry
  is selected.
  
  The code can be found in the file [11Xapp/gapdata.g[0m of the package.
  
  [1X6.7-2 BrowseGapDataAdd[0m
  
  [2X> BrowseGapDataAdd( [0X[3Xtitle, call, ret, documentation[0X[2X ) ______________[0Xfunction
  
  This  function  extends the list [10XBrowseData.GapDataOverviews[0m by a new entry.
  The list is used by [2XBrowseGapData[0m ([14X6.7-1[0m).
  
  [3Xtitle[0m  must be a string of length at most 76; it will be shown in the browse
  table  that is opened by [2XBrowseGapData[0m ([14X6.7-1[0m). [3Xcall[0m must be a function that
  takes  no  arguments; it will be called when [3Xtitle[0m is "clicked". [3Xret[0m must be
  [9Xtrue[0m  if  [3Xcall[0m  has a return value and if [2XBrowseGapData[0m ([14X6.7-1[0m) shall return
  this  value,  and  [9Xfalse[0m  otherwise.  [3Xdocumentation[0m  must  be  a string that
  describes what happens when the function [3Xcall[0m is called; it will be shown in
  the  footer  of  the  table  opened  by  [2XBrowseGapData[0m ([14X6.7-1[0m) when [3Xtitle[0m is
  selected.
  
  
  [1X6.8 Navigating in a Directory Tree[0X
  
  A  natural  way to visualize the contents of a directory is via a tree whose
  leaves  denote  plain  files,  and the other vertices denote subdirectories.
  [5XBrowse[0m  provides  a  function  based  on  [2XNCurses.BrowseGeneric[0m  ([14X4.3-1[0m) for
  displaying such trees; the leaves correspond to the data rows, and the other
  vertices correspond to category rows.
  
  [1X6.8-1 BrowseDirectory[0m
  
  [2X> BrowseDirectory( [0X[3X[startpath][0X[2X ) ___________________________________[0Xfunction
  [6XReturns:[0X  a list of the "clicked" filenames.
  
  If no argument is given then the contents of the current directory is shown,
  see [2XDirectoryCurrent[0m ([14XReference: DirectoryCurrent[0m). If a string [3Xstartpath[0m is
  given as the only argument then it is understood as a directory path, in the
  sense  of  [2XDirectory[0m  ([14XReference:  Directory[0m),  and  the  contents  of  this
  directory is shown.
  
  The  full  functionality  of  the  function [2XNCurses.BrowseGeneric[0m ([14X4.3-1[0m) is
  available.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> n:= [ 14, 14, 14 ];;  # ``do nothing''[0X
    [4Xgap> BrowseData.SetReplay( Concatenation([0X
    [4X>        "q",                                  # leave the selection[0X
    [4X>        "X",                                  # expand all categories[0X
    [4X>        "/filetree", [ NCurses.keys.ENTER ],  # search for "filetree"[0X
    [4X>        n, "Q" ) );                           # and quit[0X
    [4Xgap> dir:= Filename( DirectoriesPackageLibrary( "Browse", "" ), "" );;[0X
    [4Xgap> BrowseDirectory( dir );;[0X
    [4Xgap> BrowseData.SetReplay( false );[0X
  [4X------------------------------------------------------------------[0X
  
  [13XImplementation  remarks[0m: The browse table has a static header, no footer, no
  row  or  column  labels,  and exactly one data column. The category rows are
  precomputed,  i. e.,  they  do  not  arise  from  a  table  column. The tree
  structure  is  visualized  via a special grid that is shown in the separator
  column  before  the  table column; the width of this column is computed from
  the  largest  nesting  depth  of files. For technical reasons, category rows
  representing  [13Xempty[0m  directories  are  realized  via  "dummy"  table rows; a
  special [10XShowTables[0m function guarantees that these rows are always hidden,
  
  When  a  data  row  or  an  entry  in this row is selected, "click" adds the
  corresponding  filename  to  the  result  list.  Initially, the first row is
  selected.  (So  if you want to search in the whole tree then you should quit
  this selection by hitting the [12Xq[0m key.)
  
  The  category  hierarchy  is  computed  using  [2XDirectoryContents[0m ([14XReference:
  DirectoryContents[0m).
  
  This  function  is  available  only  if  the [5XGAP[0m package [5XIO[0m (see [Neu07]) is
  available,  because  the  check  for  cycles  uses the function [2XIO_stat[0m ([14XIO:
  IO_stat[0m) from this package.
  
  The code can be found in the file [11Xapp/filetree.g[0m of the package.
  
  
  [1X6.9 A Puzzle[0X
  
  We  consider  an m by n rectangle of squares numbered from 1 to m n - 1, the
  bottom  right  square  is  left  empty. The numbered squares are permuted by
  successively  exchanging the empty square and a neighboring square such that
  in the end, the empty cell is again in the bottom right corner.
  
      ---------------------
      | 7  | 13 | 14 | 2  | 
      ---------------------
      | 1  | 4  | 15 | 11 | 
      ---------------------
      | 6  | 8  | 3  | 9  | 
      ---------------------
      | 10 | 5  | 12 |    | 
      ---------------------
  
  The aim of the game is to order the numbered squares via these moves.
  
  For  the  case  m  =  n  = 4, the puzzle is known under the name "Sam Loyd's
  Fifteen", see [Bog] and [OR] for more information and references.
  
  [1X6.9-1 BrowsePuzzle[0m
  
  [2X> BrowsePuzzle( [0X[3X[m, n[, pi]][0X[2X ) _____________________________________[0Xfunction
  [6XReturns:[0X  a record describing the initial and final status of the puzzle.
  
  This function shows the rectangle in a window.
  
  The  arguments  [3Xm[0m and [3Xn[0m are the dimensions of the rectangle, the default for
  both values is 4. The initial distribution of the numbers in the squares can
  be  prescribed  via a permutation [3Xpi[0m, the default is a random element in the
  alternating  group on the points 1, 2, ..., [3Xm[0m [3Xn[0m - 1. (Note that the game has
  not always a solution.)
  
  In  any  case, the empty cell is selected, and the selection can be moved to
  neighboring  cells  via  the  arrow keys, or to any place in the same row or
  column via a mouse click.
  
  The  return  value  is a record with the components [10Xdim[0m (the pair [10X[ m, n ][0m),
  [10Xinit[0m  (the  initial  permutation),  [10Xfinal[0m (the final permutation), and [10Xsteps[0m
  (the number of transpositions that were needed).
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> BrowseData.SetReplay( Concatenation([0X
    [4X>        BrowsePuzzleSolution.steps, "Q" ) );[0X
    [4Xgap> BrowsePuzzle( 4, 4, BrowsePuzzleSolution.init );;[0X
    [4Xgap> BrowseData.SetReplay( false );[0X
  [4X------------------------------------------------------------------[0X
  
  An implementation using only mouse clicks but no key strokes is available in
  the [5XGAP[0m package [5XXGAP[0m (see [CN04]).
  
  [13XImplementation  remarks[0m:  The  game board is implemented via a browse table,
  without  row  and  column  labels,  with  static header, dynamic footer, and
  individual  [10Xminyx[0m  function.  Only  one  mode is needed in which one cell is
  selected,  and  besides  the standard actions for quitting the table, asking
  for  help,  and  saving the current window contents, only the four moves via
  the arrow keys and mouse clicks are admissible.
  
  Some   standard   [2XNCurses.BrowseGeneric[0m   ([14X4.3-1[0m)   functionality,  such  as
  scrolling, selecting, and searching, are not available in this application.
  
  The code can be found in the file [11Xapp/puzzle.g[0m of the package.
  
  
  [1X6.10 Peg Solitaire[0X
  
  Peg  solitaire  is  a  board game for one player. The game board consists of
  several  holes some of which contain pegs. In each step of the game, one peg
  is  moved  horizontally  or  vertically to an empty hole at distance two, by
  jumping over a neighboring peg which is then removed from the board.
  
                -------------
                | o | o | o |
                -------------
                | o | o | o |
        -----------------------------
        | o | o | o | o | o | o | o |
        -----------------------------
        | o | o | o |   | o | o | o |
        -----------------------------
        | o | o | o | o | o | o | o |
        -----------------------------
                | o | o | o |
                -------------
                | o | o | o |
                -------------
  
  We  consider  the game that in the beginning, exactly one hole is empty, and
  in the end, exactly one peg is left.
  
  [1X6.10-1 PegSolitaire[0m
  
  [2X> PegSolitaire( [0X[3X[format, ][nrholes, ][twoModes][0X[2X ) __________________[0Xfunction
  
  This function shows the game board in a window.
  
  If  the  argument [3Xformat[0m is one of the strings [10X"small"[0m or [10X"large"[0m then small
  or large pegs are shown, the default is [10X"small"[0m.
  
  Three  shapes  of  the  game board are supported, with 33, 37, and 45 holes,
  respectively;  this  number  can  be specified via the argument [3Xnrholes[0m, the
  default  is  33.  In  the cases of 33 and 45 holes, the position of both the
  initial  hole  and  the  destination  of  the  final peg is the middle cell,
  whereas  in  the  case  of  37  holes,  the  initial hole is in the top left
  position and the final peg has to be placed in the bottom right position.
  
  If a Boolean [3XtwoModes[0m is entered as an argument then it determines whether a
  browse  table  with  one  or  two  modes is used; the default [9Xfalse[0m yields a
  browse table with only one mode.
  
  In  any  case,  one  cell of the board is selected, and the selection can be
  moved  to  neighboring  cells via the arrow keys. A peg in the selected cell
  jumps  over  a neighboring peg to an adjacent hole via the [10Xj[0m key followed by
  the appropriate arrow key.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> for n in [ 33, 37, 45 ] do[0X
    [4X>      BrowseData.SetReplay( Concatenation([0X
    [4X>          PegSolitaireSolutions.( String( n ) ), "Q" ) );[0X
    [4X>      PegSolitaire( n );[0X
    [4X> od;[0X
    [4Xgap> BrowseData.SetReplay( false );[0X
  [4X------------------------------------------------------------------[0X
  
  For  more  information  such  as  variations  of  the  game  and references,
  see [Köla].  Also the solutions stored in the variable [10XPegSolitaireSolutions[0m
  have been taken from this web page.
  
  [13XImplementation  remarks[0m:  The  game board is implemented via a browse table,
  without  row  and  column  labels,  with  static header, dynamic footer, and
  individual  [10Xminyx[0m  function.  In fact, two implementations are provided. The
  first  one  needs  only  one  mode in which one cell is selected; moving the
  selection  and  jumping with the peg in the selected cell in one of the four
  directions  are  the supported user actions. The second implementation needs
  two modes, one for moving the selection and one for jumping.
  
  Some   standard   [2XNCurses.BrowseGeneric[0m   ([14X4.3-1[0m)   functionality,  such  as
  scrolling, selecting, and searching, are not available in this application.
  
  The code can be found in the file [11Xapp/solitair.g[0m of the package.
  
  
  [1X6.11 Rubik's Cube[0X
  
  We  visualize  the  transformations of Rubik's magic cube in a model that is
  given by "unfolding" the faces and numbering them as follows.
  
                     +--------------+
                     |  1    2    3 |
                     |  4   top   5 |
                     |  6    7    8 |
      +--------------+--------------+--------------+--------------+
      |  9   10   11 | 17   18   19 | 25   26   27 | 33   34   35 |
      | 12  left  13 | 20 front  21 | 28 right  29 | 36  back  37 |
      | 14   15   16 | 22   23   24 | 30   31   32 | 38   39   40 |
      +--------------+--------------+--------------+--------------+
                     | 41   42   43 |
                     | 44  down  45 |
                     | 46   47   48 |
                     +--------------+
  
  Clockwise  turns of the six layers (top, left, front, right, back, and down)
  are represented by the following permutations.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> cubegens := [[0X
    [4X>   ( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19),[0X
    [4X>   ( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35),[0X
    [4X>   (17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11),[0X
    [4X>   (25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24),[0X
    [4X>   (33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27),[0X
    [4X>   (41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)[0X
    [4X> ];;[0X
  [4X------------------------------------------------------------------[0X
  
  [5XGAP[0m  computations  analyzing  this  permutation  group have been part of the
  announcements of [5XGAP[0m 3 releases. For a [5XGAP[0m 4 equivalent, see [Sch]. For more
  information and references (not [5XGAP[0m related) about Rubik's cube, see [Kölb].
  
  [1X6.11-1 BrowseRubiksCube[0m
  
  [2X> BrowseRubiksCube( [0X[3X[format, ][pi][0X[2X ) _______________________________[0Xfunction
  
  This function shows the model of the cube in a window.
  
  If  the  argument [3Xformat[0m is one of the strings [10X"small"[0m or [10X"large"[0m then small
  or large cells are shown, the default is [10X"small"[0m.
  
  The  argument  [3Xpi[0m  is the initial permutation of the faces, the default is a
  random permutation in the cube group, see [14X'Reference: Random'[0m.
  
  Supported  user inputs are the keys [12Xt[0m, [12Xl[0m, [12Xf[0m, [12Xr[0m, [12Xb[0m, and [12Xd[0m for clockwise turns
  of   the   six   layers,   and   the   corresponding   capital  letters  for
  counter-clockwise  turns.  If the terminal supports colors, according to the
  global  variable  [2XNCurses.attrs.has_colors[0m  ([14X2.2-1[0m),  the  input  [12Xs[0m switches
  between  a  screen that shows only the colors of the faces and a screen that
  shows the numbers; the color screen is the default.
  
  The return value is a record with the components [10Xinputs[0m (a string describing
  the  user inputs), [10Xinit[0m, and [10Xfinal[0m (the initial and final permutation of the
  faces,  respectively).  (The  [10Xinputs[0m  component  can  be used for the replay
  feature, see the example below.)
  
  In  the  following  example,  a  word  in terms of the generators is used to
  initialize the browse table, and then the letters in this word are used as a
  series  of input steps, except that in between, the display is switched once
  from colors to numbers and back.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> choice:= List( [ 1 .. 30 ], i -> Random( [ 1 .. 6 ] ) );;[0X
    [4Xgap> input:= List( "tlfrbd", INT_CHAR ){ choice };;[0X
    [4Xgap> BrowseData.SetReplay( Concatenation([0X
    [4X>        input{ [ 1 .. 20 ] },[0X
    [4X>        "s",                    # switch to number display[0X
    [4X>        input{ [ 21 .. 25 ] },[0X
    [4X>        "s",                    # switch to color display[0X
    [4X>        input{ [ 26 .. 30 ] },[0X
    [4X>        "Q" ) );;               # quit the browse table[0X
    [4Xgap> BrowseRubiksCube( Product( cubegens{ choice } ) );;[0X
    [4Xgap> BrowseData.SetReplay( false );[0X
  [4X------------------------------------------------------------------[0X
  
  [13XImplementation  remarks[0m: The cube is implemented via a browse table, without
  row  and  column  labels, with static header, dynamic footer, and individual
  [10Xminyx[0m  function.  Only  one mode is needed, and besides the standard actions
  for  quitting  the  table,  asking  for  help, and saving the current window
  contents,  only  the  twelve  moves  and the switch between color and number
  display are admissible.
  
  Switching  between  the  two  display  formats is implemented via a function
  [10Xwork.Main[0m, so this relies on [13Xnot[0m caching the formatted cells in [10Xwork.main[0m.
  
  Row  and  column separators of the browse table are whitespace of height and
  width  one.  The  separating lines are drawn using an individual [10XSpecialGrid[0m
  function  in  the  browse  table. Note that the relevant cells do not form a
  rectangular array.
  
  Some   standard   [2XNCurses.BrowseGeneric[0m   ([14X4.3-1[0m)   functionality,  such  as
  scrolling, selecting, and searching, are not available in this application.
  
  The code can be found in the file [11Xapp/rubik.g[0m of the package.
  
  
  [1X6.12 Changing Sides[0X
  
  We  consider  a  5 by 5 board of squares filled with two types of stones, as
  follows. The square in the middle is left empty.
  
             ---------------------
             | x | x | x | x | x |
             ---------------------
             | o | x | x | x | x |
             ---------------------
             | o | o |   | x | x |
             ---------------------
             | o | o | o | o | x |
             ---------------------
             | o | o | o | o | o |
             ---------------------
  
  The aim of the game is to exchange the two types of stones via a sequence of
  single  steps  that  move one stone to the empty position on the board. Only
  those  moves  are  allowed that increase or decrease one coordinate by 2 and
  increase  or  decrease  the  other  by 1; these are the allowed moves of the
  knight in chess.
  
  This game has been part of the MacTutor system [OR00].
  
  [1X6.12-1 BrowseChangeSides[0m
  
  [2X> BrowseChangeSides( [0X[3X[0X[2X ) ____________________________________________[0Xfunction
  
  This function shows the game board in a window.
  
  Each  move  is  encoded  as  a  sequence  of  three arrow keys; there are 24
  admissible inputs.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> for entry in BrowseChangeSidesSolutions do[0X
    [4X>      BrowseData.SetReplay( Concatenation( entry, "Q" ) );[0X
    [4X>      BrowseChangeSides();[0X
    [4X> od;[0X
    [4Xgap> BrowseData.SetReplay( false );[0X
  [4X------------------------------------------------------------------[0X
  
  [13XImplementation  remarks[0m:  The  game board is implemented via a browse table,
  without  row  and  column  labels,  with  static header, dynamic footer, and
  individual [10Xminyx[0m function. Only one mode is needed, and besides the standard
  actions  for  quitting  the  table,  asking for help, and saving the current
  window  contents,  only  moves  via  combinations of the four arrow keys are
  admissible.
  
  The  separating  lines are drawn using an individual [10XSpecialGrid[0m function in
  the browse table.
  
  Some   standard   [2XNCurses.BrowseGeneric[0m   ([14X4.3-1[0m)   functionality,  such  as
  scrolling, selecting, and searching, are not available in this application.
  
  The code can be found in the file [11Xapp/knight.g[0m of the package.
  
  
  [1X6.13 Sudoku[0X
  
  We  consider  a  9  by 9 board of squares. Some squares are initially filled
  with  numbers  from 1 to 9. The aim of the game is to fill the empty squares
  in  such  a  way  that  each row, each column, and each of the marked 3 by 3
  subsquares contains all numbers from 1 to 9. A [13Xproper Sudoku game[0m is defined
  as one with a unique solution. Here is an example.
  
                   ------------- ------------- -------------
                   |   |   |   | |   |   |   | | 5 |   |   |
                   ------------- ------------- -------------
                   |   | 1 | 5 | | 4 |   | 6 | |   | 2 |   |
                   ------------- ------------- -------------
                   | 9 |   |   | |   | 5 |   | | 3 |   |   |
                   ------------- ------------- -------------
                   ------------- ------------- -------------
                   | 6 |   | 4 | |   |   |   | |   |   |   |
                   ------------- ------------- -------------
                   |   |   |   | | 8 |   |   | |   |   |   |
                   ------------- ------------- -------------
                   | 8 |   |   | | 9 |   |   | |   | 5 | 3 |
                   ------------- ------------- -------------
                   ------------- ------------- -------------
                   |   |   |   | |   |   | 5 | |   |   |   |
                   ------------- ------------- -------------
                   |   | 4 |   | |   |   | 7 | |   |   | 2 |
                   ------------- ------------- -------------
                   |   |   | 9 | | 1 |   |   | | 8 |   |   |
                   ------------- ------------- -------------
  
  The [5XBrowse[0m package contains functions to create, play and solve these games.
  There  are  basic  command line functions for this, which we describe first,
  and there is a user interface [2XPlaySudoku[0m ([14X6.13-7[0m) which is implemented using
  the generic browse functionality described in Chapter [14X4[0m.
  
  [1X6.13-1 Sudoku.Init[0m
  
  [2X> Sudoku.Init( [0X[3X[arg][0X[2X ) _____________________________________________[0Xfunction
  [6XReturns:[0X  A record describing a Sudoku board or [9Xfail[0m.
  
  This  function constructs a record describing a Sudoku game. This is used by
  the  other  functions described below. There a several possibilities for the
  argument [3Xarg[0m.
  
  [8X[3Xarg[0m[8X is a string[0m
        The  entries  of  a Sudoku board are numbered row-wise from 1 to 81. A
        board  is encoded as a string as follows. If one of the numbers 1 to 9
        is  in  entry  i  then the corresponding digit character is written in
        position  i  of the string. If an entry is empty any character, except
        [10X'1'[0m  to  [10X'9'[0m  or  [10X'|'[0m is written in position i of the string. Trailing
        empty  entries  can  be  left  out.  Afterwards  [10X'|'[0m-characters can be
        inserted  in  the string (for example to mark line ends). Such strings
        can be used for [3Xarg[0m.
  
  [8X[3Xarg[0m[8X is a matrix[0m
        A  Sudoku board can also be encoded as a 9 by 9-matrix, that is a list
        of  9 lists of length 9, whose (i,j)-th entry is the (i,j)-th entry of
        the  board  as  integer if it is not empty. Empty entries of the board
        correspond to unbound entries in the matrix.
  
  [8X[3Xarg[0m[8X is a list of integers[0m
        Instead of the matrix just described the argument can also be given by
        the  concatenation  of  the rows of the matrix (so, a list of integers
        and holes).
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\[0X
    [4X>  6  47   |45  2    |89   2 1 | 4   8 7 | ");;[0X
  [4X------------------------------------------------------------------[0X
  
  [1X6.13-2 Sudoku.Place[0m
  
  [2X> Sudoku.Place( [0X[3Xgame, i, n[0X[2X ) _______________________________________[0Xfunction
  [2X> Sudoku.Remove( [0X[3Xgame, i[0X[2X ) _________________________________________[0Xfunction
  [6XReturns:[0X  The changed [3Xgame[0m.
  
  Here  [3Xgame[0m is a record describing a Sudoku board, as returned by [2XSudoku.Init[0m
  ([14X6.13-1[0m).  The argument [3Xi[0m is the number of an entry, counted row-wise from 1
  to  81,  and  [3Xn[0m  is  an integer from 1 to 9 to be placed on the board. These
  functions change [3Xgame[0m.
  
  [2XSudoku.Place[0m  tries  to place number [3Xn[0m on entry [3Xi[0m. It is an error if entry [3Xi[0m
  is  not  empty.  The  number  is not placed if [3Xn[0m is already used in the row,
  column  or  subsquare of entry [3Xi[0m. In this case the component [10Xgame.impossible[0m
  is bound.
  
  [2XSudoku.Remove[0m  tries to remove the number placed on position [3Xi[0m of the board.
  It  does  not  change the board if entry [3Xi[0m is empty, or if entry [3Xi[0m was given
  when  the  board  [3Xgame[0m  was  created.  In the latter case [10Xgame.impossible[0m is
  bound.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\[0X
    [4X>  6  47   |45  2    |89   2 1 | 4   8 7 | ");;[0X
    [4Xgap> Sudoku.Place(game, 1, 3);; # 3 is already in first row[0X
    [4Xgap> IsBound(game.impossible);[0X
    [4Xtrue[0X
    [4Xgap> Sudoku.Place(game, 1, 2);; # 2 is not in row, col or subsquare[0X
    [4Xgap> IsBound(game.impossible);[0X
    [4Xfalse[0X
  [4X------------------------------------------------------------------[0X
  
  [1X6.13-3 Sudoku.RandomGame[0m
  
  [2X> Sudoku.RandomGame( [0X[3X[seed][0X[2X ) ______________________________________[0Xfunction
  [6XReturns:[0X  A pair [10X[str, seed][0m of string and seed.
  
  The  optional argument [3Xseed[0m, if given, must be an integer. If not given some
  random integer from the current [5XGAP[0m session is used. This function returns a
  random  proper Sudoku game, where the board is described by a string [10Xstr[0m, as
  explained  in  [2XSudoku.Init[0m  ([14X6.13-1[0m).  With  the same [3Xseed[0m the same board is
  returned.
  
  The  games  computed  by this function have the property that after removing
  any given entry the puzzle does no longer have a unique solution.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> Sudoku.RandomGame(5833750);[0X
    [4X[ " 1         2     43  2   68   72    8     6 2   1 9 8  8 3   \[0X
    [4X9     47 3   7  18  ", 5833750 ][0X
    [4Xgap> last = Sudoku.RandomGame(last[2]);[0X
    [4Xtrue[0X
  [4X------------------------------------------------------------------[0X
  
  [1X6.13-4 Sudoku.SimpleDisplay[0m
  
  [2X> Sudoku.SimpleDisplay( [0X[3Xgame[0X[2X ) _____________________________________[0Xfunction
  
  Displays  a Sudoku board on the terminal. (But see [2XPlaySudoku[0m ([14X6.13-7[0m) for a
  fancier interface.)
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\[0X
    [4X>  6  47   |45  2    |89   2 1 | 4   8 7 | ");;[0X
    [4Xgap> Sudoku.SimpleDisplay(game);[0X
    [4X 3 |  6|8  [0X
    [4X 85|  1| 69[0X
    [4X  9|7  | 53[0X
    [4X-----------[0X
    [4X   |   |79 [0X
    [4X 6 | 47|   [0X
    [4X45 | 2 |   [0X
    [4X-----------[0X
    [4X89 |  2| 1 [0X
    [4X 4 |  8| 7 [0X
    [4X   |   |   [0X
  [4X------------------------------------------------------------------[0X
  
  [1X6.13-5 Sudoku.OneSolution[0m
  
  [2X> Sudoku.OneSolution( [0X[3Xgame[0X[2X ) _______________________________________[0Xfunction
  [6XReturns:[0X  A completed Sudoku board that solves [3Xgame[0m, or [9Xfail[0m.
  
  Here  [3Xgame[0m must be a Sudoku board as returned by [2XSudoku.Init[0m ([14X6.13-1[0m). It is
  not  necessary  that  [3Xgame[0m  describes  a  proper  Sudoku  game (has a unique
  solution).  It  may  have  several  solutions,  then  one random solution is
  returned. Or it may have no solution, then [9Xfail[0m is returned.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> Sudoku.SimpleDisplay(Sudoku.OneSolution(Sudoku.Init("  3")));[0X
    [4X493|876|251[0X
    [4X861|542|739[0X
    [4X527|193|648[0X
    [4X-----------[0X
    [4X942|618|573[0X
    [4X156|739|482[0X
    [4X738|425|916[0X
    [4X-----------[0X
    [4X289|354|167[0X
    [4X375|961|824[0X
    [4X614|287|395[0X
  [4X------------------------------------------------------------------[0X
  
  [1X6.13-6 Sudoku.UniqueSolution[0m
  
  [2X> Sudoku.UniqueSolution( [0X[3Xgame[0X[2X ) ____________________________________[0Xfunction
  [6XReturns:[0X  A completed Sudoku board that solves [3Xgame[0m, or [9Xfalse[0m, or [9Xfail[0m.
  
  Here  [3Xgame[0m must be a Sudoku board as returned by [2XSudoku.Init[0m ([14X6.13-1[0m). It is
  not  necessary  that  [3Xgame[0m describes a proper Sudoku game. If it has several
  solutions,  then  [9Xfalse[0m  is  returned.  If  it has no solution, then [9Xfail[0m is
  returned. Otherwise a board with the unique solution is returned.
  
  [4X---------------------------  Example  ----------------------------[0X
    [4Xgap> s := "      5  | 154 6 2 |9   5 3  |6 4      |   8     |8  9   53\[0X
    [4X> |     5   | 4   7  2|  91  8  ";;[0X
    [4Xgap> sol := Sudoku.UniqueSolution(Sudoku.Init(s));;[0X
    [4Xgap> Sudoku.SimpleDisplay(sol);[0X
    [4X438|219|576[0X
    [4X715|436|928[0X
    [4X962|758|314[0X
    [4X-----------[0X
    [4X694|573|281[0X
    [4X153|862|749[0X
    [4X827|941|653[0X
    [4X-----------[0X
    [4X281|695|437[0X
    [4X546|387|192[0X
    [4X379|124|865[0X
  [4X------------------------------------------------------------------[0X
  
  [1X6.13-7 PlaySudoku[0m
  
  [2X> PlaySudoku( [0X[3X[arg][0X[2X ) ______________________________________________[0Xfunction
  [6XReturns:[0X  A record describing the latest status of a Sudoku board.
  
  This  function  allows  one to solve Sudoku puzzles interactively. There are
  several  possibilities  for  the  optional  argument [3Xarg[0m. It can either be a
  string,  matrix  or  list  of holes and integers as described in [2XSudoku.Init[0m
  ([14X6.13-1[0m),  or  a  board as returned by [2XSudoku.Init[0m ([14X6.13-1[0m). Furthermore [3Xarg[0m
  can  be  an integer or not be given, in that case [2XSudoku.RandomGame[0m ([14X6.13-3[0m)
  is called to produce a random game.
  
  The  usage of this function is self-explanatory, pressing the [12X?[0m key displays
  a  help screen. Here, we mention two keys with a particular action: Pressing
  the  [12Xh[0m  key  you  get a hint, either an empty entry is filled or the program
  tells you that there is no solution (so you must delete some entries and try
  others).  Pressing the [12Xs[0m key the puzzle is solved by the program or it tells
  you that there is no or no unique solution.
  
  [13XImplementation  remarks[0m:  The  game board is implemented via a browse table,
  without  row  and  column  labels,  with  static header, dynamic footer, and
  individual  [10Xminyx[0m  function.  Two  modes  are  supported,  with the standard
  actions  for quitting the table and asking for help; one cell is selected in
  each  mode. The first mode provides actions for moving the selected cell via
  arrow  keys, for changing the value in the selected cell, for getting a hint
  or  the  (unique) solution. (Initial entries of the matrix cannot be changed
  via  user  input.  They  are  shown in boldface.) The second mode serves for
  error handling: When the user enters an invalid number, i. e., a number that
  occurs  already  in  the  current  row  or  column  or  subsquare,  then the
  application  switches  to this mode, which causes that a message is shown in
  the  footer,  and the invalid entry is shown in red and blinking; similarly,
  error mode is entered if a hint or solution does not exist.
  
  The  separating  lines are drawn using an individual [10XSpecialGrid[0m function in
  the  browse  table, since they cannot be specified within the generic browse
  table functions.
  
  Some   standard   [2XNCurses.BrowseGeneric[0m   ([14X4.3-1[0m)   functionality,  such  as
  scrolling, selecting, and searching, are not available in this application.
  
  The code can be found in the file [11Xapp/sudoku.g[0m of the package.
  
  [1X6.13-8 Sudoku.HTMLGame[0m
  
  [2X> Sudoku.HTMLGame( [0X[3Xgame[0X[2X ) __________________________________________[0Xfunction
  [2X> Sudoku.LaTeXGame( [0X[3Xgame[0X[2X ) _________________________________________[0Xfunction
  [6XReturns:[0X  A string with HTML or LaTeX code, respectively.
  
  The  argument of these functions is a record describing a Sudoku game. These
  functions  return  code for including the current status of the board into a
  webpage or a LaTeX document.
  
