% generated by GAPDoc2LaTeX from XML source (Frank Luebeck)
\documentclass[11pt]{report}
\usepackage{a4wide}
\sloppy
\pagestyle{myheadings}
\usepackage{amssymb}
\usepackage[latin1]{inputenc}
\usepackage{makeidx}
\makeindex
\usepackage{color}
\definecolor{DarkOlive}{rgb}{0.1047,0.2412,0.0064}
\definecolor{FireBrick}{rgb}{0.5812,0.0074,0.0083}
\definecolor{RoyalBlue}{rgb}{0.0236,0.0894,0.6179}
\definecolor{RoyalGreen}{rgb}{0.0236,0.6179,0.0894}
\definecolor{RoyalRed}{rgb}{0.6179,0.0236,0.0894}
\definecolor{LightBlue}{rgb}{0.8544,0.9511,1.0000}
\definecolor{Black}{rgb}{0.0,0.0,0.0}
\definecolor{FuncColor}{rgb}{1.0,0.0,0.0}
%% strange name because of pdflatex bug:
\definecolor{Chapter }{rgb}{0.0,0.0,1.0}

\usepackage{fancyvrb}

\usepackage{pslatex}

\usepackage[
        a4paper=true,bookmarks=false,pdftitle={Written with GAPDoc},
        pdfcreator={LaTeX with hyperref package / GAPDoc},
        colorlinks=true,backref=page,breaklinks=true,linkcolor=RoyalBlue,
        citecolor=RoyalGreen,filecolor=RoyalRed,
        urlcolor=RoyalRed,pagecolor=RoyalBlue]{hyperref}

% write page numbers to a .pnr log file for online help
\newwrite\pagenrlog
\immediate\openout\pagenrlog =\jobname.pnr
\immediate\write\pagenrlog{PAGENRS := [}
\newcommand{\logpage}[1]{\protect\write\pagenrlog{#1, \thepage,}}
\newcommand{\Q}{\mathbb{Q}}
\newcommand{\R}{\mathbb{R}}
\newcommand{\C}{\mathbb{C}}
\newcommand{\Z}{\mathbb{Z}}
\newcommand{\N}{\mathbb{N}}
\newcommand{\F}{\mathbb{F}}

\newcommand{\GAP}{\textsf{GAP}}

\newsavebox{\backslashbox}
\sbox{\backslashbox}{\texttt{\symbol{92}}}
\newcommand{\bs}{\usebox{\backslashbox}}

\begin{document}

\logpage{[ 0, 0, 0 ]}
\begin{titlepage}
\begin{center}{\Huge \textbf{\textsf{Browse}}}\\[1cm]
\hypersetup{pdftitle=\textsf{Browse}}
\markright{\scriptsize \mbox{}\hfill \textsf{Browse} \hfill\mbox{}}
{( Version 0.9 ) }\\[1cm]
\mbox{}\\[2cm]
{\large \textbf{ Thomas Breuer   }}\\
{\large \textbf{ Frank Lübeck   }}\\
\hypersetup{pdfauthor= Thomas Breuer   ;  Frank Lübeck   }
\end{center}\vfill

\mbox{}\\
{\mbox{}\\
\small \noindent \textbf{ Thomas Breuer   } --- Email: \href{mailto://Thomas.Breuer@Math.RWTH-Aachen.De}{\texttt{Thomas.Breuer@Math.RWTH-Aachen.De}}\\
 --- Homepage: \href{http://www.math.rwth-aachen.de/~Thomas.Breuer}{\texttt{http://www.math.rwth-aachen.de/\~{}Thomas.Breuer}}}\\
{\mbox{}\\
\small \noindent \textbf{ Frank Lübeck   } --- Email: \href{mailto://Frank.Luebeck@Math.RWTH-Aachen.De}{\texttt{Frank.Luebeck@Math.RWTH-Aachen.De}}\\
 --- Homepage: \href{http://www.math.rwth-aachen.de/~Frank.Luebeck}{\texttt{http://www.math.rwth-aachen.de/\~{}Frank.Luebeck}}}\\
\end{titlepage}

\newpage\setcounter{page}{2}
{\small 
\section*{Copyright}
\logpage{[ 0, 0, 1 ]}
 {\copyright} 2006 by Thomas Breuer and Frank Lübeck 

 We adopt the copyright regulations of \textsf{GAP} as detailed in the copyright notice in the \textsf{GAP} manual. }\\[1cm]
\newpage

\def\contentsname{Contents\logpage{[ 0, 0, 2 ]}}

\tableofcontents
\newpage

 
\chapter{\textcolor{Chapter }{Introduction and Overview}}\label{ch:intro}
\logpage{[ 1, 0, 0 ]}
{
 
\section{\textcolor{Chapter }{Introduction}}\label{sec:intro}
\logpage{[ 1, 1, 0 ]}
{
 The motivation of the package \textsf{Browse} was to provide better functionality for displaying two-dimensional arrays of
data (e.g., character tables): moving through the data without loosing row and
column labels, searching for text, displaying extra information, hiding
information, allowing interactive user input, ... 

 We wanted to achieve this by using the capabilities of the terminal emulations
in which \textsf{GAP} is running, and not by some external graphical user interface. For this we
have chosen to use the widely available \texttt{C}-library \texttt{ncurses}, see \cite{NCursesWeb}. It contains functions to find out terminal capabilities, to change
properties of terminals, to place text, to handle several windows with
overlapping, ... To use these functions the terminal is switched to a \emph{visual mode} \index{visual mode} so that the display of the non-visual mode of your terminal in which \textsf{GAP} is running is not clobbered. 

 \textsf{Browse} has now three levels of functionality: 
\begin{description}
\item[{A low level interface to \texttt{ncurses}}] This may be interesting for all kinds of applications which want to display
text with some markup including \index{colors as text attributes}colors, maybe in several windows, using the available capabilities of a
terminal.
\item[{A medium level interface to a generic function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric})}] This is for displaying two-dimensional arrays of data, handles labels for rows
and columns, searching, sorting, binding keys to actions, ... Look here, if
you want to implement such applications for further kinds of data.
\item[{Applications of these interfaces}] We provide some applications of the \texttt{ncurses} interface and of the generic \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) function. These may be interesting for end users, and also as examples for
programmers of further applications. This includes (of course) a method for
browsing through character tables, functions for browsing through data
collections, several games,\index{game} and an interface for demos.
\end{description}
 Users interested only in these applications should perhaps just try \texttt{NCurses.Demo()}. }

 
\section{\textcolor{Chapter }{Overview}}\label{sec:overview}
\logpage{[ 1, 2, 0 ]}
{
 
\subsection{\textcolor{Chapter }{The \texttt{ncurses} interface}}\label{ssec:ov_ncurses}
\logpage{[ 1, 2, 1 ]}
{
  Chapter \ref{ch:curses} describes \textsf{GAP}'s interface to the \texttt{ncurses} \texttt{C}-library. The imported \texttt{C}-functions are shortly explained, but for further details we refer to the
documentation of that library. There are also a few utility functions on \textsf{GAP} level, such as \texttt{NCurses.SetTerm} (\ref{NCurses.SetTerm}), which simplify the use of the library. 

 The concept of an \emph{attribute line}\index{attribute line}, see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine}), helps to deal with text with markup for its display in a terminal window. 

 This chapter is for users who want to write their own applications of \texttt{ncurses}. }

 
\subsection{\textcolor{Chapter }{Applications of \texttt{ncurses}}}\label{ssec:ov_ncappl}
\logpage{[ 1, 2, 2 ]}
{
 In Chapter \ref{ch:util} we describe some interactive applications of the \texttt{ncurses} interface. For example, there is \texttt{NCurses.Select} (\ref{NCurses.Select}) for asking a user to choose one or several of a given list of items. There is
also a demo function \texttt{NCurses.Demo} (\ref{NCurses.Demo}) which we use to demonstrate features of the \textsf{Browse} package, but it may be interesting for other kinds of demos as well. }

 
\subsection{\textcolor{Chapter }{The interface to browse two-dimensional arrays}}\label{ssec:ov_genbrowse}
\logpage{[ 1, 2, 3 ]}
{
  Chapters \ref{chap:browse_user} and \ref{chap:browse_prg} describe the interface to a generic function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) which can be used for an interactive display of two-dimensional arrays of
data. The first of these covers the basic functionality which may be
sufficient for many applications and the second gives more technical details.
With interactive display we mean that it is not only possible to scroll
through the data, but one can search for strings, sort by rows or columns,
select entries, bind arbitrary actions to keys, ask for help, and more. }

 
\subsection{\textcolor{Chapter }{Applications of the generic function \texttt{NCurses.BrowseGeneric}}}\label{ssec:ov_browseappl}
\logpage{[ 1, 2, 4 ]}
{
  In Chapter \ref{ch:appl} we describe several applications which are using the generic \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) interface introduced before. They are provided as prototype applications and
so we include some implementation remarks in their documentation. 

 Users who just want to use these applications hopefully do not need to read
this \textsf{Browse} manual, all applications are coming with built-in help windows. 

 There are different kinds of applications. First, there are methods for
browsing through character tables and tables of marks (our original motivation
for this package). Then there are applications for browsing through data
collections, e.g., the data available through the \textsf{AtlasRep} package, the \textsf{GAP} bibliography or the sections of the \textsf{GAP} manuals. Finally, there are several games like Sam Loyd's fifteen puzzle
(generalized), peg solitaire, and Sudoku (including functions to create new
puzzles and to solve puzzles). }

 }

 }

 
\chapter{\textcolor{Chapter }{Interface to the \texttt{ncurses} Library}}\label{ch:curses}
\logpage{[ 2, 0, 0 ]}
{
  In this chapter we describe the \textsf{GAP} interface to the \textsf{GNU} \texttt{curses}/\texttt{ncurses} \texttt{C}-library. This library contains routines to manipulate the contents of
terminal windows. It allows one to write programs which should work on a wide
variety of terminal emulations with different sets of capabilities. 

 This technical chapter is intended for readers who want to program new
applications using the \texttt{ncurses} functionality. If you are only interested in the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) from this package or some of its applications you can skip this chapter. 

 Detailed documentation of the \texttt{ncurses} library is probably available in your operating system (try \texttt{man ncurses}) and from the web (see for example \cite{NCursesWeb}). Here, we only give short reminders about the functions provided in the \textsf{GAP} interface and explain how to use the \textsf{GAP} functions. 
\section{\textcolor{Chapter }{The \texttt{ncurses} Library}}\label{sec:cursesC}
\logpage{[ 2, 1, 0 ]}
{
 In this section we list the functions from the GNU \texttt{ncurses} library and its \texttt{panel} extension which are made available in \textsf{GAP} via the \textsf{Browse} package. See the following section \ref{sec:cursesGAP} for explanations how to use these functions from within \textsf{GAP}. 

 The basic objects to manipulate are called \emph{windows}, they correspond to rectangular regions of the terminal screen. Windows can
overlap but \texttt{ncurses} cannot handle this for the display. Therefore windows can be wrapped in \emph{panels}, they provide a display depth for windows and it is possible to move panels
to the top and bottom of the display or to hide a panel. 

 We will not import all the functions of the \texttt{ncurses} library to \textsf{GAP}. For example, there are many pairs of functions with the same name except for
a leading \texttt{w} (like \texttt{move} and \texttt{wmove} for moving the cursor in a window). Here, we only import the versions with \texttt{w}, which get a window as first argument. The functions without \texttt{w} are for the \texttt{ncurses} standard screen window \texttt{stdscr} which is available as window \texttt{0} in \textsf{GAP}. Similarly, there are functions with the same name except for an extra \texttt{n} (like \texttt{waddstr} and \texttt{waddnstr} for placing a string into a window). Here, we only import the safer functions
with \texttt{n} which get the number of characters to write as argument. (More convenient
functions are then implemented on the \textsf{GAP} level.) 
\subsection{\textcolor{Chapter }{Setting the terminal}}\label{ssec:ncursesTermset}
\logpage{[ 2, 1, 1 ]}
{
  We first list flags for setting the basic behavior of a terminal. With \texttt{savetty}/\texttt{resetty} a setting can be stored and recovered. 
\begin{description}
\item[{\texttt{savetty()}}] This stores the current setting of the terminal in a buffer.
\item[{\texttt{resetty()}}] This resets the terminal to what was stored in the last call to \texttt{savetty}.
\item[{\texttt{cbreak()/nocbreak()}}] In \texttt{cbreak} mode each input character from a terminal is directly forwarded to the
application (but see \texttt{keypad}). With \texttt{nocbreak} this only happens after a newline or return is typed.
\item[{\texttt{keypad(win, bool)}}] If set to \texttt{true} some special input like arrow or function keys can be read as single
characters from the input (such keys actually generate certain sequences of
characters), see also \ref{ssec:ncursesInput}. (The \mbox{\texttt{win}} argument is irrelevant.)
\item[{\texttt{echo()}/\texttt{noecho()}}] This determines if input characters are automatically echoed by the terminal
at the current cursor position.
\item[{\texttt{curs{\textunderscore}set(vis)}}] This determines the visibility of the cursor. The argument \mbox{\texttt{vis}}=0 makes the cursor invisible. With \mbox{\texttt{vis}}=1 it becomes visible; some terminals allow also higher levels of visibility.
\item[{\texttt{wtimeout(win, delay)}}] Here \mbox{\texttt{delay}} determines a timeout in milliseconds for reading characters from the input of
a window. Negative values mean infinity, that is a blocking read.
\item[{\texttt{nl()}/\texttt{nonl()}}] With \texttt{nl} a return on input is translated to a newline character and a newline on output
is interpreted as return and linefeed.
\item[{\texttt{intrflush(win, bool)}}] This flag determines if after an interrupt pending output to the terminal is
flushed. (The \mbox{\texttt{win}} argument is irrelevant.)
\item[{\texttt{idlok(win, bool)}}] With \texttt{true} the library tries to use a hardware line insertion functionality (in
particular for scrolling).
\item[{\texttt{scrollok(win, bool)}}] If set to \texttt{true} moving the cursor down from the last line of a window causes scrolling of the
whole window, otherwise nothing happens.
\item[{\texttt{leaveok(win, bool)}}] If set to \texttt{true} a refresh of the window leaves the cursor at its current location, otherwise
this is not guaranteed.
\item[{\texttt{clearok(win, bool)}}] If set to \texttt{true} the next refresh of the window will clear the screen completely and redraw
everything.
\item[{\texttt{immedok(win, bool)}}] If set to \texttt{true} all changes of the window will automatically also call a \texttt{wrefresh}.
\item[{\texttt{raw()}/\texttt{noraw()}}] Similar to \texttt{cbreak}, usually not needed (see the \texttt{ncurses} documentation for details).
\end{description}
 }

 
\subsection{\textcolor{Chapter }{Manipulating windows}}\label{ssec:ncursesWin}
\logpage{[ 2, 1, 2 ]}
{
  In \texttt{ncurses} an arbitrary number of windows which correspond to rectangular regions (maybe
overlapping) of the screen can be handled. You should always delete windows
which are no longer needed. To get a proper display of overlapping windows
(which may occur by recursively called functions using this library) we
suggest that you always wrap windows in panels, see \ref{ssec:ncursesPan}. 

 For functions which involve coordinates recall that the upper left corner of
the screen or internally of any window has the coordinates (0,0). 
\begin{description}
\item[{\texttt{newwin(nlines, ncols, y, x)}}] This creates a new window whose upper left corner has the coordinates (\mbox{\texttt{y}},\mbox{\texttt{x}}) on the screen and has \mbox{\texttt{nlines}} lines and \mbox{\texttt{ncols}} columns, if this is possible. The arguments \mbox{\texttt{nlines}} and \mbox{\texttt{ncols}} can be zero, then their maximal possible values are assumed.
\item[{\texttt{delwin(win)}}] Deletes a window.
\item[{\texttt{mvwin(win, y, x)}}] Moves the upper left corner of the window to the given coordinates, if the
window still fits on the screen. With panels don't use this function, but use \texttt{move{\textunderscore}panel} mentioned below.
\item[{\texttt{wrefresh(win)}}] Writing to a window only changes some internal buffers, this function copies
the window content to the actual display screen. You don't need this function
if you wrap your windows in panels, use \texttt{update{\textunderscore}panels} and \texttt{doupdate} instead.
\item[{\texttt{doupdate()}}] Use this function to update the content of your display screen to the current
content of all windows. If your terminal is not yet in visual mode this
function changes to visual mode.
\item[{\texttt{endwin()}}] Use this function to leave the visual mode of your terminal.
\item[{\texttt{getbegyx(win)}}] Get the coordinates of the upper left corner of a window on the screen.
\item[{\texttt{getmaxyx(win)}}] Get the number of lines and columns of a window.
\end{description}
 }

 
\subsection{\textcolor{Chapter }{Manipulating panels}}\label{ssec:ncursesPan}
\logpage{[ 2, 1, 3 ]}
{
  Wrap windows in panels to get a proper handling of overlapping windows on the
display. Don't forget to delete a panel before deleting the corresponding
window. 
\begin{description}
\item[{\texttt{new{\textunderscore}panel(win)}}] Create a panel for a window.
\item[{\texttt{del{\textunderscore}panel(pan)}}] Delete a panel.
\item[{\texttt{update{\textunderscore}panels()}}] Use this function to copy changes of windows and panels to a screen buffer.
Then call \texttt{doupdate()} to update the display screen.
\item[{\texttt{move{\textunderscore}panel(pan, y, x)}}] Move top left corner of a panel wrapped window to coordinates (\mbox{\texttt{y}},\mbox{\texttt{x}}) if possible.
\item[{\texttt{hide{\textunderscore}panel(pan)}/\texttt{show{\textunderscore}panel(pan)}}] Hide or show, respectively, the content of a panel on the display screen.
\item[{\texttt{top{\textunderscore}panel(pan)}/\texttt{bottom{\textunderscore}panel(pan)}}] Move a panel to the top or bottom of all panels, respectively.
\item[{\texttt{panel{\textunderscore}below(pan)}/\texttt{panel{\textunderscore}above(pan)}}] Return the panel directly below or above the given one, respectively.
\end{description}
 }

 
\subsection{\textcolor{Chapter }{Getting keyboard input}}\label{ssec:ncursesInput}
\logpage{[ 2, 1, 4 ]}
{
  If you want to read input from the user first adjust the terminal settings of \texttt{cbreak}, \texttt{keypad}, \texttt{echo}, \texttt{wtimeout} and \texttt{curs{\textunderscore}set} to your needs, see \ref{ssec:ncursesTermset}. The basic functions are as follows. 
\begin{description}
\item[{\texttt{wgetch(win)}}] Reads one character from user input (returned as integer). If \texttt{wtimeout} was set with a positive \mbox{\texttt{delay}} then the function returns \texttt{false} if there was no input for \mbox{\texttt{delay}} milliseconds. Note that in \texttt{nocbreak} mode typed characters reach the application only after typing a return. If the \texttt{keypad} flag is set to \texttt{true} some special keys can be read like single characters; the keys are explained
below. (Note that there is only one input queue for all windows.)
\item[{\texttt{ungetch(char)}}] Puts back the character \mbox{\texttt{char}} on the input queue.
\end{description}
 Some terminals allow one to read special keys like one character, we import
some of the symbolic names of such keys into \textsf{GAP}. You can check for such characters by comparing with the components of the
record \texttt{NCurses.keys}, these are 
\begin{description}
\item[{\texttt{UP}/\texttt{DOWN}/\texttt{LEFT}/\texttt{RIGHT}}] the arrow keys
\item[{\texttt{PPAGE}/\texttt{NPAGE}}] the page up and page down keys
\item[{\texttt{HOME}/\texttt{END}}] the home and end keys
\item[{\texttt{BACKSPACE}/\texttt{DC}}] the backspace and delete keys
\item[{\texttt{IC}}] the insert key
\item[{\texttt{ENTER}}] the enter key
\item[{\texttt{F1}/\texttt{F2}/../\texttt{F24}}] the function keys
\item[{\texttt{MOUSE}}] a pseudo key to detect mouse events
\item[{\texttt{A1}/\texttt{A3}/\texttt{B2}/\texttt{C1}/\texttt{C3}}] the keys around the arrow keys on a num pad
\end{description}
 It can happen that on a specific keyboard there is no key for some of these.
Also, not all terminals can interpret all of these keys. You can check this
with the function 
\begin{description}
\item[{\texttt{has{\textunderscore}key(key)}}] Checks if the special key \mbox{\texttt{key}} is recognized by the terminal.
\end{description}
 }

 
\subsection{\textcolor{Chapter }{Writing to windows}}\label{ssec:ncursesWrite}
\logpage{[ 2, 1, 5 ]}
{
  The display of text in \texttt{ncurses} windows has two aspects. The first is to get actual characters on the screen.
The second is to specify attributes which influence the display, for example
normal or bold fonts or colors. This subsection is for the first aspect.
Possible attributes are explained below in \ref{ssec:ncursesAttrs}. 
\begin{description}
\item[{\texttt{wmove(win, y, x)}}] Moves the cursor to position (\mbox{\texttt{y}},\mbox{\texttt{x}}), recall that the coordinates are zero based, (0,0) being the top left
corner.
\item[{\texttt{waddnstr(win, str, len)}}] Writes the string \mbox{\texttt{str}} to the window starting from the current cursor position. Writes at most \mbox{\texttt{len}} characters. At end of line the cursor moves to the beginning of next line. The
behavior at the end of the window depends on the setting of \texttt{scrollok}, see \ref{ssec:ncursesTermset}.
\item[{\texttt{waddch(win, char)}}] Writes a character to the window at the current cursor position and moves the
cursor on. The character \mbox{\texttt{char}} is given as integer and can include attribute information.
\item[{\texttt{wborder(win, charlist)}}] Draws a border around the window. If \mbox{\texttt{charlist}} is a plain list of eight \textsf{GAP} characters these are taken for left/right/top/bottom sides and
top-left/top-right/bottom-left/bottom-right corners. Otherwise default
characters are used. (See \texttt{NCurses.WBorder} (\ref{NCurses.WBorder}) for a more user friendly interface.) 
\item[{\texttt{wvline(win, char, len)}}] Writes a vertical line of length \mbox{\texttt{len}} (or as long as fitting into the window) starting from the current cursor
position to the bottom, using the character \mbox{\texttt{char}}. If \mbox{\texttt{char}}=\texttt{0} the default character is used.
\item[{\texttt{whline(win, char, len)}}] Same as \texttt{wvline} but for horizontal lines starting from the cursor position to the right.
\item[{\texttt{werase(win)}}] Deletes all characters in the window.
\item[{\texttt{wclear(win)}}] Like \texttt{werase}, but also calls \texttt{clearok}.
\item[{\texttt{wclrtobot(win)}}] Deletes all characters from cursor position to the right and bottom.
\item[{\texttt{wclrtoeol(win)}}] Deletes all characters from cursor position to end of line.
\item[{\texttt{winch(win)}}] Returns the character at current cursor position, as integer and including
color and attribute information.
\item[{\texttt{getyx(win)}}] Returns the current cursor position.
\item[{\texttt{waddstr(win, str)}}] Delegates to \texttt{waddnstr(win, str, Length(str))}.
\end{description}
 }

 
\subsection{\textcolor{Chapter }{Line drawing characters}}\label{ssec:ncursesLines}
\logpage{[ 2, 1, 6 ]}
{
  For drawing lines and grids in a terminal window you should use some "virtual"
characters which are available as components of the record \texttt{NCurses.lineDraw}. On some terminals these are nicely displayed as proper lines (on others they
are simulated by ASCII characters). These are: 
\begin{description}
\item[{\texttt{BLOCK}}] solid block
\item[{\texttt{BOARD}}] board of squares
\item[{\texttt{BTEE/LTEE/RTEE/TTEE}}] bottom/left/right/top tee
\item[{\texttt{BULLET}}] bullet
\item[{\texttt{CKBOARD}}] checker board
\item[{\texttt{DARROW/LARROW/RARROW/UARROW}}] down/left/right/up arrow
\item[{\texttt{DEGREE}}] degree symbol
\item[{\texttt{DIAMOND}}] diamond
\item[{\texttt{GEQUAL}}] greater than or equal
\item[{\texttt{HLINE/VLINE}}] horizontal/vertical line
\item[{\texttt{LANTERN}}] lantern symbol
\item[{\texttt{LEQUAL}}] less than or equal
\item[{\texttt{LLCORNER/LRCORNER/ULCORNER/URCORNER}}] lower left/lower right/upper left/upper right corner
\item[{\texttt{NEQUAL}}] not equal
\item[{\texttt{PI}}] letter pi
\item[{\texttt{PLMINUS}}] plus-minus
\item[{\texttt{PLUS}}] crossing lines like a plus
\item[{\texttt{S1/S3/S7/S9}}] scan line 1/3/7/9
\item[{\texttt{STERLING}}] pound sterling
\end{description}
 }

 
\subsection{\textcolor{Chapter }{Text attributes and colors}}\label{ssec:ncursesAttrs}
\logpage{[ 2, 1, 7 ]}
{
  In addition to the actual characters to be written to the screen the way they
are displayed can be changed by additional \emph{attributes}. \index{attributes of text} (There should be no danger to mix up this notion of attributes with the one
introduced in~ (\textbf{Reference: Attributes}).) The available attributes are stored in the record \texttt{NCurses.attrs}, they are 
\begin{description}
\item[{\texttt{NORMAL}}] normal display with no extra attributes.
\item[{\texttt{STANDOUT}}] displays text in the best highlighting mode of the terminal.
\item[{\texttt{UNDERLINE}}] underlines the text.
\item[{\texttt{REVERSE}}] display in reverse video by exchanging the foreground and background color.
\item[{\texttt{BLINK}}] displays the text blinking.
\item[{\texttt{DIM}}] displays the text half bright.
\item[{\texttt{BOLD}}] displays the text in a bold font.
\end{description}
 Note that not all of these work with all types of terminals, or some may cause
the same display. Furthermore, if \texttt{NCurses.attrs.has{\textunderscore}colors} is \texttt{true} there is a list \texttt{NCurses.attrs.ColorPairs} of attributes to set the foreground and background color. These should be
accessed indirectly with \texttt{NCurses.ColorAttr} (\ref{NCurses.ColorAttr}). Attributes can be combined by adding their values (internally, they are
represented by integers). They can also be added to the integer representing a
character for use with \texttt{waddch}. 

 The library functions for setting attributes are: 
\begin{description}
\item[{\texttt{wattrset(win, attr)}}] This sets the default (combined) attributes for a window which is added to all
characters written to it; using \texttt{NCurses.attrs.NORMAL} as attribute is a reset.
\item[{\texttt{wattron(win, attr)}/\texttt{wattroff(win, attr)}}] This sets or unsets one or some default attributes of the window without
changing the others.
\item[{\texttt{wattr{\textunderscore}get(win)}}] This returns the current default attribute and default color pair of a window.
\item[{\texttt{wbkgdset(win, attr)}}] This is similar to \texttt{wattrset} but you can also add a character to \mbox{\texttt{attr}} which is used as default instead of blanks.
\item[{\texttt{wbkgd(win, attr)}}] This function changes the attributes for all characters in the window to \mbox{\texttt{attr}}, also used for further characters written to that window.
\end{description}
 }

 
\subsection{\textcolor{Chapter }{Miscellaneous function}}\label{ssec:ncursesMisc}
\logpage{[ 2, 1, 8 ]}
{
  We also provide the \texttt{ncurses} function \texttt{mnap(msec)} which is a sleep for \mbox{\texttt{msec}} milliseconds. }

 }

 
\section{\textcolor{Chapter }{The \texttt{ncurses} \textsf{GAP} functions}}\label{sec:cursesGAP}
\logpage{[ 2, 2, 0 ]}
{
 The functions of the \texttt{ncurses} library are used within \textsf{GAP} very similarly to their \texttt{C} equivalents. The functions are available as components of a record \texttt{NCurses} with the name of the \texttt{C} function (e.g., \texttt{NCurses.newwin}). 

 In \textsf{GAP} the \texttt{ncurses} windows are accessed via integers (as returned by \texttt{NCurses.newwin}). The standard screen \texttt{stdscr} from the \texttt{ncurses} library is available as window number \texttt{0}. But this should not be used; to allow recursive applications of \texttt{ncurses} always create a new window, wrap it in a panel and delete both when they are
no longer needed. 

 Each window can be wrapped in one panel which is accessed by the same integer.
(Window \texttt{0} cannot be used with a panel.) 

 Coordinates in windows are the same zero based integers as in the
corresponding \texttt{C} functions. The interface of functions which \emph{return} coordinates is slightly different from the \texttt{C} version; they just return lists of integers and you just give the window as
argument, e.g., \texttt{NCurses.getmaxyx(win)} returns a list \texttt{[nrows, ncols]} of two integers. 

 Characters to be written to a window can be given either as \textsf{GAP} characters like \texttt{'a'} or as integers like \texttt{INT{\textunderscore}CHAR('a') = 97}. If you use the integer version you can also add attributes including color
settings to it for use with \texttt{NCurses.waddch}. 

 When writing an application decide about an appropriate terminal setting for
your visual mode windows, see \ref{ssec:ncursesTermset} and the utility function \texttt{NCurses.SetTerm} (\ref{NCurses.SetTerm}) below. Use \texttt{NCurses.savetty()} and \texttt{NCurses.resetty()} to save and restore the previous setting. 

 We also provide some higher level functionality for displaying marked up text,
see \texttt{NCurses.PutLine} (\ref{NCurses.PutLine}) and \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine}). 

 We now describe some utility functions for putting text on a terminal window. 

\subsection{\textcolor{Chapter }{NCurses.ColorAttr}}
\logpage{[ 2, 2, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.ColorAttr( fgcolor, bgcolor )\index{NCurses.ColorAttr@\texttt{NCurses.ColorAttr}}
\label{NCurses.ColorAttr}
}\hfill{\scriptsize (function)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.attrs.has{\_}colors\index{NCurses.attrs.hascolors@\texttt{NCurses.attrs.has{\_}colors}}
\label{NCurses.attrs.hascolors}
}\hfill{\scriptsize (global variable)}}\\
\textbf{\indent Returns:\ }
an attribute for setting the foreground and background color to be used on a
terminal window (it is a \textsf{GAP} integer).



 The return value can be used like any other attribute as described in \ref{ssec:ncursesAttrs}. The arguments \mbox{\texttt{fgcolor}} and \mbox{\texttt{bgcolor}} can be given as strings, allowed are those in \texttt{[ "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white" ]}. These are the default foreground colors 0 to 7 on ANSI terminals.
Alternatively, the numbers 0 to 7 can be used directly as arguments. 

 Note that terminals can be configured in a way such that these named colors
are not the colors which are actually displayed. 

 The variable \texttt{NCurses.attrs.has{\_}colors} (\ref{NCurses.attrs.hascolors}) \index{colors, availability} is set to \texttt{true} or \texttt{false} if the terminal supports colors or not, respectively. If a terminal does not
support colors then \texttt{NCurses.ColorAttr} always returns \texttt{NCurses.attrs.NORMAL}. 

 For an attribute setting the foreground color with the default background
color of the terminal use \texttt{-1} as \mbox{\texttt{bgcolor}} or the same as \mbox{\texttt{fgcolor}}. 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> win := NCurses.newwin(0,0,0,0);; pan := NCurses.new_panel(win);;
  gap> defc := NCurses.defaultColors;;
  gap> NCurses.wmove(win, 0, 0);;
  gap> for a in defc do for b in defc do
  >      NCurses.wattrset(win, NCurses.ColorAttr(a, b));
  >      NCurses.waddstr(win, Concatenation(a,"/",b,"\t"));
  >    od; od; 
  gap> NCurses.update_panels();; NCurses.doupdate();;
  gap> NCurses.napms(5000); # show for 5 seconds
  gap> NCurses.endwin();; NCurses.del_panel(pan);; NCurses.delwin(win);;
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{NCurses.SetTerm}}
\logpage{[ 2, 2, 2 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.SetTerm( [record] )\index{NCurses.SetTerm@\texttt{NCurses.SetTerm}}
\label{NCurses.SetTerm}
}\hfill{\scriptsize (function)}}\\


 This function provides a unified interface to the various terminal setting
functions of \texttt{ncurses} listed in \ref{ssec:ncursesTermset}. The optional argument is a record with components which are assigned to \texttt{true} or \texttt{false}. Recognised components are: \texttt{cbreak}, \texttt{echo}, \texttt{nl}, \texttt{intrflush}, \texttt{leaveok}, \texttt{scrollok}, \texttt{keypad}, \texttt{raw} (with the obvious meaning if set to \texttt{true} or \texttt{false}, respectively). 

 The default, if no argument is given, is \texttt{rec(cbreak := true, echo := false, nl := false, intrflush := false, leaveok :=
true, scrollok := false, keypad := true)}. (This is a useful setting for many applications.) If there is an argument \mbox{\texttt{record}}, then the given components overwrite the corresponding defaults. }

 

\subsection{\textcolor{Chapter }{NCurses.IsAttributeLine}}
\logpage{[ 2, 2, 3 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.IsAttributeLine( obj )\index{NCurses.IsAttributeLine@\texttt{NCurses.IsAttributeLine}}
\label{NCurses.IsAttributeLine}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 \texttt{true} if the argument describes a string with attributes. 



 An \emph{attribute line} describes a string with attributes. It is represented by either a string or a
dense list of strings, integers, and Booleans immediately following integers,
where at least one list entry must \emph{not} be a string. (The reason is that we want to be able to distinguish between an
attribute line and a list of such lines, and that the case of plain strings is
perhaps the most usual one, so we do not want to force wrapping each string in
a list.) The integers denote attribute values such as color or font
information, the Booleans denote that the attribute given by the preceding
integer is set or reset. 

 If an integer is not followed by a Boolean then it is used as the attribute
for the following characters, that is it overwrites all previously set
attributes. Note that in some applications the variant with explicit Boolean
values is preferable, because such a line can nicely be highlighted just by
prepending a \texttt{NCurses.attrs.STANDOUT} attribute. 

 For an overview of attributes, see~\ref{ssec:ncursesAttrs}. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> NCurses.IsAttributeLine( "abc" );
  true
  gap> NCurses.IsAttributeLine( [ "abc", "def" ] );
  false
  gap> NCurses.IsAttributeLine( [ NCurses.attrs.UNDERLINE, true, "abc" ] );
  true
  gap> NCurses.IsAttributeLine( "" );  NCurses.IsAttributeLine( [] );
  true
  false
\end{Verbatim}
 

 The \emph{empty string} is an attribute line whereas the \emph{empty list} (which is not in \texttt{IsStringRep}, see~\texttt{IsStringRep} (\textbf{Reference: IsStringRep})) is \emph{not} an attribute line. }

 

\subsection{\textcolor{Chapter }{NCurses.ConcatenationAttributeLines}}
\logpage{[ 2, 2, 4 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.ConcatenationAttributeLines( lines[, keep] )\index{NCurses.ConcatenationAttributeLines@\texttt{NCurses.ConcatenationAttributeLines}}
\label{NCurses.ConcatenationAttributeLines}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 an attribute line. 



 For a list \mbox{\texttt{lines}} of attribute lines (see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine})), \texttt{NCurses.ConcatenationAttributeLines} returns the attribute line obtained by concatenating the attribute lines in \mbox{\texttt{lines}}. 

 If the optional argument \mbox{\texttt{keep}} is \texttt{true} then attributes set in an entry of \mbox{\texttt{lines}} are valid also for the following entries of \mbox{\texttt{lines}}. Otherwise (in particular if there is no second argument) the attributes are
reset to \texttt{NCurses.attrs.NORMAL} between the entries of \mbox{\texttt{lines}}. 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> plain_str:= "hello";;
  gap> with_attr:= [ NCurses.attrs.BOLD, "bold" ];;
  gap> NCurses.ConcatenationAttributeLines( [ plain_str, plain_str ] );
  "hellohello"
  gap> NCurses.ConcatenationAttributeLines( [ plain_str, with_attr ] );
  [ "hello", 2097152, "bold" ]
  gap> NCurses.ConcatenationAttributeLines( [ with_attr, plain_str ] );
  [ 2097152, "bold", 0, "hello" ]
  gap> NCurses.ConcatenationAttributeLines( [ with_attr, with_attr ] );
  [ 2097152, "bold", 0, 2097152, "bold" ]
  gap> NCurses.ConcatenationAttributeLines( [ with_attr, with_attr ], true );
  [ 2097152, "bold", 2097152, "bold" ]
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{NCurses.RepeatedAttributeLine}}
\logpage{[ 2, 2, 5 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.RepeatedAttributeLine( line, width )\index{NCurses.RepeatedAttributeLine@\texttt{NCurses.RepeatedAttributeLine}}
\label{NCurses.RepeatedAttributeLine}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 an attribute line. 



 For an attribute line \mbox{\texttt{line}} (see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine})) and a positive integer \mbox{\texttt{width}}, \texttt{NCurses.RepeatedAttributeLine} returns an attribute line with \mbox{\texttt{width}} displayed characters (see~\texttt{NCurses.WidthAttributeLine} (\ref{NCurses.WidthAttributeLine})) that is obtained by concatenating sufficiently many copies of \mbox{\texttt{line}} and cutting off a tail if applicable. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> NCurses.RepeatedAttributeLine( "12345", 23 );
  "12345123451234512345123"
  gap> NCurses.RepeatedAttributeLine( [ NCurses.attrs.BOLD, "12345" ], 13 );
  [ 2097152, "12345", 0, 2097152, "12345", 0, 2097152, "123" ]
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{NCurses.PutLine}}
\logpage{[ 2, 2, 6 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.PutLine( win, y, x, lines[, skip] )\index{NCurses.PutLine@\texttt{NCurses.PutLine}}
\label{NCurses.PutLine}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 \texttt{true} if \mbox{\texttt{lines}} were written, otherwise \texttt{false}. 



 The argument \mbox{\texttt{lines}} can be a list of attribute lines (see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine})) or a single attribute line. This function writes the attribute lines to
window \mbox{\texttt{win}} at and below of position \mbox{\texttt{y}}, \mbox{\texttt{x}}. 

 If the argument \mbox{\texttt{skip}} is given, it must be a nonnegative integer. In that case the first \mbox{\texttt{skip}} characters of each given line are not written to the window (but the
attributes are). }

 

\subsection{\textcolor{Chapter }{NCurses.WidthAttributeLine}}
\logpage{[ 2, 2, 7 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.WidthAttributeLine( line )\index{NCurses.WidthAttributeLine@\texttt{NCurses.WidthAttributeLine}}
\label{NCurses.WidthAttributeLine}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
number of displayed characters in an attribute line.



 For an attribute line \mbox{\texttt{line}} (see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine})), the function returns the number of displayed characters of \mbox{\texttt{line}}. \index{displayed characters} 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> NCurses.WidthAttributeLine( "abcde" );
  5
  gap> NCurses.WidthAttributeLine( [ NCurses.attrs.BOLD, "abc",
  >        NCurses.attrs.NORMAL, "de" ] );
  5
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{NCurses.Grid}}
\logpage{[ 2, 2, 8 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.Grid( win, trow, brow, lcol, rcol, rowinds, colinds )\index{NCurses.Grid@\texttt{NCurses.Grid}}
\label{NCurses.Grid}
}\hfill{\scriptsize (function)}}\\


 This function draws a grid of horizontal and vertical lines on the window \mbox{\texttt{win}}, using the line drawing characters explained in \ref{ssec:ncursesLines}. The given arguments specify the top and bottom row of the grid, its left and
right column, and lists of row and column numbers where lines should be drawn. 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> fun := function() local win, pan;
  >      win := NCurses.newwin(0,0,0,0);
  >      pan := NCurses.new_panel(win);
  >      NCurses.Grid(win, 2, 11, 5, 22, [5, 6], [13, 14]);
  >      NCurses.PutLine(win, 12, 0, "Press <Enter> to quit");
  >      NCurses.update_panels(); NCurses.doupdate();
  >      NCurses.wgetch(win);
  >      NCurses.endwin();
  >      NCurses.del_panel(pan); NCurses.delwin(win);
  > end;;
  gap> fun();
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{NCurses.WBorder}}
\logpage{[ 2, 2, 9 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.WBorder( win[, chars] )\index{NCurses.WBorder@\texttt{NCurses.WBorder}}
\label{NCurses.WBorder}
}\hfill{\scriptsize (function)}}\\


 This is a convenient interface to the \texttt{ncurses} function \texttt{wborder}. It draws a border around the window \mbox{\texttt{win}}. If no second argument is given the default line drawing characters are used,
see \ref{ssec:ncursesLines}. Otherwise, \mbox{\texttt{chars}} must be a list of \textsf{GAP} characters or integers specifying characters, possibly with attributes. If \mbox{\texttt{chars}} has length 8 the characters are used for the left/right/top/bottom sides and
top-left/top-right/bottom-left/bottom-right corners. If \mbox{\texttt{chars}} contains 2 characters the first is used for the sides and the second for all
corners. If \mbox{\texttt{chars}} contains just one character it is used for all sides including the corners. }

 

\subsection{\textcolor{Chapter }{NCurses.SaveWin}}
\logpage{[ 2, 2, 10 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.SaveWin( win )\index{NCurses.SaveWin@\texttt{NCurses.SaveWin}}
\label{NCurses.SaveWin}
}\hfill{\scriptsize (function)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.StringsSaveWin( cont )\index{NCurses.StringsSaveWin@\texttt{NCurses.StringsSaveWin}}
\label{NCurses.StringsSaveWin}
}\hfill{\scriptsize (function)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.RestoreWin( win, cont )\index{NCurses.RestoreWin@\texttt{NCurses.RestoreWin}}
\label{NCurses.RestoreWin}
}\hfill{\scriptsize (function)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.ShowSaveWin( cont )\index{NCurses.ShowSaveWin@\texttt{NCurses.ShowSaveWin}}
\label{NCurses.ShowSaveWin}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 a \textsf{GAP} object describing the contents of a window. 



 These functions can be used to save and restore the contents of \texttt{ncurses} windows. \texttt{NCurses.SaveWin} returns a list \texttt{[nrows, ncols, chars]} giving the number of rows, number of columns, and a list of integers
describing the content of window \mbox{\texttt{win}}. The integers in the latter contain the displayed characters plus the
attributes for the display. 

 The function \texttt{NCurses.StringsSaveWin} translates data \mbox{\texttt{cont}} in form of the output of \texttt{NCurses.SaveWin} to a list of \texttt{nrows} strings giving the text of the rows of the saved window, and ignoring the
attributes. You can view the result with \texttt{NCurses.Pager} (\ref{NCurses.Pager}). 

 The argument \mbox{\texttt{cont}} for \texttt{NCurses.RestoreWin} must be of the same format as the output of \texttt{NCurses.SaveWin}. The content of the saved window is copied to the window \mbox{\texttt{win}}, starting from the top-left corner as much as it fits. 

 The utility \texttt{NCurses.ShowSaveWin} can be used to display the output of \texttt{NCurses.SaveWin} (as much of the top-left corner as fits on the screen). }

 }

 }

 
\chapter{\textcolor{Chapter }{Utilities using \texttt{ncurses}}}\label{ch:util}
\logpage{[ 3, 0, 0 ]}
{
  In this chapter we describe the usage of some example applications of the \texttt{ncurses} interface provided by the \textsf{Browse} package. They may be of interest by themselves, or they may be used as utility
functions within larger applications. 
\section{\textcolor{Chapter }{\texttt{ncurses} utilities}}\label{sect:ncurses_utils}
\logpage{[ 3, 1, 0 ]}
{
  If you call the functions \texttt{NCurses.Alert} (\ref{NCurses.Alert}), \texttt{NCurses.Select} (\ref{NCurses.Select}), \texttt{NCurses.GetLineFromUser} (\ref{NCurses.GetLineFromUser}), or \texttt{NCurses.Pager} (\ref{NCurses.Pager}) from another \texttt{ncurses} application in visual mode, you should refresh the windows that are still
open, by calling \texttt{NCurses.update{\textunderscore}panels} and \texttt{NCurses.doupdate} afterwards, see Section \ref{ssec:ncursesPan} and \ref{ssec:ncursesWin}. Also, if the cursor shall be hidden after that, you should call \texttt{curs{\textunderscore}set} with argument \texttt{0}, see Section \ref{ssec:ncursesTermset}, since the cursor is automatically made visible in \texttt{NCurses.endwin}. 

\subsection{\textcolor{Chapter }{NCurses.Alert}}
\logpage{[ 3, 1, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.Alert( messages, timeout[, attrs] )\index{NCurses.Alert@\texttt{NCurses.Alert}}
\label{NCurses.Alert}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 the integer corresponding to the character entered, or \texttt{fail}. 



 In visual mode, \texttt{Print} cannot be used for messages. An alternative is given by \texttt{NCurses.Alert}. 

 Let \mbox{\texttt{messages}} be either an attribute line or a nonempty list of attribute lines, and \mbox{\texttt{timeout}} be a nonnegative integer. \texttt{NCurses.Alert} shows \mbox{\texttt{messages}} in a bordered box in the middle of the screen. 

 If \mbox{\texttt{timeout}} is zero then the box is closed after any user input, and the integer
corresponding to the entered key is returned. If \mbox{\texttt{timeout}} is a positive number $n$, say, then the box is closed after $n$ milliseconds, and \texttt{fail} is returned. 

 If the optional argument \mbox{\texttt{attrs}} is given, it must be an integer representing attributes such as the components
of \texttt{NCurses.attrs} (see Section~\ref{ssec:ncursesAttrs}) or the return value of \texttt{NCurses.ColorAttr} (\ref{NCurses.ColorAttr}); these attributes are used for the border of the box. The default is \texttt{NCurses.attrs.NORMAL}. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> NCurses.Alert( "Hello world!", 1000 );
  fail
  gap> NCurses.Alert( [ "Hello world!",                       
  >      [ "Hello ", NCurses.attrs.BOLD, "bold!" ] ], 1500,
  >      NCurses.ColorAttr( "red", -1 ) + NCurses.attrs.BOLD );
  fail
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{NCurses.Select}}
\logpage{[ 3, 1, 2 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.Select( poss[, single[, none]] )\index{NCurses.Select@\texttt{NCurses.Select}}
\label{NCurses.Select}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
Position or list of positions, or \texttt{false}.



 This function allows the user to select one or several items from a given
list. In the simplest case \mbox{\texttt{poss}} is a list of attribute lines (see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine})), each of which should fit on one line. Then \texttt{NCurses.Select} displays these lines and lets the user browse through them. After pressing the \textsc{Return} key the index of the highlighted item is returned. Note that attributes in
your lines should be switched on and off separately by \texttt{true}/\texttt{false} entries such that the lines can be nicely highlighted. 

 The optional argument \mbox{\texttt{single}} must be \texttt{true} (default) or \texttt{false}. In the second case, an arbitrary number of items can be marked and the
function returns the list of their indices. 

 If \mbox{\texttt{single}} is \texttt{true} a third argument \mbox{\texttt{none}} can be given. If it is \texttt{true} then it is possible to leave the selection without choosing an item, in this
case \texttt{false} is returned. 

 More details can be given to the function by giving a record as argument \mbox{\texttt{poss}}. It can have the following components: 
\begin{description}
\item[{\texttt{items}}] The list of attribute lines as described above.
\item[{\texttt{single}}] Boolean with the same meaning as the optional argument \mbox{\texttt{single}}.
\item[{\texttt{none}}] Boolean with the same meaning as the optional argument \mbox{\texttt{none}}.
\item[{\texttt{size}}] The size of the window like the first two arguments of \texttt{NCurses.newwin} (default is \texttt{[0, 0]}, as big as possible). 
\item[{\texttt{begin}}] Top-left corner of the window like the last two arguments of \texttt{NCurses.newwin} (default is \texttt{[0, 0]}, top-left of the screen). 
\item[{\texttt{attribute}}] An attribute used for the display of the window (default is \texttt{NCurses.attrs.NORMAL}).
\item[{\texttt{border}}] Set to \texttt{true} if the window should be displayed with a border (default is \texttt{false}).
\item[{\texttt{header}}] An attribute line used as header line (the default depends on the settings of \texttt{single} and \texttt{none}).
\item[{\texttt{hint}}] An attribute line used as hint in the last line of the window (the default
depends on the settings of \texttt{single} and \texttt{none}).
\end{description}
 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> index := NCurses.Select(["Apples", "Pears", "Oranges"]);
  gap> index := NCurses.Select(rec(
  >                     items := ["Apples", "Pears", "Oranges"],
  >                     single := false,
  >                     border := true,
  >                     begin := [5, 5],
  >                     size := [8, 60],
  >                     header := "Choose fruits",
  >                     attribute := NCurses.ColorAttr("yellow","red") ) );
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{NCurses.GetLineFromUser}}
\logpage{[ 3, 1, 3 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.GetLineFromUser( pre )\index{NCurses.GetLineFromUser@\texttt{NCurses.GetLineFromUser}}
\label{NCurses.GetLineFromUser}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
User input as string.



 This function can be used to get an input string from the user. It opens a one
line window and writes the given string \mbox{\texttt{pre}} into it. Then it waits for user input. After hitting the \textsc{Return} key the typed line is returned as a string to \textsf{GAP}. If the user exits via hitting the \textsc{Esc} key instead of hitting the \textsc{Return} key, the function returns \texttt{false}. (The \textsc{Esc} key may be recognized as input only after a delay of about a second.) 

 Some simple editing is possible during user input: The \textsc{Left}, \textsc{Right}, \textsc{Home} and \textsc{End} keys, the \textsc{Insert}/\textsc{Replace} keys, and the \textsc{Backspace}/\textsc{Delete} keys are supported. 

 Instead of a string, \mbox{\texttt{pre}} can also be a record with the component \texttt{prefix}, whose value is the string described above. The following optional components
of this record are supported. 

 
\begin{description}
\item[{\texttt{window}}]  The window with the input field is created relative to this window, the
default is $0$. 
\item[{\texttt{begin}}]  This is a list with the coordinates of the upper left corner of the window
with the input field, relative to the window described by the \texttt{window} component; the default is \texttt{[ y-4, 2 ]}, where \texttt{y} is the height of this window. 
\item[{\texttt{default}}]  This string appears as result when the window is opened, the default is an
empty string. 
\end{description}
 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> str := NCurses.GetLineFromUser("Your Name: ");;
  gap> Print("Hello ", str, "!\n");
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{NCurses.Pager}}
\logpage{[ 3, 1, 4 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.Pager( lines[, border[, ly, lx, y, x]] )\index{NCurses.Pager@\texttt{NCurses.Pager}}
\label{NCurses.Pager}
}\hfill{\scriptsize (function)}}\\


 This is a simple pager utility for displaying and scrolling text. The argument \mbox{\texttt{lines}} can be a list of attribute lines (see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine})) or a string (the lines are separated by newline characters) or a record. In
case of a record the following components are recognized: 

 More details can be given to the function by using a record as argument \mbox{\texttt{poss}}. It can have the following components: 
\begin{description}
\item[{\texttt{lines}}] The list of attribute lines or a string as described above.
\item[{\texttt{start}}] Line number to start the display.
\item[{\texttt{size}}] The size \texttt{[ly, lx]} of the window like the first two arguments of \texttt{NCurses.newwin} (default is \texttt{[0, 0]}, as big as possible). 
\item[{\texttt{begin}}] Top-left corner \texttt{[y, x]} of the window like the last two arguments of \texttt{NCurses.newwin} (default is \texttt{[0, 0]}, top-left of the screen). 
\item[{\texttt{attribute}}] An attribute used for the display of the window (default is \texttt{NCurses.attrs.NORMAL}).
\item[{\texttt{border}}] Either one of \texttt{true}/\texttt{false} to show the pager window with or without a standard border. Or it can be
string with eight, two or one characters, giving characters to be used for a
border, see \texttt{NCurses.WBorder} (\ref{NCurses.WBorder}).
\item[{\texttt{hint}}]  A text for usage info in the last line of the window.
\end{description}
 

 As an abbreviation the information from \texttt{border}, \texttt{size} and \texttt{begin} can also be specified in optional arguments. 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> lines := List([1..100],i-> ["line ",NCurses.attrs.BOLD,String(i)]);;
  gap> NCurses.Pager(lines);
\end{Verbatim}
 }

 
\subsection{\textcolor{Chapter }{Selection of help matches}}\label{ssec:selhelpmatch}
\logpage{[ 3, 1, 5 ]}
{
  After loading the \textsf{Browse} package \textsf{GAP}'s help system behaves slightly different when a request yields several
matches. The matches are shown via \texttt{NCurses.Select} (\ref{NCurses.Select}) and one can choose one match for immediate display. It is possible to not
choose a match and the \texttt{?<nr>} syntax still works. 

 If you want the original behavior define \texttt{NoSelectHelpMatches := false;} in your \textsf{GAP} session or \texttt{.gaprc} file, see~ (\textbf{Reference: The .gaprc file}). }

 }

 
\section{\textcolor{Chapter }{A Demo Function}}\label{sec:demo}
\logpage{[ 3, 2, 0 ]}
{
  

\subsection{\textcolor{Chapter }{NCurses.Demo}}
\logpage{[ 3, 2, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.Demo( [inputs] )\index{NCurses.Demo@\texttt{NCurses.Demo}}
\label{NCurses.Demo}
}\hfill{\scriptsize (function)}}\\


 Let \mbox{\texttt{inputs}} be a list of records, each with the components \texttt{title} (a string), \texttt{inputblocks} (a list of strings, each describing some \textsf{GAP} statements), and optionally \texttt{footer} (a string) and \texttt{cleanup} (a string describing \textsf{GAP} statements). The default is \texttt{NCurses.DemoDefaults}. 

 \texttt{NCurses.Demo} lets the user choose an entry from \mbox{\texttt{inputs}}, via \texttt{NCurses.Select} (\ref{NCurses.Select}), and then executes the \textsf{GAP} statements in the first entry of the \texttt{inputblocks} list of this entry; these strings, together with the values of \texttt{title} and \texttt{footer}, are shown in a window, at the bottom of the screen. The effects of calls to
functions using \texttt{ncurses} are shown in the rest of the screen. After the execution of the statements
(which may require user input), the user can continue with the next entry of \texttt{inputblocks}, or return to the \texttt{inputs} selection (and thus cancel the current \texttt{inputs} entry), or return to the execution of the beginning of the current \texttt{inputs} entry. At the end of the current entry of \texttt{inputs}, the user returns to the \texttt{inputs} selection. 

 The \textsf{GAP} statements in the \texttt{cleanup} component, if available, are executed whenever the user does not continue;
this is needed for deleting panels and windows that are defined in the
statements of the current entry. 

 Note that the \textsf{GAP} statements are executed in the \emph{global} scope, that is, they have the same effect as if they would be entered at the \textsf{GAP} prompt. Initially, \texttt{NCurses.Demo} sets the value of \texttt{BrowseData.defaults.work.windowParameters} to the parameters that describe the part of the screen above the window that
shows the inputs; so applications of \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) use automatically the maximal part of the screen as their window. It is
recommended to to use a screen with at least $80$ columns and at least $37$ rows. }

 }

 }

 
\chapter{\textcolor{Chapter }{Browsing Tables in \textsf{GAP} using \texttt{ncurses} -- The User Interface}}\label{chap:browse_user}
\logpage{[ 4, 0, 0 ]}
{
  As stated in Section~\ref{sec:intro}, one aim of the \textsf{Browse} package is to provide tools for the quite usual task to show a two-dimensional
array or certain rows and columns of it on a character screen in a formatted
way, to navigate in this array via key strokes, and to search for strings, to
sort the array by row or column values etc. The idea is that one starts with
an array of data, the \emph{main table}\index{main table of a browse table}. Optionally, labels for each row of the main table are given, which are also
arranged in an array (with perhaps several columns), the \emph{row labels table}\index{row labels of a browse table}; analogously, a \emph{column labels table}\index{column labels of a browse table} of labels for the columns of the main table may be given. The row labels are
shown to the left of the main table, the column labels are shown above the
main table. The space above the row labels and to the left of the column
labels can be used for a fourth table, the \emph{corner table}\index{corner table of a browse table}, with information about the labels or about the main table. Optionally, a \emph{header}\index{header of a browse table} and a \emph{footer}\index{footer of a browse table} may be shown above and below these four tables, respectively. Header and
footer are not separated into columns. So the shown window has the following
structure.  \begin{center} \begin{tabular}{|c|c|} \hline \multicolumn{2}{|c|}{header} \\
\hline corner & column labels \\ \hline & \\ row & main \\ labels & table \\ &
\\ \hline \multicolumn{2}{|c|}{footer} \\ \hline \end{tabular} \end{center}    If not the whole tables fit into the window then only subranges of rows and
columns of the main table are shown, together with the corresponding row and
column labels. Also in this case, the row heights and column widths are
computed w.r.t. the whole table not w.r.t. the shown rows and columns. This
means that the shown row labels are unchanged if the range of shown columns is
changed, the shown column labels are unchanged if the range of shown rows is
changed, and the whole corner table is always shown. 

 The current chapter describes the user interface for \emph{standard applications} of this kind, i.~e., those applications for which one just has to collect the data to be shown
in a record --which we call a \emph{browse table}-- without need for additional \textsf{GAP} programming. 

 Section~\ref{sec:features} gives an overview of the features available in standard browse table
applications, and Section~\ref{sec:browsebasicdata} describes the data structures used in browse tables. Finally, Section~\ref{sec:browsegeneric} introduces the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}), which is the generic function for showing browse table in visual mode. 

 For technical details needed to extend these applications and to build other
applications, see Chapter~\ref{chap:browse_prg}. 

 Examples of browse table applications are shown in Chapter~\ref{ch:appl}.  
\section{\textcolor{Chapter }{Features Supported by the Function \texttt{NCurses.BrowseGeneric} }}\label{sec:features}
\logpage{[ 4, 1, 0 ]}
{
  Standard applications of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) have the following functionality. Other applications may provide only a
subset, or add further functionality, see Chapters~\ref{chap:browse_prg} and~\ref{ch:appl}. 

 
\begin{description}
\item[{Scrolling:\index{scrolling in a browse table}}]  The subranges of shown rows and columns of the main table can be modified,
such that the focus area is moved to the left, to the right, up, or down;
depending on the context, the focus is moved by one character, by one table
cell or a part of it, by the window height/width (minus one character or minus
one table cell). 
\item[{Selecting:\index{selecting entries of a browse table}}]  A cell, row, or column of the main table can be selected; then it is shown
highlighted on the screen (by default using the attribute \texttt{NCurses.attrs.STANDOUT}, see Section~\ref{ssec:ncursesAttrs}). The selection can be moved inside the main table to a neighboring cell,
row, or column; this causes also scrolling of the main table when the window
borders are reached. 
\item[{Searching:\index{searching in a browse table}}]  A search string is entered by the user, and the first matching cell becomes
selected; one can search further for the next matching cell. Global search
parameters define what matching means (case sensitive or not, search for
substrings or complete words) and what the first and the next matching cells
are (search in the whole table or just in the selected row or column, search
for whole words or prefixes or suffixes, search forwards or backwards). 
\item[{Sorting:\index{sorting a browse table}}]  If a row or column is selected then the main table can be sorted w.r.t. the
entries in this row or column. Global sort parameters describe for example
whether one wants to sort ascending or descending, or case sensitive or not. 
\item[{Sorting and Categorizing:\index{categorizing a browse table} }]  If a column is selected then the main table can be sorted w.r.t. the entries
in this column, and additionally these entries are turned into \emph{category rows}, i.~e., additional rows are added to the main table, appearing immediately above
the table rows with a fixed value in the selected column, and showing this
column value. (There should be no danger to mix up this notion of categories
with the one introduced in~ (\textbf{Reference: Categories}).) The category rows can be \emph{collapsed} \index{collapsed category row} (that is, the table rows that belong to this category row are not shown) or \emph{expanded}\index{expanded category row} (that is, the corresponding table rows are shown). Some of the global search
parameters affect the category rows, for example, whether the category rows
shall involve a counter with the number of corresponding data rows. With
additional programming, one can achieve that a row of the browse table appears
under several category rows. 
\item[{Help:\index{help window for a browse table}}]  Depending on the application and on the situation, different sets of user
inputs may be available and different meanings of these inputs are possible.
An overview of the currently available inputs and their meanings can be opened
in each situation, by hitting the \textsc{?} key. 
\item[{Re-entering:}]  When one has called \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) with a browse table, and returns from visual mode to the \textsf{GAP} prompt after some navigation steps, calling \texttt{NCurses.BrowseGeneric} again with this table will enter visual mode in the same situation where it
was left. For example, the cell in the top-left position will be the same as
before, and if a cell was selected before then this cell will be selected now.
(One can avoid this behavior using the optional second argument of \texttt{NCurses.BrowseGeneric}.) 
\item[{Logging:\index{log of a browse table session}}]  The integers corresponding to the user inputs in visual mode are collected in
a list that is stored in the component \texttt{dynamic.log} of the browse table. It can be used for repeating the inputs with the replay
feature. (For browse table applications that give the user no access to the
browse table itself, one can force the log to be assigned to the component \texttt{log} of the global variable \texttt{BrowseData}, \index{BrowseData.log} see Section~\ref{BrowseData}.) 
\item[{Replay:\index{replay of a browse table session}}]  Instead of interactively hitting keys in visual mode, one can prescribe the
user inputs to a browse table via a ``replay record''; the inputs are then processed with given time intervals. The easiest way to
create a meaningful replay record is via the function \texttt{BrowseData.SetReplay} (\ref{BrowseData.SetReplay}), with argument the \texttt{dynamic.log} component of the browse table in question that was stored in an interactive
session. 
\end{description}
 

 The following features are not available in standard applications. They
require additional programming. 

 
\begin{description}
\item[{Clicking:\index{click on an entry of a browse table}}]  One possible action is to ``click'' a selected cell, row, or column. It depends on the application what the effect
is. A typical situation is that a corresponding \textsf{GAP} object is added to the list of return values of \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}). Again it depends on the application what this \textsf{GAP} object is. In order to use this feature, one has to provide a record whose
components are \textsf{GAP} functions, see Section~\ref{BrowseData} for details. 
\item[{Return Value:\index{return value of a browse table session} }]  The function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) may have an application dependent return value. A typical situation is that a
list of objects corresponding to those cells is returned that were ``clicked'' in visual mode. In order to use this feature, one has to assign the desired
value to the component \texttt{dynamic.Return} of the browse table. 
\end{description}
 }

  
\section{\textcolor{Chapter }{Data Structures used by \texttt{NCurses.BrowseGeneric}}}\label{sec:browsebasicdata}
\logpage{[ 4, 2, 0 ]}
{
  

\subsection{\textcolor{Chapter }{BrowseData.IsBrowseTableCellData}}
\logpage{[ 4, 2, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseData.IsBrowseTableCellData( obj )\index{BrowseData.IsBrowseTableCellData@\texttt{BrowseData.IsBrowseTableCellData}}
\label{BrowseData.IsBrowseTableCellData}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 \texttt{true} if the argument is a list or a record in a supported format. 



 A \emph{table cell data object} describes the input data for the contents of a cell in a browse table. It is
represented by either an attribute line (see~\texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine})), for cells of height one, or a list of attribute lines or a record with the
components \texttt{rows}, a list of attribute lines, and optionally \texttt{align}, a substring of \texttt{"bclt"}, which describes the alignment of the attribute lines in the table cell --
bottom, horizontally centered, left, and top alignment; the default is right
and vertically centered alignment. (Note that the height of a table row and
the width of a table column can be larger than the height and width of an
individual cell.) 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> BrowseData.IsBrowseTableCellData( "abc" );
  true
  gap> BrowseData.IsBrowseTableCellData( [ "abc", "def" ] );
  true
  gap> BrowseData.IsBrowseTableCellData( rec( rows:= [ "ab", "cd" ],
  >                                           align:= "tl" ) );
  true
  gap> BrowseData.IsBrowseTableCellData( "" );
  true
  gap> BrowseData.IsBrowseTableCellData( [] );
  true
\end{Verbatim}
 

 The \emph{empty string} is a table cell data object of height one and width zero whereas the \emph{empty list} (which is not in \texttt{IsStringRep}, see~\texttt{IsStringRep} (\textbf{Reference: IsStringRep})) is a table cell data object of height zero and width zero. }

 

\subsection{\textcolor{Chapter }{BrowseData.BlockEntry}}
\logpage{[ 4, 2, 2 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseData.BlockEntry( tablecelldata, height, width )\index{BrowseData.BlockEntry@\texttt{BrowseData.BlockEntry}}
\label{BrowseData.BlockEntry}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 a list of attribute lines. 



 For a table cell data object \mbox{\texttt{tablecelldata}} (see~\texttt{BrowseData.IsBrowseTableCellData} (\ref{BrowseData.IsBrowseTableCellData})) and two positive integers \mbox{\texttt{height}} and \mbox{\texttt{width}}, \texttt{BrowseData.BlockEntry} returns a list of \mbox{\texttt{height}} attribute lines of displayed length \mbox{\texttt{width}} each (see~\texttt{NCurses.WidthAttributeLine} (\ref{NCurses.WidthAttributeLine})), that represents the formatted version of \mbox{\texttt{tablecelldata}}. 

 If the rows of \mbox{\texttt{tablecelldata}} have different numbers of displayed characters then they are filled up to the
desired numbers of rows and columns, according to the alignment prescribed by \mbox{\texttt{tablecelldata}}; the default alignment is right and vertically centered. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> BrowseData.BlockEntry( "abc", 3, 5 );
  [ "     ", "  abc", "     " ]
  gap> BrowseData.BlockEntry( rec( rows:= [ "ab", "cd" ],
  >                                align:= "tl" ), 3, 5 );
  [ "ab   ", "cd   ", "     " ]
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{BrowseData.IsBrowseTable}}
\logpage{[ 4, 2, 3 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseData.IsBrowseTable( obj )\index{BrowseData.IsBrowseTable@\texttt{BrowseData.IsBrowseTable}}
\label{BrowseData.IsBrowseTable}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 \texttt{true} if the argument record has the required components and is consistent. 



 A \emph{browse table} is a \textsf{GAP} record that can be used as the first argument of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}). 

 The supported components of a browse table are \texttt{work} and \texttt{dynamic}, their values must be records: The components in \texttt{work} describe that part of the data that are not likely to depend on user
interactions, such as the table entries and their heights and widths. The
components in \texttt{dynamic} describe that part of the data that is intended to change with user
interactions, such as the currently shown top-left entry of the table, or the
current status w.r.t. sorting. For example, suppose you call \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) twice with the same browse table; the second call enters the table in the same
status where it was left \emph{after} the first call if the component \texttt{dynamic} is kept, whereas one has to reset (which usually simply means to unbind) the
component \texttt{dynamic} if one wants to start in the same status as \emph{before} the first call. 

 The following components are the most important ones for standard browse
applications. All these components belong to the \texttt{work} record. For other supported components (of \texttt{work} as well as of \texttt{dynamic}) and for the meaning of the term ``mode'', see Section~\ref{sec:modes}. 
\begin{description}
\item[{\texttt{main}}]  is the list of lists of table cell data objects that form the matrix to be
shown. There is no default for this component. (It is possible to compute the
entries of the main table on demand, see the description of the component \texttt{Main} in Section~\ref{BrowseData}. In this situation, the value of the component \texttt{main} can be an empty list.) 
\item[{\texttt{header}}]  describes a header that shall be shown above the column labels. The value is
either a list of attribute lines (``static header'') or a function or a record whose component names are names of available modes
of the browse table (``dynamic header''). In the function case, the function must take the browse table as its only
argument, and return a list of attribute lines. In the record case, the values
of the components must be such functions. It is assumed that the number of
these lines depends at most on the mode. The default is an empty list, i.~e., there is no header. 
\item[{\texttt{footer}}]  describes a footer that shall be shown below the table. The value is analogous
to that of \texttt{footer}. The default is an empty list, i.~e., there is no footer. 
\item[{\texttt{labelsRow}}]  is a list of row label rows, each being a list of table cell data objects.
These rows are shown to the left of the main table. The default is an empty
list, i.~e., there are no row labels. 
\item[{\texttt{labelsCol}}]  is a list of column information rows, each being a list of table cell data
objects. These rows are shown between the header and the main table. The
default is an empty list, i.~e., there are no column labels. 
\item[{\texttt{corner}}]  is a list of lists of table cell data objects that are printed in the upper
left corner, i.~e., to the left of the column label rows and above the row label columns. The
default is an empty list. 
\item[{\texttt{sepRow}}]  describes the separators above and below rows of the main table and of the row
labels table. The value is either an attribute line or a (not necessarily
dense) list of attribute lines. In the former case, repetitions of the
attribute line are used as separators below each row and above the first row
of the table; in the latter case, repetitions of the entry at the first
position (if bound) are used above the first row, and repetitions of the last
bound entry before the $(i+2)$-th position (if there is such an entry at all) are used below the $i$-th table row. The default is an empty string, which means that there are no
row separators. 
\item[{\texttt{sepCol}}]  describes the separators in front of and behind columns of the main table and
of the column labels table. The format of the value is analogous to that of
the component \texttt{sepRow}; the default is the string \texttt{" "} (whitespace of width one). 
\item[{\texttt{sepLabelsCol}}]  describes the separators above and below rows of the column labels table and
of the corner table, analogously to \texttt{sepRow}. The default is an empty string, which means that there are no column label
separators. 
\item[{\texttt{sepLabelsRow}}]  describes the separators in front of and behind columns of the row labels
table and of the corner table, analogously to \texttt{sepCol}. The default is an empty string. 
\end{description}
 We give a few examples of standard applications. 

 The first example defines a small browse table by prescribing ony the
component \texttt{work.main}, so the defaults for row and column labels (no such labels), and for
separators are used. The table cells are given by plain strings, so they have
height one. Usually this table will fit on the screen. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> m:= 10;;  n:= 5;;
  gap> xpl1:= rec( work:= rec(
  >      main:= List( [ 1 .. m ], i -> List( [ 1 .. n ],
  >        j -> String( [ i, j ] ) ) ) ) );;
  gap> BrowseData.IsBrowseTable( xpl1 );
  true
\end{Verbatim}
 

 In the second example, also row and column labels appear, and different
separators are used. The table cells have height three. Also this table will
usually fit on the screen. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> m:= 6;;  n:= 5;;
  gap> xpl2:= rec( work:= rec(
  >      main:= List( [ 1 .. m ], i -> List( [ 1 .. n ],
  >        j -> rec( rows:= List( [ -i*j, i*j*1000+j, i-j ], String ),
  >                  align:= "c" ) ) ),
  >      labelsRow:= List( [ 1 .. m ], i -> [ String( i ) ] ),
  >      labelsCol:= [ List( [ 1 .. n ], String ) ],
  >      sepRow:= "-",
  >      sepCol:= "|",
  >  ) );;
  gap> BrowseData.IsBrowseTable( xpl2 );
  true
\end{Verbatim}
 

 The third example additionally has a static header and a dynamic footer, and
the table cells involve attributes. This table will usually not fit on the
screen. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> m:= 30;;  n:= 25;;
  gap> xpl3:= rec( work:= rec(
  >      header:= [ "                    Example 3" ],
  >      main:= List( [ 1 .. m ], i -> List( [ 1 .. n ],
  >        j -> rec( rows:= [ String( -i*j ),
  >                           [ NCurses.attrs.BOLD, true,
  >                             NCurses.attrs.ColorPairs[56+1], true,
  >                             String( i*j*1000+j ),
  >                             NCurses.attrs.NORMAL, true ],
  >                             String( i-j ) ],
  >                  align:= "c" ) ) ),
  >      labelsRow:= List( [ 1 .. 30 ], i -> [ String( i ) ] ),
  >      sepLabelsRow:= " % ",
  >      labelsCol:= [ List( [ 1 .. 30 ], i -> [
  >        NCurses.attrs.ColorPairs[ 56+4 ], true,
  >        String( i ),
  >        NCurses.attrs.NORMAL, true ] ) ],
  >      sepLabelsCol:= "=",
  >      sepRow:= "*",
  >      sepCol:= " |",
  >      footer:= t -> [ Concatenation( "top-left entry is: ",
  >                          String( t.dynamic.topleft{ [ 1, 2] } ) ) ],
  >  ) );;
  gap> BrowseData.IsBrowseTable( xpl3 );
  true
\end{Verbatim}
 

 The fourth example illustrates that highlighting may not work properly for
browse tables containing entries whose attributes are not set with explicit
Boolean values, see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine}). Call \texttt{NCurses.BrowseGeneric} with the browse table \texttt{xpl4}, and select an entry (or a column or a row): Only the middle row of each
selected cell will be highlighted, because only in this row, the color
attribute is switched on with an explicit \texttt{true}. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> xpl4:= rec(
  >     defc:= NCurses.defaultColors,
  >     wd:= Maximum( List( ~.defc, Length ) ),
  >     ca:= NCurses.ColorAttr,
  >     fs:= FormattedString,
  >     work:= rec(
  >       header:= [ "Examples of NCurses.ColorAttr" ],
  >       main:= List( ~.defc, i -> List( ~.defc,
  >         j -> [ [ ~.ca( i, j ), ~.fs( i, ~.wd ) ],        # no true!
  >                [ ~.ca( i, j ), true, ~.fs( "on", ~.wd ) ],
  >                [ ~.ca( i, j ), ~.fs( j, ~.wd ) ] ] ) ),  # no true!
  >       labelsRow:= List( ~.defc, i -> [ String( i ) ] ),
  >       labelsCol:= [ List( ~.defc, String ) ],
  >       sepRow:= "-",
  >       sepCol:= [ " |", "|" ],
  >  ) );;
  gap> BrowseData.IsBrowseTable( xpl4 );
  true
\end{Verbatim}
 }

 }

  
\section{\textcolor{Chapter }{The Function \texttt{NCurses.BrowseGeneric}}}\label{sec:browsegeneric}
\logpage{[ 4, 3, 0 ]}
{
  

\subsection{\textcolor{Chapter }{NCurses.BrowseGeneric}}
\logpage{[ 4, 3, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{NCurses.BrowseGeneric( t[, arec] )\index{NCurses.BrowseGeneric@\texttt{NCurses.BrowseGeneric}}
\label{NCurses.BrowseGeneric}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 an application dependent value, or nothing. 



 \texttt{NCurses.BrowseGeneric} is used to show the browse table \mbox{\texttt{t}} (see~\texttt{BrowseData.IsBrowseTable} (\ref{BrowseData.IsBrowseTable})) in a formatted way on a text screen, and allows the user to navigate in this
table. 

 The optional argument \mbox{\texttt{arec}}, if given, must be a record whose components \texttt{work} and \texttt{dynamic}, if bound, are used to provide defaults for missing values in the
corresponding components of \mbox{\texttt{t}}. The default for \mbox{\texttt{arec}} and for the components not provided in \mbox{\texttt{arec}} is \texttt{BrowseData.defaults}, see~\texttt{BrowseData} (\ref{BrowseData}), the function \texttt{BrowseData.SetDefaults} sets these default values. 

 At least the component \texttt{work.main} must be bound in \mbox{\texttt{t}}, with value a list of list of table cell data objects, see~\texttt{BrowseData.IsBrowseTableCellData} (\ref{BrowseData.IsBrowseTableCellData}). 

 When the window or the screen is too small for the browse table, according to
its component \texttt{work.minyx}, the table will not be shown in visual mode, and \texttt{fail} is returned. (This holds also if there would be no return value of the call in
a large enough screen.) Thus one should check for \texttt{fail} results of programmatic calls of \texttt{NCurses.BrowseGeneric}, and one should better not admit \texttt{fail} as a regular return value. 

 Most likely, \texttt{NCurses.BrowseGeneric} will not be called on the command line, but the browse table \mbox{\texttt{t}} will be composed by a suitable function which then calls \texttt{NCurses.BrowseGeneric}, see the examples in Chapter~\ref{ch:appl}. }

 }

 }

  
\chapter{\textcolor{Chapter }{Browsing Tables in \textsf{GAP} using \texttt{ncurses} -- The Programming Interface}}\label{chap:browse_prg}
\logpage{[ 5, 0, 0 ]}
{
  This chapter describes some aspects of the internals of the browse table
handling. The relevant objects are \emph{action functions} that implement the individual navigation steps (see Section~\ref{sec:actions}), \emph{modes} that describe the sets of available navigation steps in given situations (see
Section~\ref{sec:modes}), and \emph{browse applications} that are given by the combination of several modes (see Section~\ref{sec:applications}). Most of the related data is stored in the global variable \texttt{BrowseData} (\ref{BrowseData}). For more details, one should look directly at the code in the file \texttt{lib/browse.gi} of the \textsf{Browse} package.  
\section{\textcolor{Chapter }{Navigation Steps in Browse Tables}}\label{sec:actions}
\logpage{[ 5, 1, 0 ]}
{
  Navigating in a browse table means that after entering visual mode by calling \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}), the user hits one or several keys, and if this input is in a given set of
admissible inputs then a corresponding function is executed with argument the
browse table. The function call then may change components in this table
(recommended: components in its \texttt{dynamic} component), such that the appearance in the window may be different
afterwards, and also the admissible inputs and their effects may have changed. 

 The relation between the admissible inputs and the corresponding functions is
application dependent. However, it is recommended to associate the same input
to the same function in different situations; for example, the \textsc{?} key and the \textsc{F1} key should belong to a function that shows a help window (see Section \ref{BrowseData.actions.ShowHelp}), the \textsc{q} key and the \textsc{Esc} key should belong to a function that exits the current mode (Note that the \textsc{Esc} key may be recognized as input only after a delay of about a second.), the \textsc{Q} key should belong to a function that exits the browse application (see Section \ref{BrowseData.actions.QuitMode}), the \textsc{F2} key should belong to a function that saves the current window contents in a
global variable (see Section \ref{BrowseData.actions.SaveWindow}), and the \textsc{E} key should belong to a function that enters a break loop (see Section~\ref{BrowseData.actions.Error}). The \textsc{Enter} and \textsc{Return} keys should belong to a ``click'' on a selected table entry, and if a category row is selected then they should
expand/collapse this category. 

 When the first characters of an admissible input have been entered, one can
delete the last entered character via the \textsc{Delete} and \textsc{Backspace} keys. It is not possible to make these keys part of an admissible input. 

 Each such function is wrapped into a record with the components \texttt{action} (the function itself) and \texttt{helplines} (a list of attribute lines that describes what the function does). \index{action record of a browse table} The help lines are used by the help feature of \texttt{NCurses.BrowseGeneric}, see Section \ref{BrowseData.actions.ShowHelp}. 

 The action functions need not return anything. Whenever the shown screen shall
be recomputed after the function call, the component \texttt{dynamic.changed} of the browse table must be set to \texttt{true} by the action functions. }

  
\section{\textcolor{Chapter }{Modes in Browse Tables}}\label{sec:modes}
\logpage{[ 5, 2, 0 ]}
{
  \index{mode of a browse table} In different situations, different inputs may be admissible for the same
browse table, and different functions may belong to the same input. For
example, the meaning of ``moving down'' can be different depending on whether a cell is selected or not. 

 The set of admissible user inputs and corresponding functions for a particular
situation is collected in a \emph{mode} of the browse table. (There should be no danger to mix up this notion of mode
with the ``visual mode'' introduced in Section~\ref{sec:intro}.) A mode is represented by a record with the components \texttt{name} (a string used to associate the mode with the components of \texttt{header}, \texttt{headerLength}, \texttt{footer}, \texttt{footerLength}, \texttt{Click}, and for the help screen), \texttt{flag} (a string that describes properties of the mode but that can be equal for
different modes), \texttt{actions} (a list of records describing the navigation steps that are admissible in the
mode, see Section~\ref{sec:actions}), and \texttt{ShowTables} (the function used to eventually print the current window contents, the
default is \texttt{BrowseData.ShowTables}). \index{BrowseData.ShowTables} Due to the requirement that each admissible user input uniquely determines a
corresponding function, no admissible user input can be a prefix of another
admissible input, for the same mode. 

 Navigation steps (see Section \ref{sec:actions}) can change the current mode or keep the mode. It is recommended that each
mode has an action to leave this mode; also an action to leave the browse
table application is advisable. 

 In a browse table, all available modes are stored in the component \texttt{work.availableModes}, whose value is a list of mode records. The value of the component \texttt{dynamic.activeModes} is a list of mode records that is used as a stack: The \emph{current mode} is the last entry in this list, changing the current mode is achieved by
unbinding the last entry (so one returns to the mode from which the current
mode had been entered by adding it to the list), by adding a new mode record
(so one can later return to the current mode), or by replacing the last entry
by another mode record. As soon as the \texttt{dynamic.activeModes} list becomes empty, the browse table application is left. (In this situation,
if the browse table had been entered from the \textsf{GAP} prompt then visual mode is left, and one returns to the \textsf{GAP} prompt.) 

 The following modes are predefined by the \textsf{Browse} package. Each of these modes admits the user inputs \textsc{?}, \textsc{F1}, \textsc{q}, \textsc{Esc}, \textsc{Q}, \textsc{F2}, and \textsc{E} that have been mentioned in Section \ref{sec:actions}. 
\begin{description}
\item[{browse}]  This mode admits scrolling of the browse table by a cell or by a screen,
searching for a string, selecting a row, a column, or an entry, and expanding
or collapsing all category rows. 
\item[{help}]  This mode is entered by calling \texttt{BrowseData.ShowHelpTable}; it shows a help window concerning the actions available in the mode from
which the \texttt{help} mode was entered. The \texttt{help} mode admits scrolling in the help table by a cell or by a screen. See Section \ref{BrowseData.actions.ShowHelp} for details. 
\item[{select{\textunderscore}entry}]  In this mode, one table cell is regarded as selected; this cell is highlighted
using the attribute in the component \texttt{work.startSelect} as a prefix of each attribute line, see the remark in Section \ref{NCurses.IsAttributeLine}. The mode admits moving the selection by one cell in the four directions,
searching for a string and for further occurrences of this string, expanding
or collapsing the current category row or all category rows, and executing the ``click'' function of this mode, provided that the component \texttt{work.Click.( "select{\textunderscore}entry" )} of the browse table is bound. 
\item[{select{\textunderscore}row}]  This is like the \texttt{select{\textunderscore}entry} mode, except that a whole row of the browse table is highlighted. Searching is
restricted to the selected row, and ``click'' refers to the function \texttt{work.Click.( "select{\textunderscore}row" )}. 
\item[{select{\textunderscore}row{\textunderscore}and{\textunderscore}entry}]  This is a combination of the \texttt{select{\textunderscore}entry} mode and the \texttt{select{\textunderscore}row} mode. 
\item[{select{\textunderscore}column}]  This is like the \texttt{select{\textunderscore}row} mode, just a column is selected not a row. 
\item[{select{\textunderscore}column{\textunderscore}and{\textunderscore}entry}]  This is like the \texttt{select{\textunderscore}row{\textunderscore}and{\textunderscore}entry} mode, just a column is selected not a row. 
\end{description}
 }

  
\section{\textcolor{Chapter }{Browse Applications}}\label{sec:applications}
\logpage{[ 5, 3, 0 ]}
{
  The data in a browse table together with the set of its available modes and
the stack of active modes forms a browse application. So the part of or all
functionality of the \textsf{Browse} package can be available (``standard application''), or additional functionality can be provided by extending available modes or
adding new modes. 

 When \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) has been called with the browse table \mbox{\texttt{t}}, say, the following loop is executed. 
\begin{description}
\item[{1.}]  If the list \mbox{\texttt{t}}\texttt{.dynamic.activeModes} is empty then exit the browse table, and if the component \mbox{\texttt{t}}\texttt{.dynamic.Return} is bound then return its value. Otherwise proceed with step 2. 
\item[{2.}]  If \mbox{\texttt{t}}\texttt{.dynamic.changed} is \texttt{true} then call the \texttt{ShowTables} function of the current mode; this causes a redraw of the window that shows
the browse table. Then go to step 3. 
\item[{3.}]  Get one character of user input. If then the current user input string is the
name of an action of the current mode then call the corresponding action
function and go to step 1; if the current user input string is just a prefix
of the name of some actions of the current mode then go to step 3; if the
current user input string is not a prefix of any name of an action of the
current mode then discard the last read character and go to step 3. 
\end{description}
 When one designs a new application, it may be not obvious whether some
functionality shall be implemented via one mode or via several modes. As a
rule of thumb, introducing a new mode is recommended when one needs a new set
of admissible actions in a given situation, and also if one wants to allow the
user to perform some actions and then to return to the previous status. }

  
\section{\textcolor{Chapter }{Predefined Browse Functionalities}}\label{sec:browse_avail}
\logpage{[ 5, 4, 0 ]}
{
  

\subsection{\textcolor{Chapter }{BrowseData}}
\logpage{[ 5, 4, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseData\index{BrowseData@\texttt{BrowseData}}
\label{BrowseData}
}\hfill{\scriptsize (global variable)}}\\


 This is the record that contains the global data used by the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}). The components are \texttt{actions}, \texttt{defaults}, and several capitalized names for which the values are functions. 

 \texttt{BrowseData.actions} is a record containing the action records that are provided by the package,
see Section~\ref{sec:actions}. These actions are used in standard applications of \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}). Of course there is no problem with using actions that are not stored in \texttt{BrowseData.actions}. 

 \texttt{BrowseData.defaults} is a record that contains the defaults for the browse table used as the first
argument of \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}). Important components have been described above, see~\texttt{BrowseData.IsBrowseTable} (\ref{BrowseData.IsBrowseTable}), in the sense that these components provide default values of \texttt{work} components in browse tables. Here is a list of further interesting components. 

 The following components are provided in \texttt{BrowseData.defaults.work}. 

 
\begin{description}
\item[{\texttt{windowParameters}}]  is a list of four nonnegative integers, denoting the arguments of \texttt{NCurses.newwin} for the window in which the browse table shall be shown. The default is \texttt{[ 0, 0, 0, 0 ]}, i.~e., the window for the browse table is the full screen. 
\item[{\texttt{minyx}}]  is a list of length two, the entries must be either nonnegative integers,
denoting the minimal number of rows and columns that are required by the
browse table, or unary functions that return these values when they are
applied to the browse table; this is interesting for applications that do not
support scrolling, or for applications that may have large row or column
labels tables. The default is a list with two functions, the return value of
the first function is the sum of the heights of the table header, the column
labels table, the first table row, and the table footer, and the return value
of the second function is the sum of widths of the row labels table and the
width of the first column. (If the header/footer is given by a function then
this part of the table is ignored in the \texttt{minyx} default.) 
\item[{\texttt{align}}]  is a substring of \texttt{"bclt"}, which describes the alignment of the browse table in the window. The meaning
and the default are the same as for \texttt{BrowseData.IsBrowseTableCellData} (\ref{BrowseData.IsBrowseTableCellData}). (Of course this is relevant only if the table is smaller than the window.) 
\item[{\texttt{headerLength}}]  describes the lengths of the headers in the modes for which \texttt{header} functions are provided. The value is a record whose component names are names
of modes and the corresponding components are nonnegative integers. This
component is ignored if the \texttt{header} component is unbound or bound to a list, missing values are computed by calls
to the corresponding \texttt{header} function as soon as they are needed. 
\item[{\texttt{footerLength}}]  corresponds to \texttt{footer} in the same way as \texttt{headerLength} to \texttt{header}. 
\item[{\texttt{Main}}]  if bound to a function then this function can be used to compute missing
values for the component \texttt{main}; this way one can avoid computing/storing all \texttt{main} values at the same time. The access to the entries of the main matrix is
defined as follows: If \texttt{mainFormatted[i][j]} is bound then take it, if \texttt{main[i][j]} is bound then take it and compute the formatted version, if \texttt{Main} is a function then call it with arguments the browse table, \texttt{i}, and \texttt{j}, and compute the formatted version, otherwise compute the formatted version
of \texttt{work.emptyCell}. (For the condition whether entries in \texttt{mainFormatted} can be bound, see below in the description of the component \texttt{cacheEntries}.) 
\item[{\texttt{cacheEntries}}]  describes whether formatted values of the entries in the matrices given by the
components \texttt{corner}, \texttt{labelsCol}, \texttt{labelsRow}, \texttt{main}, and of the corresponding row and column separators shall be stored in the
components \texttt{cornerFormatted}, \texttt{labelsColFormatted}, \texttt{labelsRowFormatted}, and \texttt{mainFormatted}. The value must be a Boolean, the default is \texttt{false}; it should be set to \texttt{true} only if the tables are reasonably small. 
\item[{\texttt{cornerFormatted}}]  is a list of lists of formatted entries corresponding to the \texttt{corner} component. Each entry is either an attribute line or a list of attribute lines
(with the same number of displayed characters), the values can be computed
from the input format with \texttt{BrowseData.FormattedEntry}. \index{BrowseData.FormattedEntry} The entries are stored in this component only if the component \texttt{cacheEntries} has the value \texttt{true}. The default is an empty list. 
\item[{\texttt{labelsColFormatted}}]  corresponds to \texttt{labelsCol} in the same way as \texttt{cornerFormatted} to \texttt{corner}. 
\item[{\texttt{labelsRowFormatted}}]  corresponds to \texttt{labelsRow} in the same way as \texttt{cornerFormatted} to \texttt{corner}. 
\item[{\texttt{mainFormatted}}]  corresponds to \texttt{main} in the same way as \texttt{cornerFormatted} to \texttt{corner}. 
\item[{\texttt{m0}}]  is the maximal number of rows in the column labels table. If this value is not
bound then it is computed from the components \texttt{corner} and \texttt{labelsCol}. 
\item[{\texttt{n0}}]  is the maximal number of columns in \texttt{corner} and \texttt{labelsRow}. 
\item[{\texttt{m}}]  is the maximal number of rows in \texttt{labelsRow} and \texttt{main}. This value \emph{must} be set in advance if the values of \texttt{main} are computed using a \texttt{Main} function, and if the number of rows in \texttt{main} is larger than that in \texttt{labelsRow}. 
\item[{\texttt{n}}]  is the maximal number of columns in \texttt{labelsCol} and \texttt{main}. This value \emph{must} be set in advance if the values of \texttt{main} are computed using a \texttt{Main} function, and if the number of columns in \texttt{main} is larger than that in \texttt{labelsCol}. 
\item[{\texttt{heightLabelsCol}}]  is a list of $2$ \texttt{m0}$ + 1$ nonnegative integers, the entry at position $i$ is the maximal height of the entries in the $i$-th row of \texttt{cornerFormatted} and \texttt{labelsColFormatted}. Values that are not bound are computed on demand from the table entries,
with the function \texttt{BrowseData.HeightLabelsCol}. \index{BrowseData.HeightLabelsCol} (So if one knows the needed heights in advance, it is advisable to set the
values, in order to avoid that formatted table entries are computed just for
computing their size.) The default is an empty list. 
\item[{\texttt{widthLabelsRow}}]  is the corresponding list of $2$ \texttt{n0}$ + 1$ maximal widths of entries in \texttt{cornerFormatted} and \texttt{labelsRowFormatted}. 
\item[{\texttt{heightRow}}]  is the corresponding list of $2$ \texttt{m}$ + 1$ maximal heights of entries in \texttt{labelsRowFormatted} and \texttt{mainFormatted}. 
\item[{\texttt{widthCol}}]  is the corresponding list of $2$ \texttt{n}$ + 1$ maximal widths of entries in \texttt{labelsColFormatted} and \texttt{mainFormatted}. 
\item[{\texttt{emptyCell}}]  is a table cell data object to be used as the default for unbound positions in
the four matrices. The default is the empty list. 
\item[{\texttt{sepCategories}}]  is an attribute line to be used repeatedly as a separator below expanded
category rows. The default is the string \texttt{"-"}. 
\item[{\texttt{startCollapsedCategory}}]  is a list of attribute lines to be used as prefixes of unhidden but collapsed
category rows. For categories of level $i$, the last bound entry before the $(i+1)$-th position is used. The default is a list of length one, the entry is the
boldface variant of the string \texttt{"> "}, so collapsed categories on different levels are treated equally. 
\item[{\texttt{startExpandedCategory}}]  is a list of attribute lines to be used as prefixes of expanded category rows,
analogously to \texttt{startCollapsedCategory}. The default is a list of length one, the entry is the boldface variant of
the string \texttt{"* "}, so expanded categories on different levels are treated equally. 
\item[{\texttt{startSelect}}]  is an attribute line to be used as a prefix of each attribute line that
belongs to a selected cell. The default is to switch the attribute \texttt{NCurses.attrs.STANDOUT} on, see Section~\ref{ssec:ncursesAttrs}. 
\item[{\texttt{Click}}]  is a record whose component names are names of available modes of the browse
table. The values are unary functions that take the browse table as their
argument. If the action \texttt{Click} is available in the current mode and the corresponding input is entered then
the function in the relevant component of the \texttt{Click} record is called. 
\item[{\texttt{availableModes}}]  is a list whose entries are the mode records that can be used when one
navigates through the browse table, see Section \ref{sec:modes}. 
\item[{\texttt{SpecialGrid}}]  is a function that takes a browse table and a record as its arguments. It is
called by \texttt{BrowseData.ShowTables} after the current contents of the window has been computed, and it is intended
to draw an individual grid into the table that fits better than anything that
can be specified in terms of row and column separators. (If other functions
than \texttt{BrowseData.ShowTables} are used in some modes of the browse table, these functions must deal with
this aspect themselves.) The default is to do nothing. 
\end{description}
 The following components are provided in \texttt{BrowseData.defaults.dynamic}. 
\begin{description}
\item[{\texttt{changed}}]  is a Boolean that must be set to \texttt{true} by action functions whenever a refresh of the window is necessary; it is
automatically reset to \texttt{false} after the refresh. 
\item[{\texttt{indexRow}}]  is a list of positive integers. The entry $k$ at position $i$ means that the $k$-th row in the \texttt{mainFormatted} table is shown as the $i$-th row. Note that depending on the current status of the browse table, the
rows of \texttt{mainFormatted} (and of \texttt{main}) may be permuted, or it may even happen that a row in \texttt{mainFormatted} is shown several times, for example under different category rows. It is
assumed (as a ``sort convention'') \index{sort convention} that the \emph{even} positions in \texttt{indexRow} point to \emph{even} numbers, and that the subsequent \emph{odd} positions (corresponding to the following separators) point to the subsequent \emph{odd} numbers. The default value is the list $[ 1, 2, \ldots, m ]$, where $m$ is the number of rows in \texttt{mainFormatted} (including the separator rows, so $m$ is always odd). 
\item[{\texttt{indexCol}}]  is the analogous list of positive integers that refers to columns. 
\item[{\texttt{topleft}}]  is a list of four positive integers denoting the current topleft position of
the main table. The value $[ i, j, k, l ]$ means that the topleft entry is indexed by the $i$-th entry in \texttt{indexRow}, the $j$-th entry in \texttt{indexCol}, and the $k$-th row and $l$-th column inside the corresponding cell. The default is $[ 1, 1, 1, 1 ]$. 
\item[{\texttt{isHiddenRow}}]  is a list of Booleans, of the same length as the \texttt{indexRow} value. If the entry at position $i$ is \texttt{true} then the $i$-th row is currently not shown; a typical situation is that the row belongs to
a collapsed category row. It is assumed (as a ``hide convention'') \index{hide convention} that the value at any even position equals the value at the subsequent odd
position. The default is that all entries are \texttt{false}. 
\item[{\texttt{isHiddenCol}}]  is the corresponding list for \texttt{indexCol}. 
\item[{\texttt{activeModes}}]  is a list of mode records that are contained in the \texttt{availableModes} list of the \texttt{work} component of the browse table. The current mode is the last entry in this
list. The default depends on the application, \texttt{BrowseData.defaults} prescribes the list containing only the mode with \texttt{name} component \texttt{"browse"}. 
\item[{\texttt{selectedEntry}}]  is a list $[ i, j ]$. If $i = j = 0$ then no table cell is selected, otherwise $i$ and $j$ are the row and column index of the selected cell. (Note that $i$ and $j$ are always even.) The default is $[ 0, 0 ]$. 
\item[{\texttt{selectedCategory}}]  is a list $[ i, l ]$. If $i = l = 0$ then no category row is selected, otherwise $i$ and $l$ are the row index and the level of the selected category row. (Note that $i$ is always even.) The default is $[ 0, 0 ]$. 
\item[{\texttt{searchString}}]  is the last string for which the user has searched in the table. The default
is the empty string. 
\item[{\texttt{searchParameters}}]  is a list of parameters that are modified by the function \texttt{BrowseData.SearchStringWithStartParameters}. \index{SearchStringWithStartParameters} If one sets these parameters in a search then these values hold also for
subsequent searches. So it may make sense to set the parameters to personally
preferred ones. 
\item[{\texttt{sortFunctionForColumnsDefault}}]  is a function with two arguments used to compare two entries in the same
column of the main table (or two category row values). The default is the
function \texttt{{\textbackslash}{\textless}}. (Note that this default may be not meaningful if some of the rows or columns
contain strings representing numbers.) 
\item[{\texttt{sortFunctionForRowsDefault}}]  is the analogous function for comparing two entries in the same row of the
main table. 
\item[{\texttt{sortFunctionsForRows}}]  is a list of comparison functions, if the $i$-th entry is bound then it replaces the \texttt{sortFunctionForRowsDefault} value when the table is sorted w.r.t. the $i$-th row. 
\item[{\texttt{sortFunctionsForColumns}}]  is the analogous list of functions for the case that the table is sorted
w.r.t. columns. 
\item[{\texttt{sortParametersForRowsDefault}}]  is a list of parameters for sorting the main table w.r.t. entries in given
rows, e.~g., whether one wants to sort ascending or descending. 
\item[{\texttt{sortParametersForColumnsDefault}}]  is the analogous list of parameters for sorting w.r.t. given columns. In
addition to the parameters for rows, also parameters concerning category rows
are available, e.~g., whether the data columns that are transformed into category rows shall be
hidden afterwards or not. 
\item[{\texttt{sortParametersForRows}}]  is a list that contains ar position $i$, if bound, a list of parameters that shall replace those in \texttt{sortParametersForRowsDefault} when the table is sorted w.r.t. the $i$-th row 
\item[{\texttt{sortParametersForColumns}}]  is the analogous list of parameters lists for sorting w.r.t. columns. 
\item[{\texttt{categories}}]  describes the current category rows. The value is a list $[ l_1, l_2 ]$ where $l_1$ is a \emph{sorted} list $[ i_1, i_2, ..., i_k ]$ of positive integers and $l_2$ is a list of length $k$ where the $j$-th entry has the form $[ i_j, l_j, v_j, s_j, h_j ]$. This means that above the $i_j$-th table row (w.r.t. the component \texttt{indexRow}), there is a category row at level $l_j$, which is hidden if $h_j$ is \texttt{true}, and otherwise the shown value is the attribute line $v_j$ and the separator below the category row is a repetition of $s_j$. The default value is \texttt{[ [], [] ]}. (Note that this ``hide convention''\index{hide convention} makes sense mainly if together with a hidden category row, also the category
rows on higher levels and the corresponding data rows are hidden -- but this
property is \emph{not} checked.) Categories are computed with the \texttt{CategoryValue} function in the \texttt{work} component of the browse table. 
\item[{\texttt{log}}]  describes the session log which is currently written. The value is a list of
positive integers, representing the user inputs in the current session. When \textsf{GAP} returns from a call to \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}), one can access the log list of the user interactions in the browse table as
the value of its component \texttt{dynamic.log}. 

 If \texttt{BrowseData.logStore} \index{BrowseData.logStore} had been set to \texttt{true} before \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) had been called then the list can also be accessed as the value of \texttt{BrowseData.log}. \index{BrowseData.log} If \texttt{BrowseData.logStore} is unbound or has a value different from \texttt{true} then \texttt{BrowseData.log} is not written. (This can be interesting in the case of browse table
applications where the user does not get access to the browse table itself.) 
\item[{\texttt{replay}}]  describes the non-interactive input for the current browse table. The value is
a record with the components \texttt{logs} (a dense list of records, the default is an empty list) and \texttt{pointer} (a positive integer, the default is $1$). If \texttt{pointer} is a position in \texttt{logs} then currently the \texttt{pointer}-th record is processed, otherwise the browse table has exhausted its
non-interactive part, and requires interactive input. The records in \texttt{log} have the components \texttt{steps} (a list of user inputs, the default is an empty list), \texttt{position} (a positive integer denoting the current position in the \texttt{steps} list if the log is currently processed, the default is $1$), \texttt{replayInterval} (the timeout between two steps in milliseconds if the log is processed, the
default is $0$), and \texttt{quiet} (a Boolean, \texttt{true} if the steps shall not be shown on the screen until the end of the log is
reached, the default is \texttt{false}). 
\end{description}
 }

 

\subsection{\textcolor{Chapter }{BrowseData.SetReplay}}
\logpage{[ 5, 4, 2 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseData.SetReplay( data )\index{BrowseData.SetReplay@\texttt{BrowseData.SetReplay}}
\label{BrowseData.SetReplay}
}\hfill{\scriptsize (function)}}\\


 This function sets and resets the value of \texttt{BrowseData.defaults.dynamic.replay}. 

 When \texttt{BrowseData.SetReplay} is called with a list \mbox{\texttt{data}} as its argument then the entries are assumed to describe user inputs for a
browse table for which \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) will be called afterwards, such that replay of the inputs runs. (Valid input
lists can be obtained from the component \texttt{dynamic.log} of the browse table in question.) 

 When \texttt{BrowseData.SetReplay} is called with the only argument \texttt{false}, the component is unbound (so replay is disabled, and thus calls to \texttt{NCurses.BrowseGeneric} will require interactive user input). 

 The replay feature should be used by initially setting the input list, then
running the replay (perhaps several times), and finally unbinding the inputs,
such that subsequent uses of other browse tables do not erroneously expect
their input in \texttt{BrowseData.defaults.dynamic.replay}. 

 Note that the value of \texttt{BrowseData.defaults.dynamic.replay} is used in a call to \texttt{NCurses.BrowseGeneric} only if the browse table in question does not have a component \texttt{dynamic.replay} before the call. }

 

\subsection{\textcolor{Chapter }{BrowseData.AlertWithReplay}}
\logpage{[ 5, 4, 3 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseData.AlertWithReplay( t, messages[, attrs] )\index{BrowseData.AlertWithReplay@\texttt{BrowseData.AlertWithReplay}}
\label{BrowseData.AlertWithReplay}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 an integer representing a (simulated) user input. 



 The function \texttt{BrowseData.AlertWithReplay} is a variant of \texttt{NCurses.Alert} (\ref{NCurses.Alert}) that is adapted for the replay feature of the browse table \mbox{\texttt{t}}, see Section \ref{sec:features}. The arguments \mbox{\texttt{messages}} and \mbox{\texttt{attrs}} are the same as the corresponding arguments of \texttt{NCurses.Alert}, the argument \texttt{timeout} of \texttt{NCurses.Alert} is taken from the browse table \mbox{\texttt{t}}, as follows. If \texttt{BrowseData.IsDoneReplay}\index{BrowseData.IsDoneReplay} returns \texttt{true} for \texttt{t} then \texttt{timeout} is zero, so a user input is requested for closing the alert box; otherwise the
requested input character is fetched from \texttt{t.dynamic.replay}. 

 No alert box is shown if \texttt{BrowseData.IsQuietSession} \index{BrowseData.IsQuietSession} returns \texttt{true} when called with \mbox{\texttt{t}}\texttt{.dynamic.replay}, otherwise the alert box is closed after the time (in milliseconds) that is
given by the \texttt{replayInterval} value of the current entry in \mbox{\texttt{t}}\texttt{.dynamic.replay.logs}. 

 The function returns either the return value of the call to \texttt{NCurses.Alert} (in the interactive case) or the value that was fetched from the current
replay record (in the replay case). }

 

\subsection{\textcolor{Chapter }{BrowseData.actions.ShowHelp}}
\logpage{[ 5, 4, 4 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseData.actions.ShowHelp\index{BrowseData.actions.ShowHelp@\texttt{BrowseData.actions.ShowHelp}}
\label{BrowseData.actions.ShowHelp}
}\hfill{\scriptsize (global variable)}}\\


 There are two predefined ways for showing an overview of the admissible inputs
and their meaning in the current mode of a browse table. The function \texttt{BrowseData.ShowHelpTable} \index{BrowseData.ShowHelpTable} displays this overview in a browse table (using the \texttt{help} mode), and \texttt{BrowseData.ShowHelpPager} \index{BrowseData.ShowHelpPager} uses \texttt{NCurses.Pager}. 

 Technically, the only difference between these two functions is that \texttt{BrowseData.ShowHelpTable} supports the replay feature of \texttt{NCurses.BrowseGeneric}, whereas \texttt{BrowseData.ShowHelpPager} simply does not call the pager in replay situations. 

 The action record \texttt{BrowseData.actions.ShowHelp} is associated with the user inputs \textsc{?} or \textsc{F1} in standard \texttt{NCurses.BrowseGeneric} applications, and it is recommended to do the same in other \texttt{NCurses.BrowseGeneric} applications. This action calls the function stored in the component \texttt{work.ShowHelp} of the browse table, the default (i.~e., the value of \texttt{BrowseData.defaults.work.ShowHelp}) is \texttt{BrowseData.ShowHelpTable}. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> xpl1.work.ShowHelp:= BrowseData.ShowHelpPager;;
  gap> BrowseData.SetReplay( "?Q" );
  gap> Unbind( xpl1.dynamic );
  gap> NCurses.BrowseGeneric( xpl1 );
  gap> xpl1.work.ShowHelp:= BrowseData.ShowHelpTable;;
  gap> BrowseData.SetReplay( "?dQQ" );
  gap> Unbind( xpl1.dynamic );
  gap> NCurses.BrowseGeneric( xpl1 );
  gap> BrowseData.SetReplay( false );
  gap> Unbind( xpl1.dynamic );
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{BrowseData.actions.SaveWindow}}
\logpage{[ 5, 4, 5 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseData.actions.SaveWindow\index{BrowseData.actions.SaveWindow@\texttt{BrowseData.actions.SaveWindow}}
\label{BrowseData.actions.SaveWindow}
}\hfill{\scriptsize (global variable)}}\\


 The function \texttt{BrowseData.actions.SaveWindow.action} asks the user to enter the name of a global \textsf{GAP} variable, using \texttt{NCurses.GetLineFromUser} (\ref{NCurses.GetLineFromUser}). If this variable name is valid and if no value is bound to this variable yet
then the current contents of the window of the browse table that is given as
the argument is saved in this variable, using \texttt{NCurses.SaveWin} (\ref{NCurses.SaveWin}). }

 

\subsection{\textcolor{Chapter }{BrowseData.actions.QuitMode}}
\logpage{[ 5, 4, 6 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseData.actions.QuitMode\index{BrowseData.actions.QuitMode@\texttt{BrowseData.actions.QuitMode}}
\label{BrowseData.actions.QuitMode}
}\hfill{\scriptsize (global variable)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseData.actions.QuitTable\index{BrowseData.actions.QuitTable@\texttt{BrowseData.actions.QuitTable}}
\label{BrowseData.actions.QuitTable}
}\hfill{\scriptsize (global variable)}}\\


 The function \texttt{BrowseData.actions.QuitMode.action} unbinds the current mode in the browse table that is given as its argument
(see Section \ref{sec:modes}), so the browse table returns to the mode from which this mode had been
called. If the current mode is the only one, first the user is asked for
confirmation whether she really wants to quit the table; only if the \textsc{y} key is hit, the last mode is unbound. 

 The function \texttt{BrowseData.actions.QuitTable.action} unbinds all modes in the browse table that is given as its argument, without
asking for confirmation; the effect is to exit the browse application (see
Section \ref{sec:applications}). }

 

\subsection{\textcolor{Chapter }{BrowseData.actions.Error}}
\logpage{[ 5, 4, 7 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseData.actions.Error\index{BrowseData.actions.Error@\texttt{BrowseData.actions.Error}}
\label{BrowseData.actions.Error}
}\hfill{\scriptsize (global variable)}}\\


 After \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) has been called, interrupting by hitting the \textsc{Ctrl-C} keys is not possible. It is recommended to provide the action \texttt{BrowseData.actions.Error} for each mode of a \texttt{NCurses.BrowseGeneric} application, which enters a break loop and admits returning to the
application. The recommended user input for this action is the \textsc{E} key. }

 }

 }

 
\chapter{\textcolor{Chapter }{Examples of Applications based on \texttt{NCurses.BrowseGeneric} }}\label{ch:appl}
\logpage{[ 6, 0, 0 ]}
{
  This chapter introduces the operation \texttt{Browse} (\ref{Browse}) and lists several examples how the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) can be utilized for rendering \textsf{GAP} related data or for playing games. Each section describes the relevant \textsf{GAP} functions and briefly sketches the technical aspects of the implementation;
more details can be found in the \textsf{GAP} files. 

 Only Section \ref{sec:tomdisp} describes a standard application in the sense of the introduction to Chapter \ref{chap:browse_user}, 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 \ref{chap:browse_prg}. 
\section{\textcolor{Chapter }{The Operation \texttt{Browse}}}\label{sec:browseoper}
\logpage{[ 6, 1, 0 ]}
{
  

\subsection{\textcolor{Chapter }{Browse}}
\logpage{[ 6, 1, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Browse( obj[, arec] )\index{Browse@\texttt{Browse}}
\label{Browse}
}\hfill{\scriptsize (operation)}}\\


 This operation displays the \textsf{GAP} object \mbox{\texttt{obj}} in a nice, formatted way, similar to the operation \texttt{Display} (\textbf{Reference: Display}). The difference is that \texttt{Browse} is intended to use \texttt{ncurses} facilities. 

 Currently there are methods for character tables (see~\texttt{Browse} (\ref{Browse:for character tables})) and for tables of marks (see~\texttt{Browse} (\ref{Browse:for tables of marks})). }

 }

 
\section{\textcolor{Chapter }{Character Table Display}}\label{sec:ctbldisp}
\logpage{[ 6, 2, 0 ]}
{
  The \textsf{GAP} library provides a \texttt{Display} (\textbf{Reference: Display}) method for character tables that breaks the table into columns fitting on the
screen. \textsf{Browse} provides an alternative, using the standard facilities of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}), i.~e., one can scroll in the matrix of character values, searching and sorting
are provided etc. 

 The \texttt{Browse} method for character tables can be called instead of \texttt{Display}. For convenience, one can additionally make this function the default \texttt{Display} method for character tables, by assigning it to the \texttt{Display} component in the global record \texttt{CharacterTableDisplayDefaults.User}, see~ (\textbf{Reference: Printing Character Tables}); for example, one can do this in one's \texttt{.gaprc} file, see~ (\textbf{Reference: The .gaprc file}). (This can be undone by unbinding the component \texttt{CharacterTableDisplayDefaults.User.Display}.) 

\subsection{\textcolor{Chapter }{Browse (for character tables)}}
\logpage{[ 6, 2, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Browse( tbl[, options] )\index{Browse@\texttt{Browse}!for character tables}
\label{Browse:for character tables}
}\hfill{\scriptsize (method)}}\\


 This method displays the character table \mbox{\texttt{tbl}} in a window. The optional record \mbox{\texttt{options}} describes what shall be displayed, the supported components and the default
values are described in~ (\textbf{Reference: Printing Character Tables}). 

 The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> BrowseData.SetReplay( Concatenation(
  >         # scroll in the table
  >         "DRULdddddrrrrrlluu",
  >         # select an entry and move it around
  >         "seddrruuuddlll",
  >         # search for the pattern 135 (six times)
  >         "/135", [ NCurses.keys.ENTER ], "nnnnn",
  >         # deselect the entry, select the first column
  >         "qLsc",
  >         # sort and categorize by this column
  >         "sc",
  >         # select the first row, move down the selection
  >         "srdddd",
  >         # expand the selected category, scroll the selection down
  >         "xd",
  >         # and quit the application
  >         "Q" ) );
  gap> Browse( CharacterTable( "HN" ) );
  gap> BrowseData.SetReplay( false );
\end{Verbatim}
 

 \emph{Implementation remarks}: The first part of the code in the \texttt{Browse} method for character tables is almost identical with the code for extracting
the data to be displayed from the input data in the \textsf{GAP} library function \texttt{CharacterTableDisplayDefault}. 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. 

 Due to an extension of the standard modes in \texttt{BrowseData} (\ref{BrowseData}) by two new actions, a pager can be opened that gives an overview of all all
irrationalities in the table, and an overview of all those irrationalities
that have been shown on the screen in the current call, respectively. The
corresponding user inputs are the \textsc{I} and the \textsc{i} 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 defaults \texttt{Display} method for character tables; this is in general \emph{not} the case for example when a row-wise search in the table is performed.) 

 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 \texttt{Main} function in the \texttt{work} 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 \texttt{lib/ctbldisp.g} of the package. }

 }

 
\section{\textcolor{Chapter }{Table of Marks Display}}\label{sec:tomdisp}
\logpage{[ 6, 3, 0 ]}
{
  The \textsf{GAP} library provides a \texttt{Display} method for tables of marks that breaks the table into columns fitting on the
screen. Similar to the situation with character tables, see Section~\ref{sec:ctbldisp}, but with a much simpler implementation, \textsf{Browse} provides an alternative based on the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}). 

 \texttt{Browse} can be called instead of \texttt{Display} for tables of marks, cf.~ (\textbf{Reference: Printing Tables of Marks}). 

\subsection{\textcolor{Chapter }{Browse (for tables of marks)}}
\logpage{[ 6, 3, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Browse( tom[, options] )\index{Browse@\texttt{Browse}!for tables of marks}
\label{Browse:for tables of marks}
}\hfill{\scriptsize (method)}}\\


 This method displays the table of marks \mbox{\texttt{tom}} in a window. The optional record \mbox{\texttt{options}} describes what shall be displayed, the supported components and the default
values are described in~ (\textbf{Reference: Printing Tables of Marks}). 

 The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> BrowseData.SetReplay( Concatenation(
  >         # scroll in the table
  >         "DDRRR",
  >         # search for the (exact) value 100 (three times)
  >         "/100",
  >         [ NCurses.keys.DOWN, NCurses.keys.DOWN, NCurses.keys.RIGHT ],
  >         [ NCurses.keys.DOWN, NCurses.keys.DOWN, NCurses.keys.DOWN ],
  >         [ NCurses.keys.RIGHT, NCurses.keys.ENTER ], "nn",
  >         # no more occurrences of 100, confirm
  >         [ NCurses.keys.ENTER ],
  >         # and quit the application
  >         "Q" ) );
  gap> Browse( TableOfMarks( "A10" ) );
  gap> BrowseData.SetReplay( false );
\end{Verbatim}
 

 \emph{Implementation remarks}: 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 \texttt{Main} function in the \texttt{work} 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 \texttt{"O8+(2)"}, with $11171$ rows and columns, can be shown with \texttt{Browse} in a \textsf{GAP} session requiring about $100$ MB.) 

 The code can be found in the file \texttt{lib/tomdisp.g} of the package. }

 }

 
\section{\textcolor{Chapter }{Table of Contents of \textsf{AtlasRep}}}\label{sec:atlasdisp}
\logpage{[ 6, 4, 0 ]}
{
  The \textsf{GAP} package \textsf{AtlasRep} (see~\cite{AtlasRep}) is an interface to a database of representations and related data. The table
of contents of this database can be displayed via the function \texttt{DisplayAtlasInfo} (\textbf{AtlasRep: DisplayAtlasInfo}) of this package. The \textsf{Browse} package provides an alternative based on the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}); one can scroll, search, and fetch representations for later use. 

\subsection{\textcolor{Chapter }{BrowseAtlasInfo}}
\logpage{[ 6, 4, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseAtlasInfo(  )\index{BrowseAtlasInfo@\texttt{BrowseAtlasInfo}}
\label{BrowseAtlasInfo}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 the list of ``clicked'' representations. 



 This function shows the table of contents of the \textsf{GAP} package \textsf{AtlasRep} in a browse table, cf. Section~ (\textbf{AtlasRep: Accessing Data of the AtlasRep Package}) 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 \texttt{BrowseAtlasInfo}. 

 The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available. 

 The following example shows how \texttt{BrowseAtlasInfo} can be used to fetch permutation representations of the alternating groups $A_5$ and $A_6$: We search for the group name \texttt{"A5"} in the overview table, and the first cell in the table row for $A_5$ becomes selected; hitting the \textsc{Enter} 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 \textsc{Enter} 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. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> d:= [ NCurses.keys.DOWN ];;  r:= [ NCurses.keys.RIGHT ];;
  gap> c:= [ NCurses.keys.ENTER ];;
  gap> BrowseData.SetReplay( Concatenation(
  >        "/A5",         # Find the string A5 ...
  >        d, d, r,       # ... such that just the word matches,
  >        c,             # start the search,
  >        c,             # click the table entry A5,
  >        d,             # move down by one row,
  >        c,             # click the row for this representation,
  >        d, d,          # move down by two rows,
  >        c,             # click the table entry A6,
  >        c,             # click the first row,
  >        "Q" ) );       # and quit the application.
  gap> tworeps:= BrowseAtlasInfo();;
  gap> BrowseData.SetReplay( false );
  gap> if fail in tworeps then
  >      Print( "no access to the Web ATLAS\n" );
  >    else
  >      Print( List( tworeps, x -> x.identifier[1] ), "\n" );
  >    fi;
  [ "A5", "A6" ]
\end{Verbatim}
 

 \emph{Implementation remarks}: 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. When a row is selected, the ``click'' functionality opens a new window (via a second level call to \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric})), 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 \textsf{GAP} package \textsf{AtlasRep} is available. 

 The code can be found in the file \texttt{lib/atlasbrowse.g} of the package. }

 }

 
\section{\textcolor{Chapter }{Access to \textsf{GAP} Manuals -- a Variant}}\label{sec:manualdisp}
\logpage{[ 6, 5, 0 ]}
{
  A \textsf{Browse} 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. 

\subsection{\textcolor{Chapter }{BrowseGapManuals}}
\logpage{[ 6, 5, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseGapManuals( [start] )\index{BrowseGapManuals@\texttt{BrowseGapManuals}}
\label{BrowseGapManuals}
}\hfill{\scriptsize (function)}}\\


 This function displays the contents of the \textsf{GAP} manuals (the main \textsf{GAP} manuals as well as the loaded package manuals) in a window. The optional
argument \mbox{\texttt{start}} describes the initial status, admissible values are the strings \texttt{"inline/collapsed"}, \texttt{"inline/expanded"}, \texttt{"pager/collapsed"}, and \texttt{"pager/expanded"}. 

 In the \texttt{inline} cases, the parts of the manuals are shown in the browse table, and in the \texttt{pager} case, the parts of the manuals are shown in a different window when they are ``clicked'', using the user's favourite help viewer, see  (\textbf{Reference: Changing the Help Viewer}). 

 In the \texttt{collapsed} case, 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 \texttt{expanded} case, all category rows are expanded, and nothing is selected; a typical next
step in the \texttt{inline/expanded} 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 \textsf{GAP}, 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 \texttt{NCurses.Select} (\ref{NCurses.Select}). 

 The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> BrowseData.SetReplay( "xdxdzzzQ" );  # expand a Tutorial section
  gap> BrowseGapManuals( "inline/collapsed" );
  gap> BrowseData.SetReplay( Concatenation(
  >        "/Browse", [ NCurses.keys.ENTER ],  # search for "Browse"
  >        "xdxddxdzzz",                       # expand a section
  >        "Q" ) );                            # and quit
  gap> BrowseGapManuals( "inline/collapsed" );
  gap> BrowseData.SetReplay( false );
\end{Verbatim}
 

 \emph{Implementation remarks}: 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 \textsf{GAP}. 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 \texttt{show} function of the default viewer \texttt{"screen"} (see  (\textbf{Reference: Changing the Help Viewer})) by a function that uses \texttt{NCurses.Pager} (\ref{NCurses.Pager}). Note that in the case that the manual bit in question fits into one screen,
the default \texttt{show} 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 \textsf{GAPDoc} manuals (using \textsc{Esc} sequences) is stripped off instead of being transferred to the attribute lines
that arise, because of the highlighting problem mentioned in Section~\ref{NCurses.IsAttributeLine}. 

 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 \emph{not} regarded as parts of the actual text since they appear already as category
rows; however, the functions of the \textsf{GAP} help system deliver the text \emph{together with} these titles, so these lines must be stripped off afterwards. 

 The category hierarchy representing the tables of contents is created from the \texttt{manual.six} 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 \emph{last} of these category rows, the data rows for the others are empty. (This problem
does not occur in the \textsf{GAPDoc} manual format because this introduces explicit subsection titles, involving
only the \emph{first} of several function definitions.) 

 Also, index entries and sectioning entries in \texttt{manual.six} files of manuals in \textsf{GAPDoc} format are not explicitly distinguished. 

 The code can be found in the file \texttt{lib/manual.g} of the package. }

 }

 
\section{\textcolor{Chapter }{Overview of the \textsf{GAP} Bibliography}}\label{sec:gapbibl}
\logpage{[ 6, 6, 0 ]}
{
  The \textsf{GAP} documentation contains a bibliography of \textsf{GAP} related publications, see~\cite{GAPBibliography}. \textsf{Browse} provides access to this information in \textsf{GAP}, using the standard facilities of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}), i.~e., one can scroll in the list, search for entries, sort by year, sort and
categorize by authors etc. 

 The \textsf{Browse} package contains a (perhaps outdated) version of this bibliography. One can
get an updated version as follows. 

 \texttt{wget -N http://www.gap-system.org/Doc/Bib/gap-publishednicer.bib} 

\subsection{\textcolor{Chapter }{BrowseBibliography}}
\logpage{[ 6, 6, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseBibliography( [bibfiles] )\index{BrowseBibliography@\texttt{BrowseBibliography}}
\label{BrowseBibliography}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 a list of strings representing BibTeX entries. 



 This function shows the list of BibTeX entries in the files given by the strings in the list \mbox{\texttt{bibfiles}}. If no argument is given then the file \texttt{bibl/gap-publishednicer.bib} in the \textsf{Browse} package directory is taken. The return value is a list of strings that contain
the BibTeX entries that have been ``clicked'' in visual mode. 

 The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> # sort and categorize by year, scroll down, expand a category row
  gap> BrowseData.SetReplay( "scrrscsedddddxdddddQ" );
  gap> BrowseBibliography();;
  gap> # sort & categorize by authors, expand all category rows, scroll down
  gap> BrowseData.SetReplay( "scscXseddddddQ" );
  gap> BrowseBibliography();;
  gap> # sort and categorize by journal, search for a journal name, expand
  gap> BrowseData.SetReplay( Concatenation( "scrrrsc/J. Algebra",
  >        [ NCurses.keys.ENTER ], "nxdddQ" ) );
  gap> BrowseBibliography();;
  gap> BrowseData.SetReplay( false );
\end{Verbatim}
 

 \emph{Implementation remarks}: The browse table has a static header, no footer and row labels, one row of
column labels is given by the descriptions of the table columns (authors,
title, year, journal). For categorizing by authors, a special \texttt{CategoryValues} function is provided that distributes the authors to different category rows,
such that each entry appears once for each of its authors in the categorized
table. When a data row or an entry in this row is selected, ``click'' adds the corresponding BibTeX entry to the result list. The width of the title column is preset, in order to
avoid computing all values in advance; note that the contents of this column
is formatted as a paragraph, using the function \texttt{FormatParagraph}. 

 For three columns, the sort parameters are customized as follows: The authors
column does not become hidden when the table is categorized according to this
column, sorting by year yields a descending order, and the category rows
arising from the three columns show the numbers of the data rows that belong
to them. 

 This function requires some of the utilities provided by the \textsf{GAP} package \textsf{GAPDoc} (see~\cite{GAPDoc}), such as \texttt{FormatParagraph}, \texttt{NormalizedWhitespace}, \texttt{NormalizeNameAndKey}, \texttt{ParseBibFiles}, and \texttt{PrintBibAsBib}. 

 The code can be found in the file \texttt{lib/gapbibl.g} of the package. }

 }

 
\section{\textcolor{Chapter }{A Puzzle}}\label{sec:mnpuzzle}
\logpage{[ 6, 7, 0 ]}
{
  \index{game} 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. \begin{center}
\begin{tabular}{|c|c|c|c|}\hline
$ 7$&
$13$&
$14$&
$ 2$\\
\hline
$ 1$&
$ 4$&
$15$&
$11$\\
\hline
$ 6$&
$ 8$&
$ 3$&
$ 9$\\
\hline
$10$&
$ 5$&
$12$&
$ $\\
\hline
\end{tabular}\\[2mm]
\end{center}

  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~\cite{LoydFifteenWeb} and~\cite{HistGames} for more information and references. 

\subsection{\textcolor{Chapter }{BrowsePuzzle}}
\logpage{[ 6, 7, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowsePuzzle( [m, n[, pi]] )\index{BrowsePuzzle@\texttt{BrowsePuzzle}}
\label{BrowsePuzzle}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 a record describing the initial and final status of the puzzle. 



 This function shows the rectangle in a window. 

 The arguments \mbox{\texttt{m}} and \mbox{\texttt{n}} 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 \mbox{\texttt{pi}}, the default is a random element in the alternating group on the points $1, 2, \ldots, \mbox{\texttt{m}} \mbox{\texttt{n}} - 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. 

 The return value is a record with the components \texttt{dim} (the pair \texttt{[ m, n ]}), \texttt{init} (the initial permutation), \texttt{final} (the final permutation), and \texttt{steps} (the number of steps that were needed). 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> BrowseData.SetReplay( Concatenation(
  >        BrowsePuzzleSolution.steps, "Q" ) );
  gap> BrowsePuzzle( 4, 4, BrowsePuzzleSolution.init );;
  gap> BrowseData.SetReplay( false );
\end{Verbatim}
 An implementation using mouse clicks instead of key strokes is available in
the \textsf{GAP} package \textsf{XGAP} (see~\cite{XGAP}). 

 \emph{Implementation remarks}: The game board is implemented via a browse table, without row and column
labels, with static header, dynamic footer, and individual \texttt{minyx} 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 are
admissible. 

 Some standard \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) functionality, such as scrolling, selecting, and searching, are not available
in this application. 

 The code can be found in the file \texttt{lib/puzzle.g} of the package. }

 }

 
\section{\textcolor{Chapter }{Peg Solitaire}}\label{sec:solitaire}
\logpage{[ 6, 8, 0 ]}
{
  \index{game} \index{solitaire game} 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.   \begin{center} \begin{tabular}{ccccccc} \cline{3-5} & &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c|}{$\circ$} & & \\ \cline{3-5} & &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c|}{$\circ$} & & \\ \hline \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c|}{$\circ$} \\ \hline
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{ } &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c|}{$\circ$} \\ \hline \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c|}{$\circ$} \\ \hline & &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c|}{$\circ$} & & \\ \cline{3-5} & &
\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &
\multicolumn{1}{|c|}{$\circ$} & & \\ \cline{3-5} \end{tabular} \end{center}     We consider the game that in the beginning, exactly one hole is empty, and in
the end, exactly one peg is left. 

\subsection{\textcolor{Chapter }{PegSolitaire}}
\logpage{[ 6, 8, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PegSolitaire( [format][,][nrholes][,][twoModes] )\index{PegSolitaire@\texttt{PegSolitaire}}
\label{PegSolitaire}
}\hfill{\scriptsize (function)}}\\


 This function shows the game board in a window. 

 If the argument \mbox{\texttt{format}} is one of the strings \texttt{"small"} or \texttt{"large"} then small or large pegs are shown, the default is \texttt{"small"}. 

 Three shapes of the game board are supported, with $33$, $37$, and $45$ holes, respectively; this number can be specified via the argument \mbox{\texttt{nrholes}}, 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 \mbox{\texttt{twoModes}} is entered as an argument then it determines whether a browse table with one
or two modes is used; the default \texttt{false} 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 \texttt{j} key followed by the appropriate arrow key. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> for n in [ 33, 37, 45 ] do
  >      BrowseData.SetReplay( Concatenation(
  >          PegSolitaireSolutions.( String( n ) ), "Q" ) );
  >      PegSolitaire( n );
  > od;
  gap> BrowseData.SetReplay( false );
\end{Verbatim}
 

 For more information such as variations of the game and references, see~\cite{PegSolitaireWeb}. Also the solutions stored in the variable \texttt{PegSolitaireSolutions} have been taken from this web page. 

 \emph{Implementation remarks}: The game board is implemented via a browse table, without row and column
labels, with static header, dynamic footer, and individual \texttt{minyx} 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 \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) functionality, such as scrolling, selecting, and searching, are not available
in this application. 

 The code can be found in the file \texttt{lib/solitair.g} of the package. }

 }

 
\section{\textcolor{Chapter }{Rubik's Cube}}\label{sec:rubikscube}
\logpage{[ 6, 9, 0 ]}
{
  \index{game} We visualize the transformations of Rubik's magic cube in a model that is
given by ``unfolding'' the faces and numbering them as follows.   \begin{center} \begin{tabular}{cccccccccccc} \cline{4-6} & & &
\multicolumn{1}{|c}{1} & \multicolumn{1}{c}{2} & \multicolumn{1}{c|}{3} & & &
& & & \\ & & & \multicolumn{1}{|c}{4} & \multicolumn{1}{c}{top} &
\multicolumn{1}{c|}{5} & & & & & & \\ & & & \multicolumn{1}{|c}{6} &
\multicolumn{1}{c}{7} & \multicolumn{1}{c|}{8} & & & & & & \\ \hline
\multicolumn{1}{|c}{9} & \multicolumn{1}{c}{10} & \multicolumn{1}{c}{11} &
\multicolumn{1}{|c}{17} & \multicolumn{1}{c}{18} & \multicolumn{1}{c}{19} &
\multicolumn{1}{|c}{25} & \multicolumn{1}{c}{26} & \multicolumn{1}{c}{27} &
\multicolumn{1}{|c}{33} & \multicolumn{1}{c}{34} & \multicolumn{1}{c|}{35} \\
\multicolumn{1}{|c}{12} & \multicolumn{1}{c}{left} & \multicolumn{1}{c}{13} &
\multicolumn{1}{|c}{20} & \multicolumn{1}{c}{front} & \multicolumn{1}{c}{21} &
\multicolumn{1}{|c}{28} & \multicolumn{1}{c}{right} & \multicolumn{1}{c}{29} &
\multicolumn{1}{|c}{36} & \multicolumn{1}{c}{back} & \multicolumn{1}{c|}{37}
\\ \multicolumn{1}{|c}{14} & \multicolumn{1}{c}{15} & \multicolumn{1}{c}{16} &
\multicolumn{1}{|c}{22} & \multicolumn{1}{c}{23} & \multicolumn{1}{c}{24} &
\multicolumn{1}{|c}{30} & \multicolumn{1}{c}{31} & \multicolumn{1}{c}{32} &
\multicolumn{1}{|c}{38} & \multicolumn{1}{c}{39} & \multicolumn{1}{c|}{40} \\
\hline & & & \multicolumn{1}{|c}{41} & \multicolumn{1}{c}{42} &
\multicolumn{1}{c|}{43} & & & & & & \\ & & & \multicolumn{1}{|c}{44} &
\multicolumn{1}{c}{down} & \multicolumn{1}{c|}{45} & & & & & & \\ & & &
\multicolumn{1}{|c}{46} & \multicolumn{1}{c}{47} & \multicolumn{1}{c|}{48} & &
& & & & \\ \cline{4-6} \end{tabular} \end{center}     Clockwise turns of the six layers (top, left, front, right, back, and down)
are represented by the following permutations. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> cubegens := [
  >   ( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19),
  >   ( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35),
  >   (17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11),
  >   (25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24),
  >   (33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27),
  >   (41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)
  > ];;
\end{Verbatim}
 \textsf{GAP} computations analyzing this permutation group have been part of the
announcements of \textsf{GAP}~3 releases. For a \textsf{GAP}~4 equivalent, see~\cite{RubiksCubeGAPWeb}. For more information and references (not \textsf{GAP} related) about Rubik's cube, see~\cite{RubiksCubeWeb}. 

\subsection{\textcolor{Chapter }{BrowseRubiksCube}}
\logpage{[ 6, 9, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseRubiksCube( [format][,][pi] )\index{BrowseRubiksCube@\texttt{BrowseRubiksCube}}
\label{BrowseRubiksCube}
}\hfill{\scriptsize (function)}}\\


 This function shows the model of the cube in a window. 

 If the argument \mbox{\texttt{format}} is one of the strings \texttt{"small"} or \texttt{"large"} then small or large cells are shown, the default is \texttt{"small"}. 

 The argument \mbox{\texttt{pi}} is the initial permutation of the faces, the default is a random permutation
in the cube group, see~ (\textbf{Reference: Random}). 

 Supported user inputs are the keys \textsc{t}, \textsc{l}, \textsc{f}, \textsc{r}, \textsc{b}, and \textsc{d} 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 \texttt{NCurses.attrs.has{\_}colors} (\ref{NCurses.attrs.hascolors}), the input \textsc{s} 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 \texttt{inputs} (a string describing the user inputs), \texttt{init}, and \texttt{final} (the initial and final permutation of the faces, respectively). (The \texttt{inputs} 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. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> choice:= List( [ 1 .. 30 ], i -> Random( [ 1 .. 6 ] ) );;
  gap> input:= List( "tlfrbd", INT_CHAR ){ choice };;
  gap> BrowseData.SetReplay( Concatenation(
  >        input{ [ 1 .. 20 ] },
  >        "s",                    # switch to number display
  >        input{ [ 21 .. 25 ] },
  >        "s",                    # switch to color display
  >        input{ [ 26 .. 30 ] },
  >        "Q" ) );;               # quit the browse table
  gap> BrowseRubiksCube( Product( cubegens{ choice } ) );;
  gap> BrowseData.SetReplay( false );
\end{Verbatim}
 \emph{Implementation remarks}: The cube is implemented via a browse table, without row and column labels,
with static header, dynamic footer, and individual \texttt{minyx} 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 \texttt{work.Main}, so this relies on \emph{not} caching the formatted cells in \texttt{work.main}. 

 Row and column separators of the browse table are whitespace of height and
width one. The separating lines are drawn using an individual \texttt{SpecialGrid} function in the browse table. Note that the relevant cells do not form a
rectangular array. 

 Some standard \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) functionality, such as scrolling, selecting, and searching, are not available
in this application. 

 The code can be found in the file \texttt{lib/rubik.g} of the package. }

 }

 
\section{\textcolor{Chapter }{Changing Sides}}\label{sec:knight}
\logpage{[ 6, 10, 0 ]}
{
  \index{game} 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. 

  \begin{center} \begin{tabular}{|c|c|c|c|c|} \hline
\rule[-6pt]{0pt}{18pt}$\times$&$\times$&$\times$&$\times$&$\times$\\ \hline
\rule[-6pt]{0pt}{18pt}$\circ$&$\times$&$\times$&$\times$&$\times$\\ \hline
\rule[-6pt]{0pt}{18pt}$\circ$&$\circ$&&$\times$&$\times$\\ \hline
\rule[-6pt]{0pt}{18pt}$\circ$&$\circ$&$\circ$&$\circ$&$\times$\\ \hline
\rule[-6pt]{0pt}{18pt}$\circ$&$\circ$&$\circ$&$\circ$&$\circ$\\ \hline
\end{tabular} \end{center}     

 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 \cite{MacTutor}. 

\subsection{\textcolor{Chapter }{BrowseChangeSides}}
\logpage{[ 6, 10, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BrowseChangeSides(  )\index{BrowseChangeSides@\texttt{BrowseChangeSides}}
\label{BrowseChangeSides}
}\hfill{\scriptsize (function)}}\\


 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. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> for entry in BrowseChangeSidesSolutions do
  >      BrowseData.SetReplay( Concatenation( entry, "Q" ) );
  >      BrowseChangeSides();
  > od;
  gap> BrowseData.SetReplay( false );
\end{Verbatim}
 

 \emph{Implementation remarks}: The game board is implemented via a browse table, without row and column
labels, with static header, dynamic footer, and individual \texttt{minyx} 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 \texttt{SpecialGrid} function in the browse table. 

 Some standard \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) functionality, such as scrolling, selecting, and searching, are not available
in this application. 

 The code can be found in the file \texttt{lib/knight.g} of the package. }

 }

 
\section{\textcolor{Chapter }{Sudoku}}\label{sec:sudoku}
\logpage{[ 6, 11, 0 ]}
{
  \index{game} 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 \emph{proper Sudoku game} is defined as one with a unique solution. Here is an example.    \begin{center} \begin{tabular}{||c|c|c||c|c|c||c|c|c||} \hline\hline
\rule[-3pt]{0pt}{15pt}& & & & & &5& & \\ \hline \rule[-3pt]{0pt}{15pt} &1&5&4&
&6& &2& \\ \hline \rule[-3pt]{0pt}{15pt}9& & & &5& &3& & \\ \hline \hline
\rule[-3pt]{0pt}{15pt}6& &4& & & & & & \\ \hline \rule[-3pt]{0pt}{15pt} & &
&8& & & & & \\ \hline \rule[-3pt]{0pt}{15pt}8& & &9& & & &5&3\\ \hline \hline
\rule[-3pt]{0pt}{15pt} & & & & &5& & & \\ \hline \rule[-3pt]{0pt}{15pt} &4& &
& &7& & &2\\ \hline \rule[-3pt]{0pt}{15pt} & &9&1& & &8& & \\ \hline \hline
\end{tabular} \end{center}   The \textsf{Browse} 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 \texttt{PlaySudoku} (\ref{PlaySudoku}) which is implemented using the generic browse functionality described in
Chapter \ref{chap:browse_user}. 

\subsection{\textcolor{Chapter }{Sudoku.Init}}
\logpage{[ 6, 11, 1 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Sudoku.Init( [arg] )\index{Sudoku.Init@\texttt{Sudoku.Init}}
\label{Sudoku.Init}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
A record describing a Sudoku board or \texttt{fail}.



 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 \mbox{\texttt{arg}}. 
\begin{description}
\item[{\mbox{\texttt{arg}} is a string}] 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 \texttt{'1'} to \texttt{'9'} or \texttt{'|'} is written in position $i$ of the string. Trailing empty entries can be left out. Afterwards \texttt{'|'}-characters can be inserted in the string (for example to mark line ends).
Such strings can be used for \mbox{\texttt{arg}}. 
\item[{\mbox{\texttt{arg}} is a matrix}] 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. 
\item[{\mbox{\texttt{arg}} is a list of integers}] 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). 
\end{description}
 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\
  >  6  47   |45  2    |89   2 1 | 4   8 7 | ");;
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{Sudoku.Place}}
\logpage{[ 6, 11, 2 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Sudoku.Place( game, i, n )\index{Sudoku.Place@\texttt{Sudoku.Place}}
\label{Sudoku.Place}
}\hfill{\scriptsize (function)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Sudoku.Remove( game, i )\index{Sudoku.Remove@\texttt{Sudoku.Remove}}
\label{Sudoku.Remove}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
The changed \mbox{\texttt{game}}.



 Here \mbox{\texttt{game}} is a record describing a Sudoku board, as returned by \texttt{Sudoku.Init} (\ref{Sudoku.Init}). The argument \mbox{\texttt{i}} is the number of an entry, counted row-wise from 1 to 81, and \mbox{\texttt{n}} is an integer from 1 to 9 to be placed on the board. These functions change \mbox{\texttt{game}}. 

 \texttt{Sudoku.Place} tries to place number \mbox{\texttt{n}} on entry \mbox{\texttt{i}}. It is an error if entry \mbox{\texttt{i}} is not empty. The number is not placed if \mbox{\texttt{n}} is already used in the row, column or subsquare of entry \mbox{\texttt{i}}. In this case the component \texttt{game.impossible} is bound. 

 \texttt{Sudoku.Remove} tries to remove the number placed on position \mbox{\texttt{i}} of the board. It does not change the board if entry \mbox{\texttt{i}} is empty, or if entry \mbox{\texttt{i}} was given when the board \mbox{\texttt{game}} was created. In the latter case \texttt{game.impossible} is bound. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\
  >  6  47   |45  2    |89   2 1 | 4   8 7 | ");;
  gap> Sudoku.Place(game, 1, 3);; # 3 is already in first row
  gap> IsBound(game.impossible);
  true
  gap> Sudoku.Place(game, 1, 2);; # 2 is not in row, col or subsquare
  gap> IsBound(game.impossible); 
  false
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{Sudoku.RandomGame}}
\logpage{[ 6, 11, 3 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Sudoku.RandomGame( [seed] )\index{Sudoku.RandomGame@\texttt{Sudoku.RandomGame}}
\label{Sudoku.RandomGame}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
A pair \texttt{[str, seed]} of string and seed.



 The optional argument \mbox{\texttt{seed}}, if given, must be an integer. If not given some random integer from the
current \textsf{GAP} session is used. This function returns a random proper Sudoku game, where the
board is described by a string \texttt{str}, as explained in \texttt{Sudoku.Init} (\ref{Sudoku.Init}). With the same \mbox{\texttt{seed}} 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. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> Sudoku.RandomGame(5833750);                                           
  [ " 1         2     43  2   68   72    8     6 2   1 9 8  8 3   \
  9     47 3   7  18  ", 5833750 ]
  gap> last = Sudoku.RandomGame(last[2]);
  true
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{Sudoku.SimpleDisplay}}
\logpage{[ 6, 11, 4 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Sudoku.SimpleDisplay( game )\index{Sudoku.SimpleDisplay@\texttt{Sudoku.SimpleDisplay}}
\label{Sudoku.SimpleDisplay}
}\hfill{\scriptsize (function)}}\\


 Displays a Sudoku board on the terminal. (But see \texttt{PlaySudoku} (\ref{PlaySudoku}) for a fancier interface.) 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> game := Sudoku.Init(" 3   68  | 85  1 69|  97   53|      79 |\
  >  6  47   |45  2    |89   2 1 | 4   8 7 | ");;
  gap> Sudoku.SimpleDisplay(game);                                        
   3 |  6|8  
   85|  1| 69
    9|7  | 53
  -----------
     |   |79 
   6 | 47|   
  45 | 2 |   
  -----------
  89 |  2| 1 
   4 |  8| 7 
     |   |   
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{Sudoku.OneSolution}}
\logpage{[ 6, 11, 5 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Sudoku.OneSolution( game )\index{Sudoku.OneSolution@\texttt{Sudoku.OneSolution}}
\label{Sudoku.OneSolution}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
A completed Sudoku board that solves \mbox{\texttt{game}}, or \texttt{fail}.



 Here \mbox{\texttt{game}} must be a Sudoku board as returned by \texttt{Sudoku.Init} (\ref{Sudoku.Init}). It is not necessary that \mbox{\texttt{game}} 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 \texttt{fail} is returned. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> Sudoku.SimpleDisplay(Sudoku.OneSolution(Sudoku.Init("  3")));
  493|876|251
  861|542|739
  527|193|648
  -----------
  942|618|573
  156|739|482
  738|425|916
  -----------
  289|354|167
  375|961|824
  614|287|395
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{Sudoku.UniqueSolution}}
\logpage{[ 6, 11, 6 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Sudoku.UniqueSolution( game )\index{Sudoku.UniqueSolution@\texttt{Sudoku.UniqueSolution}}
\label{Sudoku.UniqueSolution}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
A completed Sudoku board that solves \mbox{\texttt{game}}, or \texttt{false}, or \texttt{fail}.



 Here \mbox{\texttt{game}} must be a Sudoku board as returned by \texttt{Sudoku.Init} (\ref{Sudoku.Init}). It is not necessary that \mbox{\texttt{game}} describes a proper Sudoku game. If it has several solutions, then \texttt{false} is returned. If it has no solution, then \texttt{fail} is returned. Otherwise a board with the unique solution is returned. 

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> s := "      5  | 154 6 2 |9   5 3  |6 4      |   8     |8  9   53\
  > |     5   | 4   7  2|  91  8  ";;
  gap> sol := Sudoku.UniqueSolution(Sudoku.Init(s));;
  gap> Sudoku.SimpleDisplay(sol);
  438|219|576
  715|436|928
  962|758|314
  -----------
  694|573|281
  153|862|749
  827|941|653
  -----------
  281|695|437
  546|387|192
  379|124|865
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{PlaySudoku}}
\logpage{[ 6, 11, 7 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PlaySudoku( [arg] )\index{PlaySudoku@\texttt{PlaySudoku}}
\label{PlaySudoku}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
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 \mbox{\texttt{arg}}. It can either be a string, matrix or list of holes and integers as described
in \texttt{Sudoku.Init} (\ref{Sudoku.Init}), or a board as returned by \texttt{Sudoku.Init} (\ref{Sudoku.Init}). Furthermore \mbox{\texttt{arg}} can be an integer or not be given, in that case \texttt{Sudoku.RandomGame} (\ref{Sudoku.RandomGame}) is called to produce a random game. 

 The usage of this function is self-explanatory, pressing the \textsc{?} key displays a help screen. Here, we mention two keys with a particular
action: Pressing the \textsc{h} 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 \textsc{s} key the puzzle is solved by the program or it tells you that there is no or no
unique solution. 

 \emph{Implementation remarks}: The game board is implemented via a browse table, without row and column
labels, with static header, dynamic footer, and individual \texttt{minyx} 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 \texttt{SpecialGrid} function in the browse table, since they cannot be specified within the
generic browse table functions. 

 Some standard \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) functionality, such as scrolling, selecting, and searching, are not available
in this application. 

 The code can be found in the file \texttt{lib/sudoku.g} of the package. }

 

\subsection{\textcolor{Chapter }{Sudoku.HTMLGame}}
\logpage{[ 6, 11, 8 ]}\nobreak
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Sudoku.HTMLGame( game )\index{Sudoku.HTMLGame@\texttt{Sudoku.HTMLGame}}
\label{Sudoku.HTMLGame}
}\hfill{\scriptsize (function)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Sudoku.LaTeXGame( game )\index{Sudoku.LaTeXGame@\texttt{Sudoku.LaTeXGame}}
\label{Sudoku.LaTeXGame}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
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. }

 }

 }

 \def\bibname{References\logpage{[ "Bib", 0, 0 ]}}

\bibliographystyle{alpha}
\bibliography{browse}

\def\indexname{Index\logpage{[ "Ind", 0, 0 ]}}


\printindex

\newpage
\immediate\write\pagenrlog{["End"], \arabic{page}];}
\immediate\closeout\pagenrlog
\end{document}
