Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346% generated by GAPDoc2LaTeX from XML source (Frank Luebeck)1\documentclass[a4paper,11pt]{report}23\usepackage{a4wide}4\sloppy5\pagestyle{myheadings}6\usepackage{amssymb}7\usepackage[latin1]{inputenc}8\usepackage{makeidx}9\makeindex10\usepackage{color}11\definecolor{FireBrick}{rgb}{0.5812,0.0074,0.0083}12\definecolor{RoyalBlue}{rgb}{0.0236,0.0894,0.6179}13\definecolor{RoyalGreen}{rgb}{0.0236,0.6179,0.0894}14\definecolor{RoyalRed}{rgb}{0.6179,0.0236,0.0894}15\definecolor{LightBlue}{rgb}{0.8544,0.9511,1.0000}16\definecolor{Black}{rgb}{0.0,0.0,0.0}1718\definecolor{linkColor}{rgb}{0.0,0.0,0.554}19\definecolor{citeColor}{rgb}{0.0,0.0,0.554}20\definecolor{fileColor}{rgb}{0.0,0.0,0.554}21\definecolor{urlColor}{rgb}{0.0,0.0,0.554}22\definecolor{promptColor}{rgb}{0.0,0.0,0.589}23\definecolor{brkpromptColor}{rgb}{0.589,0.0,0.0}24\definecolor{gapinputColor}{rgb}{0.589,0.0,0.0}25\definecolor{gapoutputColor}{rgb}{0.0,0.0,0.0}2627%% for a long time these were red and blue by default,28%% now black, but keep variables to overwrite29\definecolor{FuncColor}{rgb}{0.0,0.0,0.0}30%% strange name because of pdflatex bug:31\definecolor{Chapter }{rgb}{0.0,0.0,0.0}32\definecolor{DarkOlive}{rgb}{0.1047,0.2412,0.0064}333435\usepackage{fancyvrb}3637\usepackage{mathptmx,helvet}38\usepackage[T1]{fontenc}39\usepackage{textcomp}404142\usepackage[43pdftex=true,44bookmarks=true,45a4paper=true,46pdftitle={Written with GAPDoc},47pdfcreator={LaTeX with hyperref package / GAPDoc},48colorlinks=true,49backref=page,50breaklinks=true,51linkcolor=linkColor,52citecolor=citeColor,53filecolor=fileColor,54urlcolor=urlColor,55pdfpagemode={UseNone},56]{hyperref}5758\newcommand{\maintitlesize}{\fontsize{50}{55}\selectfont}5960% write page numbers to a .pnr log file for online help61\newwrite\pagenrlog62\immediate\openout\pagenrlog =\jobname.pnr63\immediate\write\pagenrlog{PAGENRS := [}64\newcommand{\logpage}[1]{\protect\write\pagenrlog{#1, \thepage,}}65%% were never documented, give conflicts with some additional packages6667\newcommand{\GAP}{\textsf{GAP}}6869%% nicer description environments, allows long labels70\usepackage{enumitem}71\setdescription{style=nextline}7273%% depth of toc74\setcounter{tocdepth}{1}757677787980%% command for ColorPrompt style examples81\newcommand{\gapprompt}[1]{\color{promptColor}{\bfseries #1}}82\newcommand{\gapbrkprompt}[1]{\color{brkpromptColor}{\bfseries #1}}83\newcommand{\gapinput}[1]{\color{gapinputColor}{#1}}848586\begin{document}8788\logpage{[ 0, 0, 0 ]}89\begin{titlepage}90\mbox{}\vfill9192\begin{center}{\maintitlesize \textbf{\textsf{Browse}\mbox{}}}\\93\vfill9495\hypersetup{pdftitle=\textsf{Browse}}96\markright{\scriptsize \mbox{}\hfill \textsf{Browse} \hfill\mbox{}}97{\Huge ( Version 1.8.7 ) \mbox{}}\\[1cm]98{July 2017\mbox{}}\\[1cm]99\mbox{}\\[2cm]100{\Large \textbf{ Thomas Breuer \mbox{}}}\\101{\Large \textbf{ Frank L{\"u}beck \mbox{}}}\\102\hypersetup{pdfauthor= Thomas Breuer ; Frank L{\"u}beck }103\end{center}\vfill104105\mbox{}\\106{\mbox{}\\107\small \noindent \textbf{ Thomas Breuer } Email: \href{mailto://Thomas.Breuer@Math.RWTH-Aachen.De} {\texttt{Thomas.Breuer@Math.RWTH-Aachen.De}}\\108Homepage: \href{http://www.math.rwth-aachen.de/~Thomas.Breuer} {\texttt{http://www.math.rwth-aachen.de/\texttt{\symbol{126}}Thomas.Breuer}}}\\109{\mbox{}\\110\small \noindent \textbf{ Frank L{\"u}beck } Email: \href{mailto://Frank.Luebeck@Math.RWTH-Aachen.De} {\texttt{Frank.Luebeck@Math.RWTH-Aachen.De}}\\111Homepage: \href{http://www.math.rwth-aachen.de/~Frank.Luebeck} {\texttt{http://www.math.rwth-aachen.de/\texttt{\symbol{126}}Frank.Luebeck}}}\\112\end{titlepage}113114\newpage\setcounter{page}{2}115{\small116\section*{Copyright}117\logpage{[ 0, 0, 1 ]}118{\copyright} 2006-2017 by Thomas Breuer and Frank L{\"u}beck119120This package may be distributed under the terms and conditions of the GNU121Public License Version 3 or later, see \href{http://www.gnu.org/licenses} {\texttt{http://www.gnu.org/licenses}}. \mbox{}}\\[1cm]122\newpage123124\def\contentsname{Contents\logpage{[ 0, 0, 2 ]}}125126\tableofcontents127\newpage128129130\chapter{\textcolor{Chapter }{Introduction and Overview}}\label{ch:intro}131\logpage{[ 1, 0, 0 ]}132\hyperdef{L}{X794AAAFB7FFAA46C}{}133{134135\section{\textcolor{Chapter }{Introduction}}\label{sec:intro}136\logpage{[ 1, 1, 0 ]}137\hyperdef{L}{X7DFB63A97E67C0A1}{}138{139The motivation of the package \textsf{Browse} was to provide better functionality for displaying two-dimensional arrays of140data (e.g., character tables): moving through the data without loosing row and141column labels, searching for text, displaying extra information, hiding142information, allowing interactive user input, ...143144We wanted to achieve this by using the capabilities of the terminal emulations145in which \textsf{GAP} is running, and not by some external graphical user interface. For this we146have chosen to use the widely available \texttt{C}-library \texttt{ncurses}, see \cite{NCursesWeb}. It contains functions to find out terminal capabilities, to change147properties of terminals, to place text, to handle several windows with148overlapping, ... 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.149150\textsf{Browse} has now three levels of functionality:151\begin{description}152\item[{A low level interface to \texttt{ncurses}}] This may be interesting for all kinds of applications which want to display153text with some markup including \index{colors as text attributes}colors, maybe in several windows, using the available capabilities of a154terminal.155\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 rows156and columns, searching, sorting, binding keys to actions, ... If you want to157implement such applications for further kinds of data, first look at the158examples in Section \texttt{BrowseData.IsBrowseTable} (\ref{BrowseData.IsBrowseTable}), then check what can be copied from the examples in Chapter \ref{ch:appl}, and consult the descriptions in Chapters \ref{chap:browse-user} and \ref{chap:browse-prg}.159\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 for160programmers of further applications. This includes (of course) a method for161browsing through character tables, functions for browsing through data162collections, several games,\index{game} and an interface for demos.163\end{description}164Users interested only in these applications should perhaps just try \texttt{NCurses.Demo()}. }165166167\section{\textcolor{Chapter }{Overview}}\label{sec:overview}168\logpage{[ 1, 2, 0 ]}169\hyperdef{L}{X8389AD927B74BA4A}{}170{171172\subsection{\textcolor{Chapter }{The \texttt{ncurses} interface}}\label{ssec:ov_ncurses}173\logpage{[ 1, 2, 1 ]}174\hyperdef{L}{X87A6D24784C21E54}{}175{176Chapter \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 the177documentation 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.178179The 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.180181This chapter is for users who want to write their own applications of \texttt{ncurses}. }182183184\subsection{\textcolor{Chapter }{Applications of \texttt{ncurses}}}\label{ssec:ov_ncappl}185\logpage{[ 1, 2, 2 ]}186\hyperdef{L}{X80C054D881502061}{}187{188In 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 is189also 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. }190191192\subsection{\textcolor{Chapter }{The interface to browse two-dimensional arrays}}\label{ssec:ov_genbrowse}193\logpage{[ 1, 2, 3 ]}194\hyperdef{L}{X7CF47ACC83A95689}{}195{196Chapters \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 of197data. The first of these covers the basic functionality which may be198sufficient for many applications and the second gives more technical details.199With interactive display we mean that it is not only possible to scroll200through the data, but one can search for strings, sort by rows or columns,201select entries, bind arbitrary actions to keys and mouse events, ask for help,202and more. }203204205\subsection{\textcolor{Chapter }{Applications of the generic function \texttt{NCurses.BrowseGeneric}}}\label{ssec:ov_browseappl}206\logpage{[ 1, 2, 4 ]}207\hyperdef{L}{X7A0055DE7A2C5DC9}{}208{209In 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 and210so we include some implementation remarks in their documentation.211212Users who just want to use these applications hopefully do not need to read213this \textsf{Browse} manual, all applications are coming with built-in help windows.214215There are different kinds of applications. First, there are methods for216browsing through character tables and tables of marks (our original motivation217for this package). Then there are applications for browsing through data218collections, 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 puzzle219(generalized), peg solitaire, and Sudoku (including functions to create new220puzzles and to solve puzzles). }221222}223224225\section{\textcolor{Chapter }{User preferences provided by the \textsf{Browse} package}}\label{sec:pkg_userprefs}226\logpage{[ 1, 3, 0 ]}227\hyperdef{L}{X825F23FF825334B4}{}228{229See \texttt{SetUserPreference} (\textbf{Reference: SetUserPreference}) for \textsf{GAP}'s user preferences mechanism, and \texttt{BrowseUserPreferences} (\ref{BrowseUserPreferences}) for viewing and modifying user preferences.230\subsection{\textcolor{Chapter }{The user preference \texttt{EnableMouseEvents}}}\label{subsec:EnableMouseEvents}231\logpage{[ 1, 3, 1 ]}232\hyperdef{L}{X859EAEDA850D3B02}{}233{234This user preference defines whether mouse events are enabled by default in235visual mode (value \texttt{true}) or not (value \texttt{false}, this is the default). During the \textsf{GAP} session, the value can be changed using \texttt{NCurses.UseMouse} (\ref{NCurses.UseMouse}). Inside browse applications based on \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) or \texttt{NCurses.Select} (\ref{NCurses.Select}), the value can be toggled usually by hitting the \textsc{M} key. }236237238\subsection{\textcolor{Chapter }{The user preference \texttt{SelectHelpMatches}}}\label{subsec:SelectHelpMatches}239\logpage{[ 1, 3, 2 ]}240\hyperdef{L}{X7D242D4286EAB00A}{}241{242In the case that the \textsf{GAP} help system finds multiple matches, \texttt{true} (the default) means that the user can choose one entry from a list that is243shown via \texttt{NCurses.Select} (\ref{NCurses.Select}), and \texttt{false} means that the matches are just shown in a pager. }244245246\subsection{\textcolor{Chapter }{The user preference \texttt{SelectPackageName}}}\label{subsec:SelectPackageName}247\logpage{[ 1, 3, 3 ]}248\hyperdef{L}{X7BC3B5827A4B09C3}{}249{250In the case that \texttt{LoadPackage} (\textbf{Reference: LoadPackage}) is called with a prefix of some package names, \texttt{true} (the default) means that the user can choose one matching entry, and \texttt{false} means that the matches are just printed. }251252}253254}255256257\chapter{\textcolor{Chapter }{Interface to the \texttt{ncurses} Library}}\label{ch:curses}258\logpage{[ 2, 0, 0 ]}259\hyperdef{L}{X7E049B1185A56B30}{}260{261In 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 of262terminal windows. It allows one to write programs which should work on a wide263variety of terminal emulations with different sets of capabilities.264265This technical chapter is intended for readers who want to program new266applications 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.267268Detailed 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.269\section{\textcolor{Chapter }{The \texttt{ncurses} Library}}\label{sec:cursesC}270\logpage{[ 2, 1, 0 ]}271\hyperdef{L}{X85DE9B75837BA65B}{}272{273In 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}.274275The basic objects to manipulate are called \emph{windows}, they correspond to rectangular regions of the terminal screen. Windows can276overlap 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 panels277to the top and bottom of the display or to hide a panel.278279We 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 for280a 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 functions281with \texttt{n} which get the number of characters to write as argument. (More convenient282functions are then implemented on the \textsf{GAP} level.)283\subsection{\textcolor{Chapter }{Setting the terminal}}\label{ssec:ncursesTermset}284\logpage{[ 2, 1, 1 ]}285\hyperdef{L}{X8499A3A384BF1F2D}{}286{287We first list flags for setting the basic behavior of a terminal. With \texttt{savetty}/\texttt{resetty} a setting can be stored and recovered.288\begin{description}289\item[{\index{savetty@\texttt{savetty}}\texttt{savetty()}}] This stores the current setting of the terminal in a buffer.290\item[{\index{resetty@\texttt{resetty}}\texttt{resetty()}}] This resets the terminal to what was stored in the last call to \texttt{savetty}.291\item[{\index{cbreak@\texttt{cbreak}} \index{nocbreak@\texttt{nocbreak}}\texttt{cbreak()/nocbreak()}}] In \texttt{cbreak} mode each input character from a terminal is directly forwarded to the292application (but see \texttt{keypad}). With \texttt{nocbreak} this only happens after a newline or return is typed.293\item[{\index{keypad@\texttt{keypad}}\texttt{keypad(win, bool)}}] If set to \texttt{true} some special input like arrow or function keys can be read as single294characters from the input (such keys actually generate certain sequences of295characters), see also \ref{ssec:ncursesInput}. (The \mbox{\texttt{\mdseries\slshape win}} argument is irrelevant.)296\item[{\index{echo@\texttt{echo}} \index{noecho@\texttt{noecho}}\texttt{echo()}/\texttt{noecho()}}] This determines if input characters are automatically echoed by the terminal297at the current cursor position.298\item[{\index{curs_set@\texttt{curs{\textunderscore}set}}\texttt{curs{\textunderscore}set(vis)}}] This determines the visibility of the cursor. The argument \mbox{\texttt{\mdseries\slshape vis}}=0 makes the cursor invisible. With \mbox{\texttt{\mdseries\slshape vis}}=1 it becomes visible; some terminals allow also higher levels of visibility.299\item[{\index{wtimeout@\texttt{wtimeout}}\texttt{wtimeout(win, delay)}}] Here \mbox{\texttt{\mdseries\slshape delay}} determines a timeout in milliseconds for reading characters from the input of300a window. Negative values mean infinity, that is a blocking read.301\item[{\index{nonl@\texttt{nonl}} \index{nl@\texttt{nl}}\texttt{nl()}/\texttt{nonl()}}] With \texttt{nl} a return on input is translated to a newline character and a newline on output302is interpreted as return and linefeed.303\item[{\index{intrflush@\texttt{intrflush}}\texttt{intrflush(win, bool)}}] This flag determines if after an interrupt pending output to the terminal is304flushed. (The \mbox{\texttt{\mdseries\slshape win}} argument is irrelevant.)305\item[{\index{idlok@\texttt{idlok}}\texttt{idlok(win, bool)}}] With \texttt{true} the library tries to use a hardware line insertion functionality (in306particular for scrolling).307\item[{\index{scrollok@\texttt{scrollok}}\texttt{scrollok(win, bool)}}] If set to \texttt{true} moving the cursor down from the last line of a window causes scrolling of the308whole window, otherwise nothing happens.309\item[{\index{leaveok@\texttt{leaveok}}\texttt{leaveok(win, bool)}}] If set to \texttt{true} a refresh of the window leaves the cursor at its current location, otherwise310this is not guaranteed.311\item[{\index{clearok@\texttt{clearok}}\texttt{clearok(win, bool)}}] If set to \texttt{true} the next refresh of the window will clear the screen completely and redraw312everything.313\item[{\index{immedok@\texttt{immedok}}\texttt{immedok(win, bool)}}] If set to \texttt{true} all changes of the window will automatically also call a \texttt{wrefresh}.314\item[{\index{noraw@\texttt{noraw}} \index{raw@\texttt{raw}}\texttt{raw()}/\texttt{noraw()}}] Similar to \texttt{cbreak}, usually not needed (see the \texttt{ncurses} documentation for details).315\end{description}316}317318319\subsection{\textcolor{Chapter }{Manipulating windows}}\label{ssec:ncursesWin}320\logpage{[ 2, 1, 2 ]}321\hyperdef{L}{X800D5B6381F0356F}{}322{323In \texttt{ncurses} an arbitrary number of windows which correspond to rectangular regions (maybe324overlapping) of the screen can be handled. You should always delete windows325which are no longer needed. To get a proper display of overlapping windows326(which may occur by recursively called functions using this library) we327suggest that you always wrap windows in panels, see \ref{ssec:ncursesPan}.328329For functions which involve coordinates recall that the upper left corner of330the screen or internally of any window has the coordinates (0,0).331\begin{description}332\item[{\index{newwin@\texttt{newwin}}\texttt{newwin(nlines, ncols, y, x)}}] This creates a new window whose upper left corner has the coordinates (\mbox{\texttt{\mdseries\slshape y}},\mbox{\texttt{\mdseries\slshape x}}) on the screen and has \mbox{\texttt{\mdseries\slshape nlines}} lines and \mbox{\texttt{\mdseries\slshape ncols}} columns, if this is possible. The arguments \mbox{\texttt{\mdseries\slshape nlines}} and \mbox{\texttt{\mdseries\slshape ncols}} can be zero, then their maximal possible values are assumed.333\item[{\index{delwin@\texttt{delwin}}\texttt{delwin(win)}}] Deletes a window.334\item[{\index{mvwin@\texttt{mvwin}}\texttt{mvwin(win, y, x)}}] Moves the upper left corner of the window to the given coordinates, if the335window still fits on the screen. With panels don't use this function, but use \texttt{move{\textunderscore}panel} mentioned below.336\item[{\index{wrefresh@\texttt{wrefresh}}\texttt{wrefresh(win)}}] Writing to a window only changes some internal buffers, this function copies337the window content to the actual display screen. You don't need this function338if you wrap your windows in panels, use \texttt{update{\textunderscore}panels} and \texttt{doupdate} instead.339\item[{\index{doupdate@\texttt{doupdate}}\texttt{doupdate()}}] Use this function to update the content of your display screen to the current340content of all windows. If your terminal is not yet in visual mode this341function changes to visual mode.342\item[{\index{endwin@\texttt{endwin}}\texttt{endwin()}}] Use this function to leave the visual mode of your terminal. (Remark: If you343use this function while not in visual mode the cursor will be moved to the344line where the visual mode was started last time. To avoid this use \texttt{isendwin} first.)345\item[{\index{isendwin@\texttt{isendwin}}\texttt{isendwin()}}] Returns \texttt{true} if called while not in visual mode and \texttt{false} otherwise346\item[{\index{getbegyx@\texttt{getbegyx}}\texttt{getbegyx(win)}}] Get the coordinates of the upper left corner of a window on the screen.347\item[{\index{getmaxyx@\texttt{getmaxyx}}\texttt{getmaxyx(win)}}] Get the number of lines and columns of a window.348\end{description}349}350351352\subsection{\textcolor{Chapter }{Manipulating panels}}\label{ssec:ncursesPan}353\logpage{[ 2, 1, 3 ]}354\hyperdef{L}{X7D541BDE7BB8BED5}{}355{356Wrap windows in panels to get a proper handling of overlapping windows on the357display. Don't forget to delete a panel before deleting the corresponding358window.359\begin{description}360\item[{\index{new_panel@\texttt{new{\textunderscore}panel}}\texttt{new{\textunderscore}panel(win)}}] Create a panel for a window.361\item[{\index{del_panel@\texttt{del{\textunderscore}panel}}\texttt{del{\textunderscore}panel(pan)}}] Delete a panel.362\item[{\index{update_panels@\texttt{update{\textunderscore}panels}}\texttt{update{\textunderscore}panels()}}] Use this function to copy changes of windows and panels to a screen buffer.363Then call \texttt{doupdate()} to update the display screen.364\item[{\index{move_panel@\texttt{move{\textunderscore}panel}}\texttt{move{\textunderscore}panel(pan, y, x)}}] Move top left corner of a panel wrapped window to coordinates (\mbox{\texttt{\mdseries\slshape y}},\mbox{\texttt{\mdseries\slshape x}}) if possible.365\item[{\index{show_panel@\texttt{show{\textunderscore}panel}} \index{hide_panel@\texttt{hide{\textunderscore}panel}}\texttt{hide{\textunderscore}panel(pan)}/\texttt{show{\textunderscore}panel(pan)}}] Hide or show, respectively, the content of a panel on the display screen.366\item[{\index{bottom_panel@\texttt{bottom{\textunderscore}panel}} \index{top_panel(@\texttt{top{\textunderscore}panel}}\texttt{top{\textunderscore}panel(pan)}/\texttt{bottom{\textunderscore}panel(pan)}}] Move a panel to the top or bottom of all panels, respectively.367\item[{\index{panel_above@\texttt{panel{\textunderscore}above}} \index{panel_below@\texttt{panel{\textunderscore}below}}\texttt{panel{\textunderscore}below(pan)}/\texttt{panel{\textunderscore}above(pan)}}] Return the panel directly below or above the given one, respectively. With368argument \texttt{0} the top or bottom panel are returned, respectively. If argument is the bottom369or top panel, respectively, then \texttt{false} is returned.370\end{description}371}372373374\subsection{\textcolor{Chapter }{Getting keyboard input}}\label{ssec:ncursesInput}375\logpage{[ 2, 1, 4 ]}376\hyperdef{L}{X7F23F5F48650A78B}{}377{378If 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.379\begin{description}380\item[{\index{wgetch@\texttt{wgetch}}\texttt{wgetch(win)}}] Reads one character from user input (returned as integer). If \texttt{wtimeout} was set with a positive \mbox{\texttt{\mdseries\slshape delay}} then the function returns \texttt{false} if there was no input for \mbox{\texttt{\mdseries\slshape 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 explained381below. (Note that there is only one input queue for all windows.)382\item[{\index{ungetch@\texttt{ungetch}}\texttt{ungetch(char)}}] Puts back the character \mbox{\texttt{\mdseries\slshape char}} on the input queue.383\end{description}384\index{NCurses.keys@\texttt{NCurses.keys}} Some terminals allow one to read special keys like one character, we import385some of the symbolic names of such keys into \textsf{GAP}. You can check for such characters by comparing with the components of the386record \texttt{NCurses.keys}, these are387\begin{description}388\item[{\texttt{UP}/\texttt{DOWN}/\texttt{LEFT}/\texttt{RIGHT}}] the arrow keys389\item[{\texttt{PPAGE}/\texttt{NPAGE}}] the page up and page down keys390\item[{\texttt{HOME}/\texttt{END}}] the home and end keys391\item[{\texttt{BACKSPACE}/\texttt{DC}}] the backspace and delete keys392\item[{\texttt{IC}}] the insert key393\item[{\texttt{ENTER}}] the enter key394\item[{\texttt{F1}/\texttt{F2}/../\texttt{F24}}] the function keys395\item[{\texttt{MOUSE}}] a pseudo key to detect mouse events396\item[{\texttt{A1}/\texttt{A3}/\texttt{B2}/\texttt{C1}/\texttt{C3}}] the keys around the arrow keys on a num pad397\end{description}398It can happen that on a specific keyboard there is no key for some of these.399Also, not all terminals can interpret all of these keys. You can check this400with the function401\begin{description}402\item[{\index{has_key@\texttt{has{\textunderscore}key}}\texttt{has{\textunderscore}key(key)}}] Checks if the special key \mbox{\texttt{\mdseries\slshape key}} is recognized by the terminal.403\end{description}404}405406407\subsection{\textcolor{Chapter }{Writing to windows}}\label{ssec:ncursesWrite}408\logpage{[ 2, 1, 5 ]}409\hyperdef{L}{X7FD4E558816B3146}{}410{411The display of text in \texttt{ncurses} windows has two aspects. The first is to get actual characters on the screen.412The second is to specify attributes which influence the display, for example413normal or bold fonts or colors. This subsection is for the first aspect.414Possible attributes are explained below in \ref{ssec:ncursesAttrs}.415\begin{description}416\item[{\index{wmove@\texttt{wmove}}\texttt{wmove(win, y, x)}}] Moves the cursor to position (\mbox{\texttt{\mdseries\slshape y}},\mbox{\texttt{\mdseries\slshape x}}), recall that the coordinates are zero based, (0,0) being the top left417corner.418\item[{\index{waddnstr@\texttt{waddnstr}}\texttt{waddnstr(win, str, len)}}] Writes the string \mbox{\texttt{\mdseries\slshape str}} to the window starting from the current cursor position. Writes at most \mbox{\texttt{\mdseries\slshape len}} characters. At end of line the cursor moves to the beginning of next line. The419behavior at the end of the window depends on the setting of \texttt{scrollok}, see \ref{ssec:ncursesTermset}.420\item[{\index{waddch@\texttt{waddch}}\texttt{waddch(win, char)}}] Writes a character to the window at the current cursor position and moves the421cursor on. The character \mbox{\texttt{\mdseries\slshape char}} is given as integer and can include attribute information.422\item[{\index{wborder@\texttt{wborder}}\texttt{wborder(win, charlist)}}] Draws a border around the window. If \mbox{\texttt{\mdseries\slshape charlist}} is a plain list of eight \textsf{GAP} characters these are taken for left/right/top/bottom sides and423top-left/top-right/bottom-left/bottom-right corners. Otherwise default424characters are used. (See \texttt{NCurses.WBorder} (\ref{NCurses.WBorder}) for a more user friendly interface.)425\item[{\index{wvline@\texttt{wvline}}\texttt{wvline(win, char, len)}}] Writes a vertical line of length \mbox{\texttt{\mdseries\slshape len}} (or as long as fitting into the window) starting from the current cursor426position to the bottom, using the character \mbox{\texttt{\mdseries\slshape char}}. If \mbox{\texttt{\mdseries\slshape char}}=\texttt{0} the default character is used.427\item[{\index{whline@\texttt{whline}}\texttt{whline(win, char, len)}}] Same as \texttt{wvline} but for horizontal lines starting from the cursor position to the right.428\item[{\index{werase@\texttt{werase}}\texttt{werase(win)}}] Deletes all characters in the window.429\item[{\index{wclear@\texttt{wclear}}\texttt{wclear(win)}}] Like \texttt{werase}, but also calls \texttt{clearok}.430\item[{\index{wclrtobot@\texttt{wclrtobot}}\texttt{wclrtobot(win)}}] Deletes all characters from cursor position to the right and bottom.431\item[{\index{wclrtoeol@\texttt{wclrtoeol}}\texttt{wclrtoeol(win)}}] Deletes all characters from cursor position to end of line.432\item[{\index{winch@\texttt{winch}}\texttt{winch(win)}}] Returns the character at current cursor position, as integer and including433color and attribute information.434\item[{\index{getyx@\texttt{getyx}}\texttt{getyx(win)}}] Returns the current cursor position.435\item[{\index{waddstr@\texttt{waddstr}}\texttt{waddstr(win, str)}}] Delegates to \texttt{waddnstr(win, str, Length(str))}.436\end{description}437}438439440\subsection{\textcolor{Chapter }{Line drawing characters}}\label{ssec:ncursesLines}441\logpage{[ 2, 1, 6 ]}442\hyperdef{L}{X8091936586CCD248}{}443{444\index{NCurses.lineDraw@\texttt{NCurses.lineDraw}} For drawing lines and grids in a terminal window you should use some "virtual"445characters which are available as components of the record \texttt{NCurses.lineDraw}. On some terminals these are nicely displayed as proper lines (on others they446are simulated by ASCII characters). These are:447\begin{description}448\item[{\texttt{BLOCK}}] solid block449\item[{\texttt{BOARD}}] board of squares450\item[{\texttt{BTEE/LTEE/RTEE/TTEE}}] bottom/left/right/top tee451\item[{\texttt{BULLET}}] bullet452\item[{\texttt{CKBOARD}}] checker board453\item[{\texttt{DARROW/LARROW/RARROW/UARROW}}] down/left/right/up arrow454\item[{\texttt{DEGREE}}] degree symbol455\item[{\texttt{DIAMOND}}] diamond456\item[{\texttt{GEQUAL}}] greater than or equal457\item[{\texttt{HLINE/VLINE}}] horizontal/vertical line458\item[{\texttt{LANTERN}}] lantern symbol459\item[{\texttt{LEQUAL}}] less than or equal460\item[{\texttt{LLCORNER/LRCORNER/ULCORNER/URCORNER}}] lower left/lower right/upper left/upper right corner461\item[{\texttt{NEQUAL}}] not equal462\item[{\texttt{PI}}] letter pi463\item[{\texttt{PLMINUS}}] plus-minus464\item[{\texttt{PLUS}}] crossing lines like a plus465\item[{\texttt{S1/S3/S7/S9}}] scan line 1/3/7/9466\item[{\texttt{STERLING}}] pound sterling467\end{description}468}469470471\subsection{\textcolor{Chapter }{Text attributes and colors}}\label{ssec:ncursesAttrs}472\logpage{[ 2, 1, 7 ]}473\hyperdef{L}{X793D897483674294}{}474{475In addition to the actual characters to be written to the screen the way they476are 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 one477introduced in{\nobreakspace} (\textbf{Reference: Attributes}).) \index{NCurses.attrs@\texttt{NCurses.attrs}} The available attributes are stored in the record \texttt{NCurses.attrs}, they are478\begin{description}479\item[{\texttt{NORMAL}}] normal display with no extra attributes.480\item[{\texttt{STANDOUT}}] displays text in the best highlighting mode of the terminal.481\item[{\texttt{UNDERLINE}}] underlines the text.482\item[{\texttt{REVERSE}}] display in reverse video by exchanging the foreground and background color.483\item[{\texttt{BLINK}}] displays the text blinking.484\item[{\texttt{DIM}}] displays the text half bright.485\item[{\texttt{BOLD}}] displays the text in a bold font.486\end{description}487Note that not all of these work with all types of terminals, or some may cause488the 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 be489accessed indirectly with \texttt{NCurses.ColorAttr} (\ref{NCurses.ColorAttr}). Attributes can be combined by adding their values (internally, they are490represented by integers). They can also be added to the integer representing a491character for use with \texttt{waddch}.492493The library functions for setting attributes are:494\begin{description}495\item[{\index{wattrset@\texttt{wattrset}}\texttt{wattrset(win, attr)}}] This sets the default (combined) attributes for a window which is added to all496characters written to it; using \texttt{NCurses.attrs.NORMAL} as attribute is a reset.497\item[{\index{wattroff@\texttt{wattroff}} \index{wattron@\texttt{wattron}}\texttt{wattron(win, attr)}/\texttt{wattroff(win, attr)}}] This sets or unsets one or some default attributes of the window without498changing the others.499\item[{\index{wattr_get@\texttt{wattr{\textunderscore}get}}\texttt{wattr{\textunderscore}get(win)}}] This returns the current default attribute and default color pair of a window.500\item[{\index{wbkgdset@\texttt{wbkgdset}}\texttt{wbkgdset(win, attr)}}] This is similar to \texttt{wattrset} but you can also add a character to \mbox{\texttt{\mdseries\slshape attr}} which is used as default instead of blanks.501\item[{\index{wbkgd@\texttt{wbkgd}}\texttt{wbkgd(win, attr)}}] This function changes the attributes for all characters in the window to \mbox{\texttt{\mdseries\slshape attr}}, also used for further characters written to that window.502\end{description}503}504505506\subsection{\textcolor{Chapter }{Low level \texttt{ncurses} mouse support}}\label{ssec:ncursesMouse}507\logpage{[ 2, 1, 8 ]}508\hyperdef{L}{X86675F5F791FEFEF}{}509{510Many \texttt{xterm} based terminals support mouse events. The recognition of mouse events by the \texttt{ncurses} input queue can be switched on and off. If switched on and a mouse event511occurs, then \texttt{NCurses.wgetch} gets \texttt{NCurses.keys.MOUSE} if the \texttt{keypad} flag is \texttt{true} (see \ref{ssec:ncursesInput}). If this is read one must call \texttt{NCurses.getmouse} which reads further characters from the input queue and interprets them as512details on the mouse event. In most cases the function \texttt{NCurses.GetMouseEvent} (\ref{NCurses.GetMouseEvent}) can be used in applications (it calls \texttt{NCurses.getmouse}). The following low level functions are available as components of the record \texttt{NCurses}.513514The names of mouse events which may be possible are stored in the list \texttt{NCurses.mouseEvents}, which starts \texttt{[} \texttt{"BUTTON1{\textunderscore}PRESSED",} \texttt{"BUTTON1{\textunderscore}RELEASED",} \texttt{"BUTTON1{\textunderscore}CLICKED",} \texttt{"BUTTON1{\textunderscore}DOUBLE{\textunderscore}CLICKED",} \texttt{"BUTTON1{\textunderscore}TRIPLE{\textunderscore}CLICKED",} \texttt{...} and contains the same for buttons number 2 to 5 and a few other events.515\begin{description}516\item[{\index{mousemask@\texttt{mousemask}} \texttt{mousemask(intlist)}}] The argument \mbox{\texttt{\mdseries\slshape intlist}} is a list of integers specifying mouse events. An entry \texttt{i} refers to the event described in \texttt{NCurses.mouseEvents[i+1]}. It returns a record with components \texttt{.new} (for the current setting) and \texttt{.old} (for the previous setting) which are again lists of integers with the same517meaning. Note that \texttt{.new} may be different from \mbox{\texttt{\mdseries\slshape intlist}}, it is always the empty list if the terminal does not support mouse events.518In applications use \texttt{NCurses.UseMouse} (\ref{NCurses.UseMouse}) instead of this low level function.519\item[{\index{getmouse@\texttt{getmouse}} \texttt{getmouse()}}] This function must be called after a key \texttt{NCurses.keys.MOUSE} was read. It returns a list with three entries \texttt{[y, x, intlist]} where \texttt{y} and \texttt{x} are the coordinates of the character cell where the mouse event occured and \texttt{intlist} describes the event, it should have length one and refers to a position in \texttt{NCurses.mouseEvents}.520\item[{\index{wenclose@\texttt{wenclose}} \texttt{wenclose(win, y, x)}}] This functions returns \texttt{true} if the screen position \mbox{\texttt{\mdseries\slshape y}}, \mbox{\texttt{\mdseries\slshape x}} is within window \mbox{\texttt{\mdseries\slshape win}} and \texttt{false} otherwise.521\item[{\index{mouseinterval@\texttt{mouseinterval}} \texttt{mouseinterval(t)}}] Sets the time to recognize a press and release of a mouse button as a click to \mbox{\texttt{\mdseries\slshape t}} milliseconds. (Note that this may have no effect because a window manager may522catch this.)523\end{description}524}525526527\subsection{\textcolor{Chapter }{Miscellaneous function}}\label{ssec:ncursesMisc}528\logpage{[ 2, 1, 9 ]}529\hyperdef{L}{X83897BF984211EFD}{}530{531\index{mnap@\texttt{mnap}} \index{IsStdinATty@\texttt{IsStdinATty}} \index{IsStdoutATty@\texttt{IsStdoutATty}} We also provide the \texttt{ncurses} function \texttt{mnap(msec)} which is a sleep for \mbox{\texttt{\mdseries\slshape msec}} milliseconds.532533Furthermore, there a two utilities which can be useful for scripts and534testing, namely a check if standard input or standard output are connected to535terminals. These can be called as \texttt{NCurses.IsStdinATty()} or \texttt{NCurses.IsStdoutATty()}, respectively. }536537}538539540\section{\textcolor{Chapter }{The \texttt{ncurses} \textsf{GAP} functions}}\label{sec:cursesGAP}541\logpage{[ 2, 2, 0 ]}542\hyperdef{L}{X864A5C1C7F181B4B}{}543{544The 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}).545546In \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 are547no longer needed.548549Each window can be wrapped in one panel which is accessed by the same integer.550(Window \texttt{0} cannot be used with a panel.)551552Coordinates in windows are the same zero based integers as in the553corresponding \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 as554argument, e.g., \texttt{NCurses.getmaxyx(win)} returns a list \texttt{[nrows, ncols]} of two integers.555556Characters 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 color557settings to it for use with \texttt{NCurses.waddch}.558559When writing an application decide about an appropriate terminal setting for560your 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.561562We also provide some higher level functionality for displaying marked up text,563see \texttt{NCurses.PutLine} (\ref{NCurses.PutLine}) and \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine}).564565We now describe some utility functions for putting text on a terminal window.566567\subsection{\textcolor{Chapter }{NCurses.ColorAttr}}568\logpage{[ 2, 2, 1 ]}\nobreak569\hyperdef{L}{X83ADB4E37C105B8C}{}570{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.ColorAttr({\mdseries\slshape fgcolor, bgcolor})\index{NCurses.ColorAttr@\texttt{NCurses.ColorAttr}}571\label{NCurses.ColorAttr}572}\hfill{\scriptsize (function)}}\\573\textbf{\indent Returns:\ }574an attribute for setting the foreground and background color to be used on a575terminal window (it is a \textsf{GAP} integer).576577\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.attrs.has{\textunderscore}colors\index{NCurses.attrs.hascolors@\texttt{NCurses.attrs.has{\textunderscore}colors}}578\label{NCurses.attrs.hascolors}579}\hfill{\scriptsize (global variable)}}\\580581582The return value can be used like any other attribute as described in \ref{ssec:ncursesAttrs}. The arguments \mbox{\texttt{\mdseries\slshape fgcolor}} and \mbox{\texttt{\mdseries\slshape 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.583Alternatively, the numbers 0 to 7 can be used directly as arguments.584585Note that terminals can be configured in a way such that these named colors586are not the colors which are actually displayed.587588The variable \texttt{NCurses.attrs.has{\textunderscore}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 not589support colors then \texttt{NCurses.ColorAttr} always returns \texttt{NCurses.attrs.NORMAL}.590591For an attribute setting the foreground color with the default background592color of the terminal use \texttt{-1} as \mbox{\texttt{\mdseries\slshape bgcolor}} or the same as \mbox{\texttt{\mdseries\slshape fgcolor}}.593\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]594!gapprompt@gap>| !gapinput@win := NCurses.newwin(0,0,0,0);; pan := NCurses.new_panel(win);;|595!gapprompt@gap>| !gapinput@defc := NCurses.defaultColors;;|596!gapprompt@gap>| !gapinput@NCurses.wmove(win, 0, 0);;|597!gapprompt@gap>| !gapinput@for a in defc do for b in defc do|598!gapprompt@>| !gapinput@ NCurses.wattrset(win, NCurses.ColorAttr(a, b));|599!gapprompt@>| !gapinput@ NCurses.waddstr(win, Concatenation(a,"/",b,"\t"));|600!gapprompt@>| !gapinput@ od; od;|601!gapprompt@gap>| !gapinput@if NCurses.IsStdoutATty() then|602!gapprompt@>| !gapinput@ NCurses.update_panels();; NCurses.doupdate();;|603!gapprompt@>| !gapinput@ NCurses.napms(5000);; # show for 5 seconds|604!gapprompt@>| !gapinput@ NCurses.endwin();; NCurses.del_panel(pan);; NCurses.delwin(win);;|605!gapprompt@>| !gapinput@ fi;|606\end{Verbatim}607}608609610611\subsection{\textcolor{Chapter }{NCurses.SetTerm}}612\logpage{[ 2, 2, 2 ]}\nobreak613\hyperdef{L}{X879D81B37A0A4E8F}{}614{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.SetTerm({\mdseries\slshape [record]})\index{NCurses.SetTerm@\texttt{NCurses.SetTerm}}615\label{NCurses.SetTerm}616}\hfill{\scriptsize (function)}}\\617618619This function provides a unified interface to the various terminal setting620functions 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).621622The default, if no argument is given, is \texttt{rec(cbreak := true, echo := false, nl := false, intrflush := false, leaveok :=623true, scrollok := false, keypad := true)}. (This is a useful setting for many applications.) If there is an argument \mbox{\texttt{\mdseries\slshape record}}, then the given components overwrite the corresponding defaults. }624625626627\subsection{\textcolor{Chapter }{NCurses.IsAttributeLine}}628\logpage{[ 2, 2, 3 ]}\nobreak629\hyperdef{L}{X81D1FC927C455AEB}{}630{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.IsAttributeLine({\mdseries\slshape obj})\index{NCurses.IsAttributeLine@\texttt{NCurses.IsAttributeLine}}631\label{NCurses.IsAttributeLine}632}\hfill{\scriptsize (function)}}\\633\textbf{\indent Returns:\ }634\texttt{true} if the argument describes a string with attributes.635636637638An \emph{attribute line} describes a string with attributes. It is represented by either a string or a639dense list of strings, integers, and Booleans immediately following integers,640where at least one list entry must \emph{not} be a string. (The reason is that we want to be able to distinguish between an641attribute line and a list of such lines, and that the case of plain strings is642perhaps the most usual one, so we do not want to force wrapping each string in643a list.) The integers denote attribute values such as color or font644information, the Booleans denote that the attribute given by the preceding645integer is set or reset.646647If an integer is not followed by a Boolean then it is used as the attribute648for the following characters, that is it overwrites all previously set649attributes. Note that in some applications the variant with explicit Boolean650values is preferable, because such a line can nicely be highlighted just by651prepending a \texttt{NCurses.attrs.STANDOUT} attribute.652653For an overview of attributes, see{\nobreakspace}\ref{ssec:ncursesAttrs}.654655656\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]657!gapprompt@gap>| !gapinput@NCurses.IsAttributeLine( "abc" );|658true659!gapprompt@gap>| !gapinput@NCurses.IsAttributeLine( [ "abc", "def" ] );|660false661!gapprompt@gap>| !gapinput@NCurses.IsAttributeLine( [ NCurses.attrs.UNDERLINE, true, "abc" ] );|662true663!gapprompt@gap>| !gapinput@NCurses.IsAttributeLine( "" ); NCurses.IsAttributeLine( [] );|664true665false666\end{Verbatim}667668669The \emph{empty string} is an attribute line whereas the \emph{empty list} (which is not in \texttt{IsStringRep} (\textbf{Reference: IsStringRep})) is \emph{not} an attribute line. }670671672673\subsection{\textcolor{Chapter }{NCurses.ConcatenationAttributeLines}}674\logpage{[ 2, 2, 4 ]}\nobreak675\hyperdef{L}{X8372F0C57816A29E}{}676{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.ConcatenationAttributeLines({\mdseries\slshape lines[, keep]})\index{NCurses.ConcatenationAttributeLines@\texttt{NCurses.ConcatenationAttributeLines}}677\label{NCurses.ConcatenationAttributeLines}678}\hfill{\scriptsize (function)}}\\679\textbf{\indent Returns:\ }680an attribute line.681682683684For a list \mbox{\texttt{\mdseries\slshape 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{\mdseries\slshape lines}}.685686If the optional argument \mbox{\texttt{\mdseries\slshape keep}} is \texttt{true} then attributes set in an entry of \mbox{\texttt{\mdseries\slshape lines}} are valid also for the following entries of \mbox{\texttt{\mdseries\slshape lines}}. Otherwise (in particular if there is no second argument) the attributes are687reset to \texttt{NCurses.attrs.NORMAL} between the entries of \mbox{\texttt{\mdseries\slshape lines}}.688\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]689!gapprompt@gap>| !gapinput@plain_str:= "hello";;|690!gapprompt@gap>| !gapinput@with_attr:= [ NCurses.attrs.BOLD, "bold" ];;|691!gapprompt@gap>| !gapinput@NCurses.ConcatenationAttributeLines( [ plain_str, plain_str ] );|692"hellohello"693!gapprompt@gap>| !gapinput@NCurses.ConcatenationAttributeLines( [ plain_str, with_attr ] );|694[ "hello", 2097152, "bold" ]695!gapprompt@gap>| !gapinput@NCurses.ConcatenationAttributeLines( [ with_attr, plain_str ] );|696[ 2097152, "bold", 0, "hello" ]697!gapprompt@gap>| !gapinput@NCurses.ConcatenationAttributeLines( [ with_attr, with_attr ] );|698[ 2097152, "bold", 0, 2097152, "bold" ]699!gapprompt@gap>| !gapinput@NCurses.ConcatenationAttributeLines( [ with_attr, with_attr ], true );|700[ 2097152, "bold", 2097152, "bold" ]701\end{Verbatim}702}703704705706\subsection{\textcolor{Chapter }{NCurses.RepeatedAttributeLine}}707\logpage{[ 2, 2, 5 ]}\nobreak708\hyperdef{L}{X7D2EB0BF82C4F25C}{}709{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.RepeatedAttributeLine({\mdseries\slshape line, width})\index{NCurses.RepeatedAttributeLine@\texttt{NCurses.RepeatedAttributeLine}}710\label{NCurses.RepeatedAttributeLine}711}\hfill{\scriptsize (function)}}\\712\textbf{\indent Returns:\ }713an attribute line.714715716717For an attribute line \mbox{\texttt{\mdseries\slshape line}} (see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine})) and a positive integer \mbox{\texttt{\mdseries\slshape width}}, \texttt{NCurses.RepeatedAttributeLine} returns an attribute line with \mbox{\texttt{\mdseries\slshape width}} displayed characters (see{\nobreakspace}\texttt{NCurses.WidthAttributeLine} (\ref{NCurses.WidthAttributeLine})) that is obtained by concatenating sufficiently many copies of \mbox{\texttt{\mdseries\slshape line}} and cutting off a tail if applicable.718719720\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]721!gapprompt@gap>| !gapinput@NCurses.RepeatedAttributeLine( "12345", 23 );|722"12345123451234512345123"723!gapprompt@gap>| !gapinput@NCurses.RepeatedAttributeLine( [ NCurses.attrs.BOLD, "12345" ], 13 );|724[ 2097152, "12345", 0, 2097152, "12345", 0, 2097152, "123" ]725\end{Verbatim}726}727728729730\subsection{\textcolor{Chapter }{NCurses.PutLine}}731\logpage{[ 2, 2, 6 ]}\nobreak732\hyperdef{L}{X83FFD5047ADE716E}{}733{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.PutLine({\mdseries\slshape win, y, x, lines[, skip]})\index{NCurses.PutLine@\texttt{NCurses.PutLine}}734\label{NCurses.PutLine}735}\hfill{\scriptsize (function)}}\\736\textbf{\indent Returns:\ }737\texttt{true} if \mbox{\texttt{\mdseries\slshape lines}} were written, otherwise \texttt{false}.738739740741The argument \mbox{\texttt{\mdseries\slshape 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 to742window \mbox{\texttt{\mdseries\slshape win}} at and below of position \mbox{\texttt{\mdseries\slshape y}}, \mbox{\texttt{\mdseries\slshape x}}.743744If the argument \mbox{\texttt{\mdseries\slshape skip}} is given, it must be a nonnegative integer. In that case the first \mbox{\texttt{\mdseries\slshape skip}} characters of each given line are not written to the window (but the745attributes are). }746747748749\subsection{\textcolor{Chapter }{NCurses.WidthAttributeLine}}750\logpage{[ 2, 2, 7 ]}\nobreak751\hyperdef{L}{X82C53ACD805EE0C3}{}752{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.WidthAttributeLine({\mdseries\slshape line})\index{NCurses.WidthAttributeLine@\texttt{NCurses.WidthAttributeLine}}753\label{NCurses.WidthAttributeLine}754}\hfill{\scriptsize (function)}}\\755\textbf{\indent Returns:\ }756number of displayed characters in an attribute line.757758759760For an attribute line \mbox{\texttt{\mdseries\slshape line}} (see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine})), the function returns the number of displayed characters of \mbox{\texttt{\mdseries\slshape line}}. \index{displayed characters}761762763\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]764!gapprompt@gap>| !gapinput@NCurses.WidthAttributeLine( "abcde" );|7655766!gapprompt@gap>| !gapinput@NCurses.WidthAttributeLine( [ NCurses.attrs.BOLD, "abc",|767!gapprompt@>| !gapinput@ NCurses.attrs.NORMAL, "de" ] );|7685769\end{Verbatim}770}771772773774\subsection{\textcolor{Chapter }{NCurses.Grid}}775\logpage{[ 2, 2, 8 ]}\nobreak776\hyperdef{L}{X790715F683BF1E66}{}777{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.Grid({\mdseries\slshape win, trow, brow, lcol, rcol, rowinds, colinds})\index{NCurses.Grid@\texttt{NCurses.Grid}}778\label{NCurses.Grid}779}\hfill{\scriptsize (function)}}\\780781782This function draws a grid of horizontal and vertical lines on the window \mbox{\texttt{\mdseries\slshape 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 and783right column, and lists of row and column numbers where lines should be drawn.784\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]785!gapprompt@gap>| !gapinput@fun := function() local win, pan;|786!gapprompt@>| !gapinput@ win := NCurses.newwin(0,0,0,0);|787!gapprompt@>| !gapinput@ pan := NCurses.new_panel(win);|788!gapprompt@>| !gapinput@ NCurses.Grid(win, 2, 11, 5, 22, [5, 6], [13, 14]);|789!gapprompt@>| !gapinput@ NCurses.PutLine(win, 12, 0, "Press <Enter> to quit");|790!gapprompt@>| !gapinput@ NCurses.update_panels(); NCurses.doupdate();|791!gapprompt@>| !gapinput@ NCurses.wgetch(win);|792!gapprompt@>| !gapinput@ NCurses.endwin();|793!gapprompt@>| !gapinput@ NCurses.del_panel(pan); NCurses.delwin(win);|794!gapprompt@>| !gapinput@end;;|795!gapprompt@gap>| !gapinput@fun();|796\end{Verbatim}797}798799800801\subsection{\textcolor{Chapter }{NCurses.WBorder}}802\logpage{[ 2, 2, 9 ]}\nobreak803\hyperdef{L}{X82B801587B37D571}{}804{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.WBorder({\mdseries\slshape win[, chars]})\index{NCurses.WBorder@\texttt{NCurses.WBorder}}805\label{NCurses.WBorder}806}\hfill{\scriptsize (function)}}\\807808809This is a convenient interface to the \texttt{ncurses} function \texttt{wborder}. It draws a border around the window \mbox{\texttt{\mdseries\slshape win}}. If no second argument is given the default line drawing characters are used,810see \ref{ssec:ncursesLines}. Otherwise, \mbox{\texttt{\mdseries\slshape chars}} must be a list of \textsf{GAP} characters or integers specifying characters, possibly with attributes. If \mbox{\texttt{\mdseries\slshape chars}} has length 8 the characters are used for the left/right/top/bottom sides and811top-left/top-right/bottom-left/bottom-right corners. If \mbox{\texttt{\mdseries\slshape chars}} contains 2 characters the first is used for the sides and the second for all812corners. If \mbox{\texttt{\mdseries\slshape chars}} contains just one character it is used for all sides including the corners. }813814815\subsection{\textcolor{Chapter }{Mouse support in \texttt{ncurses} applications}}\logpage{[ 2, 2, 10 ]}816\hyperdef{L}{X799C033A7AB582D7}{}817{818\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.UseMouse({\mdseries\slshape on})\index{NCurses.UseMouse@\texttt{NCurses.UseMouse}}819\label{NCurses.UseMouse}820}\hfill{\scriptsize (function)}}\\821\textbf{\indent Returns:\ }822a record823824\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.GetMouseEvent({\mdseries\slshape })\index{NCurses.GetMouseEvent@\texttt{NCurses.GetMouseEvent}}825\label{NCurses.GetMouseEvent}826}\hfill{\scriptsize (function)}}\\827\textbf{\indent Returns:\ }828a list of records829830831832\texttt{ncurses} allows on some terminals (\texttt{xterm} and related) to catch mouse events. In principle a subset of events can be833caught, see \texttt{mousemask} in \ref{ssec:ncursesMouse}. But this does not seem to work well with proper subsets of possible events834(probably due to intermediate processes X, window manager, terminal835application, ...). Therefore we suggest to catch either all or no mouse events836in applications.837838This can be done with \texttt{NCurses.UseMouse} with argument \texttt{true} to switch on the recognition of mouse events and \texttt{false} to switch it off. The function returns a record with components \texttt{.new} and \texttt{.old} which are both set to the status \texttt{true} or \texttt{false} from after and before the call, respectively. (There does not seem to be a839possibility to get the current status without calling \texttt{NCurses.UseMouse}.) If you call the function with argument \texttt{true} and the \texttt{.new} component of the result is \texttt{false}, then the terminal does not support mouse events.840841When the recognition of mouse events is switched on and a mouse event occurs842then the key \texttt{NCurses.keys.MOUSE} is found in the input queue, see \texttt{wgetch} in \ref{ssec:ncursesInput}. If this key is read the low level function \texttt{NCurses.getmouse} must be called to fetch further details about the event from the input queue,843see \ref{ssec:ncursesMouse}. In many cases this can be done by calling the function \texttt{NCurses.GetMouseEvent} which also generates additional information. The return value is a list of844records, one for each panel over which the event occured, these panels sorted845from top to bottom (so, often you will just need the first entry if there is846any). Each of these records has components \texttt{.win}, the corresponding window of the panel, \texttt{.y} and \texttt{.x}, the relative coordinates in window \texttt{.win} where the event occured, and \texttt{.event}, which is bound to one of the strings in \texttt{NCurses.mouseEvents} which describes the event.847848\emph{Suggestion:} Always make the use of the mouse optional in your application. Allow the user849to switch mouse usage on and off while your application is running. Some users850may not like to give mouse control to your application, for example the851standard cut and paste functionality cannot be used while mouse events are852caught. }853854855856\subsection{\textcolor{Chapter }{NCurses.SaveWin}}857\logpage{[ 2, 2, 11 ]}\nobreak858\hyperdef{L}{X85FB1D7878A322EB}{}859{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.SaveWin({\mdseries\slshape win})\index{NCurses.SaveWin@\texttt{NCurses.SaveWin}}860\label{NCurses.SaveWin}861}\hfill{\scriptsize (function)}}\\862\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.StringsSaveWin({\mdseries\slshape cont})\index{NCurses.StringsSaveWin@\texttt{NCurses.StringsSaveWin}}863\label{NCurses.StringsSaveWin}864}\hfill{\scriptsize (function)}}\\865\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.RestoreWin({\mdseries\slshape win, cont})\index{NCurses.RestoreWin@\texttt{NCurses.RestoreWin}}866\label{NCurses.RestoreWin}867}\hfill{\scriptsize (function)}}\\868\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.ShowSaveWin({\mdseries\slshape cont})\index{NCurses.ShowSaveWin@\texttt{NCurses.ShowSaveWin}}869\label{NCurses.ShowSaveWin}870}\hfill{\scriptsize (function)}}\\871\textbf{\indent Returns:\ }872a \textsf{GAP} object describing the contents of a window.873874875876These 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 integers877describing the content of window \mbox{\texttt{\mdseries\slshape win}}. The integers in the latter contain the displayed characters plus the878attributes for the display.879880The function \texttt{NCurses.StringsSaveWin} translates data \mbox{\texttt{\mdseries\slshape 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 the881attributes. You can view the result with \texttt{NCurses.Pager} (\ref{NCurses.Pager}).882883The argument \mbox{\texttt{\mdseries\slshape 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{\mdseries\slshape win}}, starting from the top-left corner as much as it fits.884885The 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). }886887}888889}890891892\chapter{\textcolor{Chapter }{Utilities using \texttt{ncurses}}}\label{ch:util}893\logpage{[ 3, 0, 0 ]}894\hyperdef{L}{X7F3A63788200AB4F}{}895{896In 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 utility897functions within larger applications.898\section{\textcolor{Chapter }{\texttt{ncurses} utilities}}\label{sect:ncurses_utils}899\logpage{[ 3, 1, 0 ]}900\hyperdef{L}{X84E621798148857D}{}901{902If 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 still903open, 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}.904905\subsection{\textcolor{Chapter }{NCurses.Alert}}906\logpage{[ 3, 1, 1 ]}\nobreak907\hyperdef{L}{X83E95B4A83BC473E}{}908{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.Alert({\mdseries\slshape messages, timeout[, attrs]})\index{NCurses.Alert@\texttt{NCurses.Alert}}909\label{NCurses.Alert}910}\hfill{\scriptsize (function)}}\\911\textbf{\indent Returns:\ }912the integer corresponding to the character entered, or \texttt{fail}.913914915916In visual mode, \texttt{Print} (\textbf{Reference: Print}) cannot be used for messages. An alternative is given by \texttt{NCurses.Alert}.917918Let \mbox{\texttt{\mdseries\slshape messages}} be either an attribute line or a nonempty list of attribute lines, and \mbox{\texttt{\mdseries\slshape timeout}} be a nonnegative integer. \texttt{NCurses.Alert} shows \mbox{\texttt{\mdseries\slshape messages}} in a bordered box in the middle of the screen.919920If \mbox{\texttt{\mdseries\slshape timeout}} is zero then the box is closed after any user input, and the integer921corresponding to the entered key is returned. If \mbox{\texttt{\mdseries\slshape timeout}} is a positive number $n$, say, then the box is closed after $n$ milliseconds, and \texttt{fail} is returned.922923If \texttt{timeout} is zero and mouse events are enabled (see \texttt{NCurses.UseMouse} (\ref{NCurses.UseMouse}))\index{mouse events} then the box can be moved inside the window via mouse events.924925If the optional argument \mbox{\texttt{\mdseries\slshape attrs}} is given, it must be an integer representing attributes such as the components926of \texttt{NCurses.attrs} (see Section{\nobreakspace}\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}.927928929\begin{Verbatim}[commandchars=@|E,fontsize=\small,frame=single,label=Example]930@gapprompt|gap>E @gapinput|NCurses.Alert( "Hello world!", 1000 );E931fail932@gapprompt|gap>E @gapinput|NCurses.Alert( [ "Hello world!",E933@gapprompt|>E @gapinput| [ "Hello ", NCurses.attrs.BOLD, "bold!" ] ], 1500,E934@gapprompt|>E @gapinput| NCurses.ColorAttr( "red", -1 ) + NCurses.attrs.BOLD );E935fail936\end{Verbatim}937}938939940941\subsection{\textcolor{Chapter }{NCurses.Select}}942\logpage{[ 3, 1, 2 ]}\nobreak943\hyperdef{L}{X833D321E86528981}{}944{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.Select({\mdseries\slshape poss[, single[, none]]})\index{NCurses.Select@\texttt{NCurses.Select}}945\label{NCurses.Select}946}\hfill{\scriptsize (function)}}\\947\textbf{\indent Returns:\ }948Position or list of positions, or \texttt{false}.949950951952\index{checkbox!see NCurses.Select} \index{radio button!see NCurses.Select} This function allows the user to select one or several items from a given953list. In the simplest case \mbox{\texttt{\mdseries\slshape 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 in954your lines should be switched on and off separately by \texttt{true}/\texttt{false} entries such that the lines can be nicely highlighted.955956The optional argument \mbox{\texttt{\mdseries\slshape single}} must be \texttt{true} (default) or \texttt{false}. In the second case, an arbitrary number of items can be marked and the957function returns the list of their indices.958959If \mbox{\texttt{\mdseries\slshape single}} is \texttt{true} a third argument \mbox{\texttt{\mdseries\slshape none}} can be given. If it is \texttt{true} then it is possible to leave the selection without choosing an item, in this960case \texttt{false} is returned.961962More details can be given to the function by giving a record as argument \mbox{\texttt{\mdseries\slshape poss}}. It can have the following components:963\begin{description}964\item[{\texttt{items}}] The list of attribute lines as described above.965\item[{\texttt{single}}] Boolean with the same meaning as the optional argument \mbox{\texttt{\mdseries\slshape single}}.966\item[{\texttt{none}}] Boolean with the same meaning as the optional argument \mbox{\texttt{\mdseries\slshape none}}.967\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), or the string \texttt{"fit"} which means the smallest possible window.968\item[{\texttt{align}}] A substring of \texttt{"bclt"}, which describes the alignment of the window in the terminal. The meaning and969the default are the same as for \texttt{BrowseData.IsBrowseTableCellData} (\ref{BrowseData.IsBrowseTableCellData}).970\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). This value has priority over the \texttt{align} component.971\item[{\texttt{attribute}}] An attribute used for the display of the window (default is \texttt{NCurses.attrs.NORMAL}).972\item[{\texttt{border}}] If the window should be displayed with a border then set to \texttt{true} (default is \texttt{false}) or to an integer representing attributes such as the components of \texttt{NCurses.attrs} (see Section{\nobreakspace}\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}.973\item[{\texttt{header}}] An attribute line used as header line (the default depends on the settings of \texttt{single} and \texttt{none}).974\item[{\texttt{hint}}] An attribute line used as hint in the last line of the window (the default975depends on the settings of \texttt{single} and \texttt{none}).976\item[{\texttt{onSubmitFunction}}] A function that is called when the user submits the selection; the argument977for this call is the current value of the record \mbox{\texttt{\mdseries\slshape poss}}. If the function returns \texttt{true} then the selected entries are returned as usual, otherwise the selection978window is kept open, waiting for new inputs; if the function returns a979nonempty list of attribute lines then these messages are shown using \texttt{NCurses.Alert} (\ref{NCurses.Alert}).980\end{description}981982983If mouse events are enabled (see \texttt{NCurses.UseMouse} (\ref{NCurses.UseMouse}))\index{mouse events} then the window can be moved on the screen via mouse events, the focus can be984moved to an entry, and (if \texttt{single} is \texttt{false}) the selection of an entry can be toggled.985986987\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]988!gapprompt@gap>| !gapinput@index := NCurses.Select(["Apples", "Pears", "Oranges"]);|989!gapprompt@gap>| !gapinput@index := NCurses.Select(rec(|990!gapprompt@>| !gapinput@ items := ["Apples", "Pears", "Oranges"],|991!gapprompt@>| !gapinput@ single := false,|992!gapprompt@>| !gapinput@ border := true,|993!gapprompt@>| !gapinput@ begin := [5, 5],|994!gapprompt@>| !gapinput@ size := [8, 60],|995!gapprompt@>| !gapinput@ header := "Choose at least two fruits",|996!gapprompt@>| !gapinput@ attribute := NCurses.ColorAttr("yellow","red"),|997!gapprompt@>| !gapinput@ onSubmitFunction:= function( r )|998!gapprompt@>| !gapinput@ if Length( r.RESULT ) < 2 then|999!gapprompt@>| !gapinput@ return [ "Choose at least two fruits" ];|1000!gapprompt@>| !gapinput@ else|1001!gapprompt@>| !gapinput@ return true;|1002!gapprompt@>| !gapinput@ fi;|1003!gapprompt@>| !gapinput@ end ) );|1004\end{Verbatim}1005}1006100710081009\subsection{\textcolor{Chapter }{NCurses.GetLineFromUser}}1010\logpage{[ 3, 1, 3 ]}\nobreak1011\hyperdef{L}{X837EFD8A842257EA}{}1012{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.GetLineFromUser({\mdseries\slshape pre})\index{NCurses.GetLineFromUser@\texttt{NCurses.GetLineFromUser}}1013\label{NCurses.GetLineFromUser}1014}\hfill{\scriptsize (function)}}\\1015\textbf{\indent Returns:\ }1016User input as string.1017101810191020This function can be used to get an input string from the user. It opens a one1021line window and writes the given string \mbox{\texttt{\mdseries\slshape 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.)10221023Some 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.10241025Instead of a string, \mbox{\texttt{\mdseries\slshape pre}} can also be a record with the component \texttt{prefix}, whose value is the string described above. The following optional components1026of this record are supported.102710281029\begin{description}1030\item[{\texttt{window}}] The window with the input field is created relative to this window, the1031default is $0$.1032\item[{\texttt{begin}}] This is a list with the coordinates of the upper left corner of the window1033with 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.1034\item[{\texttt{default}}] This string appears as result when the window is opened, the default is an1035empty string.1036\end{description}1037103810391040\begin{Verbatim}[commandchars=@|A,fontsize=\small,frame=single,label=Example]1041@gapprompt|gap>A @gapinput|str := NCurses.GetLineFromUser("Your Name: ");;A1042@gapprompt|gap>A @gapinput|Print("Hello ", str, "!\n");A1043\end{Verbatim}1044}1045104610471048\subsection{\textcolor{Chapter }{NCurses.Pager}}1049\logpage{[ 3, 1, 4 ]}\nobreak1050\hyperdef{L}{X87E1B2787F588CC0}{}1051{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.Pager({\mdseries\slshape lines[, border[, ly, lx, y, x]]})\index{NCurses.Pager@\texttt{NCurses.Pager}}1052\label{NCurses.Pager}1053}\hfill{\scriptsize (function)}}\\105410551056This is a simple pager utility for displaying and scrolling text. The argument \mbox{\texttt{\mdseries\slshape 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. In1057case of a record the following components are recognized:105810591060\begin{description}1061\item[{\texttt{lines}}] The list of attribute lines or a string as described above.1062\item[{\texttt{start}}] Line number to start the display.1063\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).1064\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).1065\item[{\texttt{attribute}}] An attribute used for the display of the window (default is \texttt{NCurses.attrs.NORMAL}).1066\item[{\texttt{border}}] Either one of \texttt{true}/\texttt{false} to show the pager window with or without a standard border. Or it can be1067string with eight, two or one characters, giving characters to be used for a1068border, see \texttt{NCurses.WBorder} (\ref{NCurses.WBorder}).1069\item[{\texttt{hint}}] A text for usage info in the last line of the window.1070\end{description}107110721073As an abbreviation the information from \texttt{border}, \texttt{size} and \texttt{begin} can also be specified in optional arguments.1074\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]1075!gapprompt@gap>| !gapinput@lines := List([1..100],i-> ["line ",NCurses.attrs.BOLD,String(i)]);;|1076!gapprompt@gap>| !gapinput@NCurses.Pager(lines);|1077\end{Verbatim}1078}107910801081\subsection{\textcolor{Chapter }{Selection of help matches}}\label{ssec:selhelpmatch}1082\logpage{[ 3, 1, 5 ]}1083\hyperdef{L}{X7D5685767D4FCD8E}{}1084{1085After loading the \textsf{Browse} package \textsf{GAP}'s help system behaves slightly different when a request yields several1086matches. The matches are shown via \texttt{NCurses.Select} (\ref{NCurses.Select}), the list can be searched and filtered, and one can choose one match for1087immediate display. It is possible to not choose a match and the \texttt{?{\textless}nr{\textgreater}} syntax still works.10881089If you want the original behavior call \texttt{SetUserPreference( "Browse", "SelectHelpMatches", false );} in your \textsf{GAP} session or \texttt{gap.ini} file, see{\nobreakspace} (\textbf{Reference: Configuring User preferences}). }109010911092\subsection{\textcolor{Chapter }{Selection of package names}}\label{ssec:selpackagename}1093\logpage{[ 3, 1, 6 ]}1094\hyperdef{L}{X867BB82985D7953A}{}1095{1096The function \texttt{LoadPackage} (\textbf{Reference: LoadPackage}) shows a list of matches if only a prefix of a package name is given. After1097loading the \textsf{Browse} package, \texttt{NCurses.Select} (\ref{NCurses.Select}) is used for that, and one can choose a match.10981099If you want the original behavior call \texttt{SetUserPreference( "Browse", "SelectPackageName", false );} in your \textsf{GAP} session or \texttt{gap.ini} file, see{\nobreakspace} (\textbf{Reference: Configuring User preferences}). }11001101}110211031104\section{\textcolor{Chapter }{A Demo Function}}\label{sec:demo}1105\logpage{[ 3, 2, 0 ]}1106\hyperdef{L}{X7EF34E0E7FBD3A3B}{}1107{110811091110\subsection{\textcolor{Chapter }{NCurses.Demo}}1111\logpage{[ 3, 2, 1 ]}\nobreak1112\hyperdef{L}{X8681359F8064597B}{}1113{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.Demo({\mdseries\slshape [inputs]})\index{NCurses.Demo@\texttt{NCurses.Demo}}1114\label{NCurses.Demo}1115}\hfill{\scriptsize (function)}}\\111611171118Let \mbox{\texttt{\mdseries\slshape 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}.11191120\texttt{NCurses.Demo} lets the user choose an entry from \mbox{\texttt{\mdseries\slshape 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 to1121functions using \texttt{ncurses} are shown in the rest of the screen. After the execution of the statements1122(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.11231124The \textsf{GAP} statements in the \texttt{cleanup} component, if available, are executed whenever the user does not continue;1125this is needed for deleting panels and windows that are defined in the1126statements of the current entry.11271128Note 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 that1129shows the inputs; so applications of \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) use automatically the maximal part of the screen as their window. It is1130recommended to use a screen with at least $80$ columns and at least $37$ rows. }11311132}11331134}113511361137\chapter{\textcolor{Chapter }{Browsing Tables in \textsf{GAP} using \texttt{ncurses} {\textendash}The User Interface}}\label{chap:browse-user}1138\logpage{[ 4, 0, 0 ]}1139\hyperdef{L}{X877E60DE7F53FDEC}{}1140{1141As stated in Section{\nobreakspace}\ref{sec:intro}, one aim of the \textsf{Browse} package is to provide tools for the quite usual task to show a two-dimensional1142array or certain rows and columns of it on a character screen in a formatted1143way, to navigate in this array via key strokes (and mouse events), and to1144search for strings, to sort the array by row or column values etc.11451146The 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 also1147arranged 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 are1148shown to the left of the main table, the column labels are shown above the1149main table. The space above the row labels and to the left of the column1150labels 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 and1151footer are not separated into columns. So the shown window has the following1152structure.1153115411551156\begin{center}1157\begin{tabular}{|c|c|}1158\hline1159\multicolumn{2}{|c|}{header} \\1160\hline1161corner & column labels \\1162\hline1163& \\1164row & main \\1165labels & table \\1166& \\1167\hline1168\multicolumn{2}{|c|}{footer} \\1169\hline1170\end{tabular}1171\end{center}1172117311741175If not the whole tables fit into the window then only subranges of rows and1176columns of the main table are shown, together with the corresponding row and1177column labels. Also in this case, the row heights and column widths are1178computed w.r.t. the whole table not w.r.t. the shown rows and columns. This1179means that the shown row labels are unchanged if the range of shown columns is1180changed, the shown column labels are unchanged if the range of shown rows is1181changed, and the whole corner table is always shown.11821183The current chapter describes the user interface for \emph{standard applications} of this kind, i.{\nobreakspace}e., those applications for which one just has1184to collect the data to be shown in a record {\textendash}which we call a \emph{browse table}{\textendash} without need for additional \textsf{GAP} programming.11851186Section{\nobreakspace}\ref{sec:features} gives an overview of the features available in standard browse table1187applications, and Section{\nobreakspace}\ref{sec:browsebasicdata} describes the data structures used in browse tables. Finally,1188Section{\nobreakspace}\ref{sec:browsegeneric} introduces the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}), which is the generic function for showing browse table in visual mode.11891190For technical details needed to extend these applications and to build other1191applications, see Chapter{\nobreakspace}\ref{chap:browse-prg}.11921193Examples of browse table applications are shown in Chapter{\nobreakspace}\ref{ch:appl}.1194\section{\textcolor{Chapter }{Features Supported by the Function \texttt{NCurses.BrowseGeneric} }}\label{sec:features}1195\logpage{[ 4, 1, 0 ]}1196\hyperdef{L}{X869EDB308717F199}{}1197{1198Standard applications of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) have the following functionality. Other applications may provide only a1199subset, or add further functionality, see Chapters{\nobreakspace}\ref{chap:browse-prg} and{\nobreakspace}\ref{ch:appl}.120012011202\begin{description}1203\item[{Scrolling:\index{scrolling in a browse table}}] The subranges of shown rows and columns of the main table can be modified,1204such that the focus area is moved to the left, to the right, up, or down;1205depending on the context, the focus is moved by one character, by one table1206cell or a part of it, by the window height/width (minus one character or minus1207one table cell). If mouse events \index{mouse events} are enabled then cells can be selected also via mouse clicks.1208\item[{Selecting:\index{selecting entries of a browse table}}] A cell, row, or column of the main table can be selected; then it is shown1209highlighted on the screen (by default using the attribute \texttt{NCurses.attrs.STANDOUT}, see Section{\nobreakspace}\ref{ssec:ncursesAttrs}). The selection can be moved inside the main table to a neighboring cell,1210row, or column; this causes also scrolling of the main table when the window1211borders are reached.1212\item[{Searching:\index{searching in a browse table}}] A search string is entered by the user, and the first matching cell becomes1213selected; one can search further for the next matching cell. Global search1214parameters define what matching means (case sensitive or not, search for1215substrings or complete words) and what the first and the next matching cells1216are (search in the whole table or just in the selected row or column, search1217for whole words or prefixes or suffixes, search forwards or backwards).1218\item[{Sorting:\index{sorting a browse table}}] If a row or column is selected then the main table can be sorted w.r.t. the1219entries in this row or column. Global sort parameters describe for example1220whether one wants to sort ascending or descending, or case sensitive or not.12211222If a categorized table is sorted by a column then the category rows are1223removed and the current sorting and filtering by rows is reset before the1224table is sorted by the given column. If a table is sorted by a column/row that1225is already sorted by a column/row then this ordering is reset first.12261227Sorting can be undone globally, i.{\nobreakspace}e., one can return to the1228unsorted table.1229\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 entries1230in this column, and additionally these entries are turned into \emph{category rows}, i.{\nobreakspace}e., additional rows are added to the main table, appearing1231immediately above the table rows with a fixed value in the selected column,1232and showing this column value. (There should be no danger to mix up this1233notion of categories with the one introduced in{\nobreakspace} (\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 search1234parameters affect the category rows, for example, whether the category rows1235shall involve a counter showing the number of corresponding data rows, or1236whether a row of the browse table appears under different category rows.12371238Sorting and categorizing can be undone globally, i.{\nobreakspace}e., one can1239return to the unsorted table without category rows.1240\item[{Filtering:\index{filtering a browse table}}] The browse table can be restricted to those rows or columns in which a given1241search string occurs. (Also entries in collapsed rows can match; they remain1242collapsed then.) As a consequence, the category rows are restricted to those1243under which a matching row occurs. (It is irrelevant whether the search string1244occurs in category rows.)12451246If the search string does not occur at all then a message is printed, and the1247table remains as it was before. If a browse table is restricted then this fact1248is indicated by the message ``restricted table'' in the lower right corner of the window.12491250When a column or row is selected then the search is restricted to the entries1251in this column or row, respectively. Besides using a search, one can also1252explicitly hide the selected row or column. Filtering in an already restricted1253table restricts the shown rows or columns further.12541255Filtering can be undone globally, i.{\nobreakspace}e., one can return to the1256unrestricted table.1257\item[{Help:\index{help window for a browse table}}] Depending on the application and on the situation, different sets of user1258inputs may be available and different meanings of these inputs are possible.1259An overview of the currently available inputs and their meanings can be opened1260in each situation, by hitting the \textsc{?} key.1261\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 it1262was left. For example, the cell in the top-left position will be the same as1263before, and if a cell was selected before then this cell will be selected now.1264(One can avoid this behavior using the optional second argument of \texttt{NCurses.BrowseGeneric}.)1265\item[{Logging:\index{log of a browse table session}}] The integers corresponding to the user inputs in visual mode are collected in1266a list that is stored in the component \texttt{dynamic.log} of the browse table. It can be used for repeating the inputs with the replay1267feature. (For browse table applications that give the user no access to the1268browse 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{\nobreakspace}\ref{BrowseData}.)1269\item[{Replay:\index{replay of a browse table session}}] Instead of interactively hitting keys in visual mode, one can prescribe the1270user inputs to a browse table via a ``replay record''; the inputs are then processed with given time intervals. The easiest way to1271create 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 interactive1272session.1273\end{description}127412751276The following features are not available in standard applications. They1277require additional programming.127812791280\begin{description}1281\item[{Clicking:\index{click on an entry of a browse table}}] One possible action is to ``click'' a selected cell, row, or column, by hitting the \textsc{Enter} key. It depends on the application what the effect is. A typical situation is1282that 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 whose1283components are \textsf{GAP} functions, see Section{\nobreakspace}\ref{BrowseData} for details. If mouse events \index{mouse events} are enabled (see \texttt{NCurses.UseMouse} (\ref{NCurses.UseMouse})) then also mouse clicks can be used as an alternative to hitting the \textsc{Enter} key.1284\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 a1285list 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 desired1286value to the component \texttt{dynamic.Return} of the browse table.1287\end{description}1288}128912901291\section{\textcolor{Chapter }{Data Structures used by \texttt{NCurses.BrowseGeneric}}}\label{sec:browsebasicdata}1292\logpage{[ 4, 2, 0 ]}1293\hyperdef{L}{X82689212794DA877}{}1294{129512961297\subsection{\textcolor{Chapter }{BrowseData.IsBrowseTableCellData}}1298\logpage{[ 4, 2, 1 ]}\nobreak1299\hyperdef{L}{X82157A2684969A5F}{}1300{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseData.IsBrowseTableCellData({\mdseries\slshape obj})\index{BrowseData.IsBrowseTableCellData@\texttt{BrowseData.IsBrowseTableCellData}}1301\label{BrowseData.IsBrowseTableCellData}1302}\hfill{\scriptsize (function)}}\\1303\textbf{\indent Returns:\ }1304\texttt{true} if the argument is a list or a record in a supported format.1305130613071308A \emph{table cell data object} describes the input data for the contents of a cell in a browse table. It is1309represented by either an attribute line (see{\nobreakspace}\texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine})), for cells of height one, or a list of attribute lines or a record with the1310components \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 --1311bottom, horizontally centered, left, and top alignment; the default is right1312and vertically centered alignment. (Note that the height of a table row and1313the width of a table column can be larger than the height and width of an1314individual cell.)131513161317\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]1318!gapprompt@gap>| !gapinput@BrowseData.IsBrowseTableCellData( "abc" );|1319true1320!gapprompt@gap>| !gapinput@BrowseData.IsBrowseTableCellData( [ "abc", "def" ] );|1321true1322!gapprompt@gap>| !gapinput@BrowseData.IsBrowseTableCellData( rec( rows:= [ "ab", "cd" ],|1323!gapprompt@>| !gapinput@ align:= "tl" ) );|1324true1325!gapprompt@gap>| !gapinput@BrowseData.IsBrowseTableCellData( "" );|1326true1327!gapprompt@gap>| !gapinput@BrowseData.IsBrowseTableCellData( [] );|1328true1329\end{Verbatim}133013311332The \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} (\textbf{Reference: IsStringRep})) is a table cell data object of height zero and width zero. }1333133413351336\subsection{\textcolor{Chapter }{BrowseData.BlockEntry}}1337\logpage{[ 4, 2, 2 ]}\nobreak1338\hyperdef{L}{X7CA598A77A70C3B3}{}1339{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseData.BlockEntry({\mdseries\slshape tablecelldata, height, width})\index{BrowseData.BlockEntry@\texttt{BrowseData.BlockEntry}}1340\label{BrowseData.BlockEntry}1341}\hfill{\scriptsize (function)}}\\1342\textbf{\indent Returns:\ }1343a list of attribute lines.1344134513461347For a table cell data object \mbox{\texttt{\mdseries\slshape tablecelldata}} (see{\nobreakspace}\texttt{BrowseData.IsBrowseTableCellData} (\ref{BrowseData.IsBrowseTableCellData})) and two positive integers \mbox{\texttt{\mdseries\slshape height}} and \mbox{\texttt{\mdseries\slshape width}}, \texttt{BrowseData.BlockEntry} returns a list of \mbox{\texttt{\mdseries\slshape height}} attribute lines of displayed length \mbox{\texttt{\mdseries\slshape width}} each (see{\nobreakspace}\texttt{NCurses.WidthAttributeLine} (\ref{NCurses.WidthAttributeLine})), that represents the formatted version of \mbox{\texttt{\mdseries\slshape tablecelldata}}.13481349If the rows of \mbox{\texttt{\mdseries\slshape tablecelldata}} have different numbers of displayed characters then they are filled up to the1350desired numbers of rows and columns, according to the alignment prescribed by \mbox{\texttt{\mdseries\slshape tablecelldata}}; the default alignment is right and vertically centered.135113521353\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]1354!gapprompt@gap>| !gapinput@BrowseData.BlockEntry( "abc", 3, 5 );|1355[ " ", " abc", " " ]1356!gapprompt@gap>| !gapinput@BrowseData.BlockEntry( rec( rows:= [ "ab", "cd" ],|1357!gapprompt@>| !gapinput@ align:= "tl" ), 3, 5 );|1358[ "ab ", "cd ", " " ]1359\end{Verbatim}1360}1361136213631364\subsection{\textcolor{Chapter }{BrowseData.IsBrowseTable}}1365\logpage{[ 4, 2, 3 ]}\nobreak1366\hyperdef{L}{X81007E2F8552523B}{}1367{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseData.IsBrowseTable({\mdseries\slshape obj})\index{BrowseData.IsBrowseTable@\texttt{BrowseData.IsBrowseTable}}1368\label{BrowseData.IsBrowseTable}1369}\hfill{\scriptsize (function)}}\\1370\textbf{\indent Returns:\ }1371\texttt{true} if the argument record has the required components and is consistent.1372137313741375A \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}).13761377The 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 user1378interactions, such as the table entries and their heights and widths. The1379components in \texttt{dynamic} describe that part of the data that is intended to change with user1380interactions, such as the currently shown top-left entry of the table, or the1381current 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 same1382status 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) the1383component \texttt{dynamic} if one wants to start in the same status as \emph{before} the first call.13841385The following components are the most important ones for standard browse1386applications. 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{\nobreakspace}\ref{sec:modes}.1387\begin{description}1388\item[{\texttt{main}}] is the list of lists of table cell data objects that form the matrix to be1389shown. There is no default for this component. (It is possible to compute the1390entries of the main table on demand, see the description of the component \texttt{Main} in Section{\nobreakspace}\ref{BrowseData}. In this situation, the value of the component \texttt{main} can be an empty list.)1391\item[{\texttt{header}}] describes a header that shall be shown above the column labels. The value is1392either a list of attribute lines (``static header'') or a function or a record whose component names are names of available modes1393of the browse table (``dynamic header''). In the function case, the function must take the browse table as its only1394argument, and return a list of attribute lines. In the record case, the values1395of the components must be such functions. It is assumed that the number of1396these lines depends at most on the mode. The default is an empty list,1397i.{\nobreakspace}e., there is no header.1398\item[{\texttt{footer}}] describes a footer that shall be shown below the table. The value is analogous1399to that of \texttt{footer}. The default is an empty list, i.{\nobreakspace}e., there is no footer.1400\item[{\texttt{labelsRow}}] is a list of row label rows, each being a list of table cell data objects.1401These rows are shown to the left of the main table. The default is an empty1402list, i.{\nobreakspace}e., there are no row labels.1403\item[{\texttt{labelsCol}}] is a list of column information rows, each being a list of table cell data1404objects. These rows are shown between the header and the main table. The1405default is an empty list, i.{\nobreakspace}e., there are no column labels.1406\item[{\texttt{corner}}] is a list of lists of table cell data objects that are printed in the upper1407left corner, i.{\nobreakspace}e., to the left of the column label rows and1408above the row label columns. The default is an empty list.1409\item[{\texttt{sepRow}}] describes the separators above and below rows of the main table and of the row1410labels table. The value is either an attribute line or a (not necessarily1411dense) list of attribute lines. In the former case, repetitions of the1412attribute line are used as separators below each row and above the first row1413of the table; in the latter case, repetitions of the entry at the first1414position (if bound) are used above the first row, and repetitions of the last1415bound 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 no1416row separators.1417\item[{\texttt{sepCol}}] describes the separators in front of and behind columns of the main table and1418of the column labels table. The format of the value is analogous to that of1419the component \texttt{sepRow}; the default is the string \texttt{" "} (whitespace of width one).1420\item[{\texttt{sepLabelsCol}}] describes the separators above and below rows of the column labels table and1421of the corner table, analogously to \texttt{sepRow}. The default is an empty string, which means that there are no column label1422separators.1423\item[{\texttt{sepLabelsRow}}] describes the separators in front of and behind columns of the row labels1424table and of the corner table, analogously to \texttt{sepCol}. The default is an empty string.1425\end{description}1426We give a few examples of standard applications.14271428The first example defines a small browse table by prescribing only the1429component \texttt{work.main}, so the defaults for row and column labels (no such labels), and for1430separators are used. The table cells are given by plain strings, so they have1431height one. Usually this table will fit on the screen.143214331434\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]1435!gapprompt@gap>| !gapinput@m:= 10;; n:= 5;;|1436!gapprompt@gap>| !gapinput@xpl1:= rec( work:= rec(|1437!gapprompt@>| !gapinput@ main:= List( [ 1 .. m ], i -> List( [ 1 .. n ],|1438!gapprompt@>| !gapinput@ j -> String( [ i, j ] ) ) ) ) );;|1439!gapprompt@gap>| !gapinput@BrowseData.IsBrowseTable( xpl1 );|1440true1441\end{Verbatim}144214431444In the second example, also row and column labels appear, and different1445separators are used. The table cells have height three. Also this table will1446usually fit on the screen.144714481449\begin{Verbatim}[commandchars=!@A,fontsize=\small,frame=single,label=Example]1450!gapprompt@gap>A !gapinput@m:= 6;; n:= 5;;A1451!gapprompt@gap>A !gapinput@xpl2:= rec( work:= rec(A1452!gapprompt@>A !gapinput@ main:= List( [ 1 .. m ], i -> List( [ 1 .. n ],A1453!gapprompt@>A !gapinput@ j -> rec( rows:= List( [ -i*j, i*j*1000+j, i-j ], String ),A1454!gapprompt@>A !gapinput@ align:= "c" ) ) ),A1455!gapprompt@>A !gapinput@ labelsRow:= List( [ 1 .. m ], i -> [ String( i ) ] ),A1456!gapprompt@>A !gapinput@ labelsCol:= [ List( [ 1 .. n ], String ) ],A1457!gapprompt@>A !gapinput@ sepRow:= "-",A1458!gapprompt@>A !gapinput@ sepCol:= "|",A1459!gapprompt@>A !gapinput@ ) );;A1460!gapprompt@gap>A !gapinput@BrowseData.IsBrowseTable( xpl2 );A1461true1462\end{Verbatim}146314641465The third example additionally has a static header and a dynamic footer, and1466the table cells involve attributes. This table will usually not fit on the1467screen. Note that \texttt{NCurses.attrs.ColorPairs} is available only if the terminal supports colors, which can be checked using \texttt{NCurses.attrs.has{\textunderscore}colors} (\ref{NCurses.attrs.hascolors}).146814691470\begin{Verbatim}[commandchars=!@F,fontsize=\small,frame=single,label=Example]1471!gapprompt@gap>F !gapinput@m:= 30;; n:= 25;;F1472!gapprompt@gap>F !gapinput@xpl3:= rec( work:= rec(F1473!gapprompt@>F !gapinput@ header:= [ " Example 3" ],F1474!gapprompt@>F !gapinput@ labelsRow:= List( [ 1 .. 30 ], i -> [ String( i ) ] ),F1475!gapprompt@>F !gapinput@ sepLabelsRow:= " % ",F1476!gapprompt@>F !gapinput@ sepLabelsCol:= "=",F1477!gapprompt@>F !gapinput@ sepRow:= "*",F1478!gapprompt@>F !gapinput@ sepCol:= " |",F1479!gapprompt@>F !gapinput@ footer:= t -> [ Concatenation( "top-left entry is: ",F1480!gapprompt@>F !gapinput@ String( t.dynamic.topleft{ [ 1, 2] } ) ) ],F1481!gapprompt@>F !gapinput@ ) );;F1482!gapprompt@gap>F !gapinput@if NCurses.attrs.has_colors thenF1483!gapprompt@>F !gapinput@ xpl3.work.main:= List( [ 1 .. m ], i -> List( [ 1 .. n ],F1484!gapprompt@>F !gapinput@ j -> rec( rows:= [ String( -i*j ),F1485!gapprompt@>F !gapinput@ [ NCurses.attrs.BOLD, true,F1486!gapprompt@>F !gapinput@ NCurses.attrs.ColorPairs[56+1], true,F1487!gapprompt@>F !gapinput@ String( i*j*1000+j ),F1488!gapprompt@>F !gapinput@ NCurses.attrs.NORMAL, true ],F1489!gapprompt@>F !gapinput@ String( i-j ) ],F1490!gapprompt@>F !gapinput@ align:= "c" ) ) );F1491!gapprompt@>F !gapinput@ xpl3.work.labelsCol:= [ List( [ 1 .. 30 ], i -> [F1492!gapprompt@>F !gapinput@ NCurses.attrs.ColorPairs[ 56+4 ], true,F1493!gapprompt@>F !gapinput@ String( i ),F1494!gapprompt@>F !gapinput@ NCurses.attrs.NORMAL, true ] ) ];F1495!gapprompt@>F !gapinput@elseF1496!gapprompt@>F !gapinput@ xpl3.work.main:= List( [ 1 .. m ], i -> List( [ 1 .. n ],F1497!gapprompt@>F !gapinput@ j -> rec( rows:= [ String( -i*j ),F1498!gapprompt@>F !gapinput@ [ NCurses.attrs.BOLD, true,F1499!gapprompt@>F !gapinput@ String( i*j*1000+j ),F1500!gapprompt@>F !gapinput@ NCurses.attrs.NORMAL, true ],F1501!gapprompt@>F !gapinput@ String( i-j ) ],F1502!gapprompt@>F !gapinput@ align:= "c" ) ) );F1503!gapprompt@>F !gapinput@ xpl3.work.labelsCol:= [ List( [ 1 .. 30 ], i -> [F1504!gapprompt@>F !gapinput@ NCurses.attrs.BOLD, true,F1505!gapprompt@>F !gapinput@ String( i ),F1506!gapprompt@>F !gapinput@ NCurses.attrs.NORMAL, true ] ) ];F1507!gapprompt@>F !gapinput@fi;F1508!gapprompt@gap>F !gapinput@BrowseData.IsBrowseTable( xpl3 );F1509true1510\end{Verbatim}151115121513The fourth example illustrates that highlighting may not work properly for1514browse tables containing entries whose attributes are not set with explicit1515Boolean values, see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine}). Call \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) with the browse table \texttt{xpl4}, and select an entry (or a column or a row): Only the middle row of each1516selected cell will be highlighted, because only in this row, the color1517attribute is switched on with an explicit \texttt{true}.151815191520\begin{Verbatim}[commandchars=@FG,fontsize=\small,frame=single,label=Example]1521@gappromptFgap>G @gapinputFxpl4:= rec(G1522@gappromptF>G @gapinputF defc:= NCurses.defaultColors,G1523@gappromptF>G @gapinputF wd:= Maximum( List( ~.defc, Length ) ),G1524@gappromptF>G @gapinputF ca:= NCurses.ColorAttr,G1525@gappromptF>G @gapinputF work:= rec(G1526@gappromptF>G @gapinputF header:= [ "Examples of NCurses.ColorAttr" ],G1527@gappromptF>G @gapinputF main:= List( ~.defc, i -> List( ~.defc,G1528@gappromptF>G @gapinputF j -> [ [ ~.ca( i, j ), String( i, ~.wd ) ], # no true!G1529@gappromptF>G @gapinputF [ ~.ca( i, j ), true, String( "on", ~.wd ) ],G1530@gappromptF>G @gapinputF [ ~.ca( i, j ), String( j, ~.wd ) ] ] ) ), # no true!G1531@gappromptF>G @gapinputF labelsRow:= List( ~.defc, i -> [ String( i ) ] ),G1532@gappromptF>G @gapinputF labelsCol:= [ List( ~.defc, String ) ],G1533@gappromptF>G @gapinputF sepRow:= "-",G1534@gappromptF>G @gapinputF sepCol:= [ " |", "|" ],G1535@gappromptF>G @gapinputF ) );;G1536@gappromptFgap>G @gapinputFBrowseData.IsBrowseTable( xpl4 );G1537true1538\end{Verbatim}1539}15401541}154215431544\section{\textcolor{Chapter }{The Function \texttt{NCurses.BrowseGeneric}}}\label{sec:browsegeneric}1545\logpage{[ 4, 3, 0 ]}1546\hyperdef{L}{X8135D3C2806D8F92}{}1547{154815491550\subsection{\textcolor{Chapter }{NCurses.BrowseGeneric}}1551\logpage{[ 4, 3, 1 ]}\nobreak1552\hyperdef{L}{X85FC163D87FAFD12}{}1553{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.BrowseGeneric({\mdseries\slshape t[, arec]})\index{NCurses.BrowseGeneric@\texttt{NCurses.BrowseGeneric}}1554\label{NCurses.BrowseGeneric}1555}\hfill{\scriptsize (function)}}\\1556\textbf{\indent Returns:\ }1557an application dependent value, or nothing.1558155915601561\texttt{NCurses.BrowseGeneric} is used to show the browse table \mbox{\texttt{\mdseries\slshape t}} (see{\nobreakspace}\texttt{BrowseData.IsBrowseTable} (\ref{BrowseData.IsBrowseTable})) in a formatted way on a text screen, and allows the user to navigate in this1562table.15631564The optional argument \mbox{\texttt{\mdseries\slshape 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 the1565corresponding components of \mbox{\texttt{\mdseries\slshape t}}. The default for \mbox{\texttt{\mdseries\slshape arec}} and for the components not provided in \mbox{\texttt{\mdseries\slshape arec}} is \texttt{BrowseData.defaults}, see{\nobreakspace}\texttt{BrowseData} (\ref{BrowseData}), the function \texttt{BrowseData.SetDefaults} sets these default values.15661567At least the component \texttt{work.main} must be bound in \mbox{\texttt{\mdseries\slshape t}}, with value a list of list of table cell data objects, see{\nobreakspace}\texttt{BrowseData.IsBrowseTableCellData} (\ref{BrowseData.IsBrowseTableCellData}).15681569When the window or the screen is too small for the browse table, according to1570its 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 in1571a 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.15721573Most likely, \texttt{NCurses.BrowseGeneric} will not be called on the command line, but the browse table \mbox{\texttt{\mdseries\slshape t}} will be composed by a suitable function which then calls \texttt{NCurses.BrowseGeneric}, see the examples in Chapter{\nobreakspace}\ref{ch:appl}. }15741575}15761577}157815791580\chapter{\textcolor{Chapter }{Browsing Tables in \textsf{GAP} using \texttt{ncurses} {\textendash}The Programming Interface}}\label{chap:browse-prg}1581\logpage{[ 5, 0, 0 ]}1582\hyperdef{L}{X82DDDC1783B4CA30}{}1583{1584This chapter describes some aspects of the internals of the browse table1585handling. The relevant objects are \emph{action functions} that implement the individual navigation steps (see Section{\nobreakspace}\ref{sec:actions}), \emph{modes} that describe the sets of available navigation steps in given situations (see1586Section{\nobreakspace}\ref{sec:modes}), and \emph{browse applications} that are given by the combination of several modes (see Section{\nobreakspace}\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.1587\section{\textcolor{Chapter }{Navigation Steps in Browse Tables}}\label{sec:actions}1588\logpage{[ 5, 1, 0 ]}1589\hyperdef{L}{X853E01C778A73ECB}{}1590{1591Navigating 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, or uses a mouse button, and if this input1592is in a given set of admissible inputs then a corresponding function is1593executed with argument the browse table (plus additional information in the1594case of mouse events). The function call then may change components in this1595table (recommended: components in its \texttt{dynamic} component), such that the appearance in the window may be different1596afterwards, and also the admissible inputs and their effects may have changed.15971598The relation between the admissible inputs and the corresponding functions is1599application dependent. However, it is recommended to associate the same input1600to 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 a1601global variable (see Section \ref{BrowseData.actions.SaveWindow}), and the \textsc{E} key should belong to a function that enters a break loop (see1602Section{\nobreakspace}\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 should1603expand/collapse this category. The \textsc{M} key should toggle enabling and disabling mouse events. Mouse events on a cell1604or on a category row of a browse table should move the selected entry to this1605position; it is recommended that no functionality is lost if no mouse events1606are used, although the number of steps might be reduced when the mouse is1607used.16081609Each 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}.16101611The action functions need not return anything. Whenever the shown screen shall1612be recomputed after the function call, the component \texttt{dynamic.changed} of the browse table must be set to \texttt{true} by the action functions.16131614After entering the first characters of an admissible input that consists of1615more characters, the last line of the window with the browse table shows these1616characters behind the prefix ``partial input:''. \index{partial input in a browse table} One can delete the last entered character of a partial input via the \textsc{Delete} and \textsc{Backspace} keys. It is not possible to make these keys part of an admissible input. When1617a partial input is given, only those user inputs have an effect that extend1618the partial input to (a prefix of) an admissible input. For example, asking1619for help by hitting the \textsc{?} key will in general not work if a partial input had been entered before. }162016211622\section{\textcolor{Chapter }{Modes in Browse Tables}}\label{sec:modes}1623\logpage{[ 5, 2, 0 ]}1624\hyperdef{L}{X83290BB6864B2DD0}{}1625{1626\index{mode of a browse table} In different situations, different inputs may be admissible for the same1627browse table, and different functions may belong to the same input. For1628example, the meaning of ``moving down'' can be different depending on whether a cell is selected or not.16291630The set of admissible user inputs and corresponding functions for a particular1631situation is collected in a \emph{mode} of the browse table. (There should be no danger to mix up this notion of mode1632with the ``visual mode'' introduced in Section{\nobreakspace}\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 for1633different modes), \texttt{actions} (a list of records describing the navigation steps that are admissible in the1634mode, see Section{\nobreakspace}\ref{sec:actions}), and \texttt{ShowTables} (the function used to eventually print the current window contents, the1635default is \texttt{BrowseData.ShowTables}). \index{BrowseData.ShowTables} Due to the requirement that each admissible user input uniquely determines a1636corresponding function, no admissible user input can be a prefix of another1637admissible input, for the same mode.16381639Navigation steps (see Section \ref{sec:actions}) can change the current mode or keep the mode. It is recommended that each1640mode has an action to leave this mode; also an action to leave the browse1641table application is advisable.16421643In 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 by1644unbinding the last entry (so one returns to the mode from which the current1645mode had been entered by adding it to the list), by adding a new mode record1646(so one can later return to the current mode), or by replacing the last entry1647by another mode record. As soon as the \texttt{dynamic.activeModes} list becomes empty, the browse table application is left. (In this situation,1648if the browse table had been entered from the \textsf{GAP} prompt then visual mode is left, and one returns to the \textsf{GAP} prompt.)16491650The 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}, \textsc{E}, and \textsc{M} that have been mentioned in Section \ref{sec:actions}.1651\begin{description}1652\item[{browse}] This mode admits scrolling of the browse table by a cell or by a screen,1653searching for a string, selecting a row, a column, or an entry, and expanding1654or collapsing all category rows.1655\item[{help}] This mode is entered by calling \texttt{BrowseData.ShowHelpTable}; it shows a help window concerning the actions available in the mode from1656which 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.1657\item[{select{\textunderscore}entry}] In this mode, one table cell is regarded as selected; this cell is highlighted1658using 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,1659searching for a string and for further occurrences of this string, expanding1660or 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.1661\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 is1662restricted to the selected row, and ``click'' refers to the function \texttt{work.Click.( "select{\textunderscore}row" )}.1663\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.1664\item[{select{\textunderscore}column}] This is like the \texttt{select{\textunderscore}row} mode, just a column is selected not a row.1665\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.1666\end{description}1667}166816691670\section{\textcolor{Chapter }{Browse Applications}}\label{sec:applications}1671\logpage{[ 5, 3, 0 ]}1672\hyperdef{L}{X7A4014DB84D16406}{}1673{1674The data in a browse table together with the set of its available modes and1675the stack of active modes forms a browse application. So the part of or all1676functionality of the \textsf{Browse} package can be available (``standard application''), or additional functionality can be provided by extending available modes or1677adding new modes.16781679When \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) has been called with the browse table \mbox{\texttt{\mdseries\slshape t}}, say, the following loop is executed.1680\begin{enumerate}1681\item If the list \mbox{\texttt{\mdseries\slshape t}}\texttt{.dynamic.activeModes} is empty then exit the browse table, and if the component \mbox{\texttt{\mdseries\slshape t}}\texttt{.dynamic.Return} is bound then return its value. Otherwise proceed with step 2.1682\item If \mbox{\texttt{\mdseries\slshape 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 shows1683the browse table. Then go to step 3.1684\item Get one character of user input. If then the current user input string is the1685name of an action of the current mode then call the corresponding action1686function and go to step 1; if the current user input string is just a prefix1687of the name of some actions of the current mode then go to step 3; if the1688current user input string is not a prefix of any name of an action of the1689current mode then discard the last read character and go to step 3.1690\end{enumerate}1691When one designs a new application, it may be not obvious whether some1692functionality shall be implemented via one mode or via several modes. As a1693rule of thumb, introducing a new mode is recommended when one needs a new set1694of admissible actions in a given situation, and also if one wants to allow the1695user to perform some actions and then to return to the previous status. }169616971698\section{\textcolor{Chapter }{Predefined Browse Functionalities}}\label{sec:browse-avail}1699\logpage{[ 5, 4, 0 ]}1700\hyperdef{L}{X831DD0D58052AD57}{}1701{170217031704\subsection{\textcolor{Chapter }{BrowseData}}1705\logpage{[ 5, 4, 1 ]}\nobreak1706\hyperdef{L}{X86E80E578085F137}{}1707{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseData\index{BrowseData@\texttt{BrowseData}}1708\label{BrowseData}1709}\hfill{\scriptsize (global variable)}}\\171017111712This 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.17131714\texttt{BrowseData.actions} is a record containing the action records that are provided by the package,1715see Section{\nobreakspace}\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}.17161717\texttt{BrowseData.defaults} is a record that contains the defaults for the browse table used as the first1718argument of \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}). Important components have been described above, see{\nobreakspace}\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.17191720The following components are provided in \texttt{BrowseData.defaults.work}.172117221723\begin{description}1724\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.{\nobreakspace}e., the window for the browse table is the full screen.1725\item[{\texttt{minyx}}] is a list of length two, the entries must be either nonnegative integers,1726denoting the minimal number of rows and columns that are required by the1727browse table, or unary functions that return these values when they are1728applied to the browse table; this is interesting for applications that do not1729support scrolling, or for applications that may have large row or column1730labels tables. The default is a list with two functions, the return value of1731the first function is the sum of the heights of the table header, the column1732labels table, the first table row, and the table footer, and the return value1733of the second function is the sum of widths of the row labels table and the1734width of the first column. (If the header/footer is given by a function then1735this part of the table is ignored in the \texttt{minyx} default.) Note that the conditions are checked only when \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is called, not after later changes of the screen size in a running browse1736table application.1737\item[{\texttt{align}}] is a substring of \texttt{"bclt"}, which describes the alignment of the browse table in the window. The meaning1738and 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.)1739\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 names1740of modes and the corresponding components are nonnegative integers. This1741component is ignored if the \texttt{header} component is unbound or bound to a list, missing values are computed by calls1742to the corresponding \texttt{header} function as soon as they are needed.1743\item[{\texttt{footerLength}}] corresponds to \texttt{footer} in the same way as \texttt{headerLength} to \texttt{header}.1744\item[{\texttt{Main}}] if bound to a function then this function can be used to compute missing1745values 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 is1746defined 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 version1747of \texttt{work.emptyCell}. (For the condition whether entries in \texttt{mainFormatted} can be bound, see below in the description of the component \texttt{cacheEntries}.)1748\item[{\texttt{cacheEntries}}] describes whether formatted values of the entries in the matrices given by the1749components \texttt{corner}, \texttt{labelsCol}, \texttt{labelsRow}, \texttt{main}, and of the corresponding row and column separators shall be stored in the1750components \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.1751\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 lines1752(with the same number of displayed characters), the values can be computed1753from the input format with \texttt{BrowseData.FormattedEntry}. \index{BrowseData.FormattedEntry@\texttt{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.1754\item[{\texttt{labelsColFormatted}}] corresponds to \texttt{labelsCol} in the same way as \texttt{cornerFormatted} to \texttt{corner}.1755\item[{\texttt{labelsRowFormatted}}] corresponds to \texttt{labelsRow} in the same way as \texttt{cornerFormatted} to \texttt{corner}.1756\item[{\texttt{mainFormatted}}] corresponds to \texttt{main} in the same way as \texttt{cornerFormatted} to \texttt{corner}.1757\item[{\texttt{m0}}] is the maximal number of rows in the column labels table. If this value is not1758bound then it is computed from the components \texttt{corner} and \texttt{labelsCol}.1759\item[{\texttt{n0}}] is the maximal number of columns in \texttt{corner} and \texttt{labelsRow}.1760\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}.1761\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}.1762\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,1763with the function \texttt{BrowseData.HeightLabelsCol}. \index{BrowseData.HeightLabelsCol@\texttt{BrowseData.HeightLabelsCol}} (So if one knows the needed heights in advance, it is advisable to set the1764values, in order to avoid that formatted table entries are computed just for1765computing their size.) The default is an empty list.1766\item[{\texttt{widthLabelsRow}}] is the corresponding list of $2$ \texttt{n0}$ + 1$ maximal widths of entries in \texttt{cornerFormatted} and \texttt{labelsRowFormatted}.1767\item[{\texttt{heightRow}}] is the corresponding list of $2$ \texttt{m}$ + 1$ maximal heights of entries in \texttt{labelsRowFormatted} and \texttt{mainFormatted}.1768\item[{\texttt{widthCol}}] is the corresponding list of $2$ \texttt{n}$ + 1$ maximal widths of entries in \texttt{labelsColFormatted} and \texttt{mainFormatted}.1769\item[{\texttt{emptyCell}}] is a table cell data object to be used as the default for unbound positions in1770the four matrices. The default is the empty list.1771\item[{\texttt{sepCategories}}] is an attribute line to be used repeatedly as a separator below expanded1772category rows. The default is the string \texttt{"-"}.1773\item[{\texttt{startCollapsedCategory}}] is a list of attribute lines to be used as prefixes of unhidden but collapsed1774category rows. For category rows 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 the1775boldface variant of the string \texttt{"{\textgreater} "}, so collapsed category rows on different levels are treated equally.1776\item[{\texttt{startExpandedCategory}}] is a list of attribute lines to be used as prefixes of expanded category rows,1777analogously to \texttt{startCollapsedCategory}. The default is a list of length one, the entry is the boldface variant of1778the string \texttt{"* "}, so expanded category rows on different levels are treated equally.1779\item[{\texttt{startSelect}}] is an attribute line to be used as a prefix of each attribute line that1780belongs to a selected cell. The default is to switch the attribute \texttt{NCurses.attrs.STANDOUT} on, see Section{\nobreakspace}\ref{ssec:ncursesAttrs}.1781\item[{\texttt{Click}}] is a record whose component names are names of available modes of the browse1782table. The values are unary functions that take the browse table as their1783argument. If the action \texttt{Click} is available in the current mode and the corresponding input is entered then1784the function in the relevant component of the \texttt{Click} record is called.1785\item[{\texttt{availableModes}}] is a list whose entries are the mode records that can be used when one1786navigates through the browse table, see Section \ref{sec:modes}.1787\item[{\texttt{SpecialGrid}}] is a function that takes a browse table and a record as its arguments. It is1788called by \texttt{BrowseData.ShowTables} after the current contents of the window has been computed, and it is intended1789to draw an individual grid into the table that fits better than anything that1790can be specified in terms of row and column separators. (If other functions1791than \texttt{BrowseData.ShowTables} are used in some modes of the browse table, these functions must deal with1792this aspect themselves.) The default is to do nothing.1793\end{description}1794The following components are provided in \texttt{BrowseData.defaults.dynamic}.1795\begin{description}1796\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 is1797automatically reset to \texttt{false} after the refresh.1798\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, the1799rows 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 is1800assumed (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).1801\item[{\texttt{indexCol}}] is the analogous list of positive integers that refers to columns.1802\item[{\texttt{topleft}}] is a list of four positive integers denoting the current topleft position of1803the 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 ]$.1804\item[{\texttt{isCollapsedRow}}] 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 because it belongs to a collapsed category row.1805It is assumed (as a ``hide convention'') \index{hide convention} that the value at any even position equals the value at the subsequent odd1806position. The default is that all entries are \texttt{false}.1807\item[{\texttt{isCollapsedCol}}] is the corresponding list for \texttt{indexCol}.1808\item[{\texttt{isRejectedRow}}] is a list of Booleans. If the entry at position $i$ is \texttt{true} then the $i$-th row is currently not shown because it does not match the current filtering1809of the table. Defaults, length, and hide convention are as for \texttt{isCollapsedRow}.1810\item[{\texttt{isRejectedCol}}] is the corresponding list for \texttt{indexCol}.1811\item[{\texttt{isRejectedLabelsRow}}] is a list of Booleans. If the entry at position $i$ is \texttt{true} then the $i$-th column of row labels is currently not shown.1812\item[{\texttt{isRejectedLabelsCol}}] is the corresponding list for the column labels.1813\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 this1814list. The default depends on the application, \texttt{BrowseData.defaults} prescribes the list containing only the mode with \texttt{name} component \texttt{"browse"}.1815\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 ]$.1816\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 ]$.1817\item[{\texttt{searchString}}] is the last string for which the user has searched in the table. The default1818is the empty string.1819\item[{\texttt{searchParameters}}] is a list of parameters that are modified by the function \texttt{BrowseData.SearchStringWithStartParameters}. \index{SearchStringWithStartParameters@\texttt{SearchStringWithStartParameters}} If one sets these parameters in a search then these values hold also for1820subsequent searches. So it may make sense to set the parameters to personally1821preferred ones.1822\item[{\texttt{sortFunctionForColumnsDefault}}] is a function with two arguments used to compare two entries in the same1823column of the main table (or two category row values). The default is the1824operation \texttt{\texttt{\symbol{92}}{\textless}}. (Note that this default may be not meaningful if some of the rows or columns1825contain strings representing numbers.)1826\item[{\texttt{sortFunctionForRowsDefault}}] is the analogous function for comparing two entries in the same row of the1827main table.1828\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.1829\item[{\texttt{sortFunctionsForColumns}}] is the analogous list of functions for the case that the table is sorted1830w.r.t. columns.1831\item[{\texttt{sortParametersForRowsDefault}}] is a list of parameters for sorting the main table w.r.t. entries in given1832rows, e.{\nobreakspace}g., whether one wants to sort ascending or descending.1833\item[{\texttt{sortParametersForColumnsDefault}}] is the analogous list of parameters for sorting w.r.t. given columns. In1834addition to the parameters for rows, also parameters concerning category rows1835are available, e.{\nobreakspace}g., whether the data columns that are1836transformed into category rows shall be hidden afterwards or not.1837\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.1838\item[{\texttt{sortParametersForColumns}}] is the analogous list of parameters lists for sorting w.r.t. columns.1839\item[{\texttt{categories}}] describes the current category rows. The value is a list $[ l_1, l_2, l_3 ]$ where $l_1$ is a \emph{sorted} list $[ i_1, i_2, ..., i_k ]$ of positive integers, $l_2$ is a list of length $k$ where the $j$-th entry is a record with the components \texttt{pos} (with value $i_j$), \texttt{level} (the level of the category row), \texttt{value} (an attribute line to be shown), \texttt{separator} (the separator below this category row is a repetition of this string), \texttt{isUnderCollapsedCategory} (\texttt{true} if the category row is hidden because a category row of an outer level is1840collapsed; note that in the \texttt{false} case, the category row itself can be collapsed), \texttt{isRejectedCategory} (\texttt{true} if the category row is hidden because none of th edata rows below this1841category match the current filtering of the table); the list $l_3$ contains the levels for which the category rows shall include the numbers of1842data rows under these category rows. 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 category1843rows on higher levels and the corresponding data rows are hidden1844{\textendash}but this property is \emph{not} checked.) Category rows are computed with the \texttt{CategoryValues} function in the \texttt{work} component of the browse table.1845\item[{\texttt{log}}] describes the session log which is currently written. The value is a list of1846positive 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 as1847the value of its component \texttt{dynamic.log}.18481849If \texttt{BrowseData.logStore} \index{BrowseData.logStore@\texttt{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@\texttt{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 table1850applications where the user does not get access to the browse table itself.)1851\item[{\texttt{replay}}] describes the non-interactive input for the current browse table. The value is1852a 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 its1853non-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, the1854default 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 is1855reached, the default is \texttt{false}).1856\end{description}1857}1858185918601861\subsection{\textcolor{Chapter }{BrowseData.SetReplay}}1862\logpage{[ 5, 4, 2 ]}\nobreak1863\hyperdef{L}{X791FB5BA7A9951F4}{}1864{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseData.SetReplay({\mdseries\slshape data})\index{BrowseData.SetReplay@\texttt{BrowseData.SetReplay}}1865\label{BrowseData.SetReplay}1866}\hfill{\scriptsize (function)}}\\186718681869This function sets and resets the value of \texttt{BrowseData.defaults.dynamic.replay}.18701871When \texttt{BrowseData.SetReplay} is called with a list \mbox{\texttt{\mdseries\slshape data}} as its argument then the entries are assumed to describe user inputs for a1872browse table for which \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) will be called afterwards, such that replay of the inputs runs. (Valid input1873lists can be obtained from the component \texttt{dynamic.log} of the browse table in question.)18741875When \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} (\ref{NCurses.BrowseGeneric}) will require interactive user input).18761877The replay feature should be used by initially setting the input list, then1878running the replay (perhaps several times), and finally unbinding the inputs,1879such that subsequent uses of other browse tables do not erroneously expect1880their input in \texttt{BrowseData.defaults.dynamic.replay}.18811882Note that the value of \texttt{BrowseData.defaults.dynamic.replay} is used in a call to \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) only if the browse table in question does not have a component \texttt{dynamic.replay} before the call. }1883188418851886\subsection{\textcolor{Chapter }{BrowseData.AlertWithReplay}}1887\logpage{[ 5, 4, 3 ]}\nobreak1888\hyperdef{L}{X7DAB32B785E59350}{}1889{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseData.AlertWithReplay({\mdseries\slshape t, messages[, attrs]})\index{BrowseData.AlertWithReplay@\texttt{BrowseData.AlertWithReplay}}1890\label{BrowseData.AlertWithReplay}1891}\hfill{\scriptsize (function)}}\\1892\textbf{\indent Returns:\ }1893an integer representing a (simulated) user input.1894189518961897The 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{\mdseries\slshape t}}, see Section \ref{sec:features}. The arguments \mbox{\texttt{\mdseries\slshape messages}} and \mbox{\texttt{\mdseries\slshape attrs}} are the same as the corresponding arguments of \texttt{NCurses.Alert} (\ref{NCurses.Alert}), the argument \texttt{timeout} of \texttt{NCurses.Alert} (\ref{NCurses.Alert}) is taken from the browse table \mbox{\texttt{\mdseries\slshape t}}, as follows. If \texttt{BrowseData.IsDoneReplay} \index{BrowseData.IsDoneReplay@\texttt{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 the1898requested input character is fetched from \texttt{t.dynamic.replay}.18991900If \texttt{timeout} is zero and mouse events are enabled (see \texttt{NCurses.UseMouse} (\ref{NCurses.UseMouse}))\index{mouse events} then the box can be moved inside the window via mouse events.19011902No alert box is shown if \texttt{BrowseData.IsQuietSession} \index{BrowseData.IsQuietSession@\texttt{BrowseData.IsQuietSession}} returns \texttt{true} when called with \mbox{\texttt{\mdseries\slshape t}}\texttt{.dynamic.replay}, otherwise the alert box is closed after the time (in milliseconds) that is1903given by the \texttt{replayInterval} value of the current entry in \mbox{\texttt{\mdseries\slshape t}}\texttt{.dynamic.replay.logs}.19041905The function returns either the return value of the call to \texttt{NCurses.Alert} (\ref{NCurses.Alert}) (in the interactive case) or the value that was fetched from the current1906replay record (in the replay case). }1907190819091910\subsection{\textcolor{Chapter }{BrowseData.actions.ShowHelp}}1911\logpage{[ 5, 4, 4 ]}\nobreak1912\hyperdef{L}{X82A4238B79F06271}{}1913{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseData.actions.ShowHelp\index{BrowseData.actions.ShowHelp@\texttt{BrowseData.actions.ShowHelp}}1914\label{BrowseData.actions.ShowHelp}1915}\hfill{\scriptsize (global variable)}}\\191619171918There are two predefined ways for showing an overview of the admissible inputs1919and their meaning in the current mode of a browse table. The function \texttt{BrowseData.ShowHelpTable} \index{BrowseData.ShowHelpTable@\texttt{BrowseData.ShowHelpTable}} displays this overview in a browse table (using the \texttt{help} mode), and \texttt{BrowseData.ShowHelpPager} \index{BrowseData.ShowHelpPager@\texttt{BrowseData.ShowHelpPager}} uses \texttt{NCurses.Pager}.19201921Technically, the only difference between these two functions is that \texttt{BrowseData.ShowHelpTable} supports the replay feature of \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}), whereas \texttt{BrowseData.ShowHelpPager} simply does not call the pager in replay situations.19221923The action record \texttt{BrowseData.actions.ShowHelp} is associated with the user inputs \textsc{?} or \textsc{F1} in standard \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) applications, and it is recommended to do the same in other \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) applications. This action calls the function stored in the component \texttt{work.ShowHelp} of the browse table, the default (i.{\nobreakspace}e., the value of \texttt{BrowseData.defaults.work.ShowHelp}) is \texttt{BrowseData.ShowHelpTable}.192419251926\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]1927!gapprompt@gap>| !gapinput@xpl1.work.ShowHelp:= BrowseData.ShowHelpPager;;|1928!gapprompt@gap>| !gapinput@BrowseData.SetReplay( "?Q" );|1929!gapprompt@gap>| !gapinput@Unbind( xpl1.dynamic );|1930!gapprompt@gap>| !gapinput@NCurses.BrowseGeneric( xpl1 );|1931!gapprompt@gap>| !gapinput@xpl1.work.ShowHelp:= BrowseData.ShowHelpTable;;|1932!gapprompt@gap>| !gapinput@BrowseData.SetReplay( "?dQQ" );|1933!gapprompt@gap>| !gapinput@Unbind( xpl1.dynamic );|1934!gapprompt@gap>| !gapinput@NCurses.BrowseGeneric( xpl1 );|1935!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|1936!gapprompt@gap>| !gapinput@Unbind( xpl1.dynamic );|1937\end{Verbatim}1938}1939194019411942\subsection{\textcolor{Chapter }{BrowseData.actions.SaveWindow}}1943\logpage{[ 5, 4, 5 ]}\nobreak1944\hyperdef{L}{X872AE7387885B0AD}{}1945{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseData.actions.SaveWindow\index{BrowseData.actions.SaveWindow@\texttt{BrowseData.actions.SaveWindow}}1946\label{BrowseData.actions.SaveWindow}1947}\hfill{\scriptsize (global variable)}}\\194819491950The 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 yet1951then the current contents of the window of the browse table that is given as1952the argument is saved in this variable, using \texttt{NCurses.SaveWin} (\ref{NCurses.SaveWin}). }1953195419551956\subsection{\textcolor{Chapter }{BrowseData.actions.QuitMode}}1957\logpage{[ 5, 4, 6 ]}\nobreak1958\hyperdef{L}{X860DA4007E23716E}{}1959{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseData.actions.QuitMode\index{BrowseData.actions.QuitMode@\texttt{BrowseData.actions.QuitMode}}1960\label{BrowseData.actions.QuitMode}1961}\hfill{\scriptsize (global variable)}}\\1962\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseData.actions.QuitTable\index{BrowseData.actions.QuitTable@\texttt{BrowseData.actions.QuitTable}}1963\label{BrowseData.actions.QuitTable}1964}\hfill{\scriptsize (global variable)}}\\196519661967The function \texttt{BrowseData.actions.QuitMode.action} unbinds the current mode in the browse table that is given as its argument1968(see Section \ref{sec:modes}), so the browse table returns to the mode from which this mode had been1969called. If the current mode is the only one, first the user is asked for1970confirmation whether she really wants to quit the table; only if the \textsc{y} key is hit, the last mode is unbound.19711972The function \texttt{BrowseData.actions.QuitTable.action} unbinds all modes in the browse table that is given as its argument, without1973asking for confirmation; the effect is to exit the browse application (see1974Section \ref{sec:applications}). }1975197619771978\subsection{\textcolor{Chapter }{BrowseData.actions.Error}}1979\logpage{[ 5, 4, 7 ]}\nobreak1980\hyperdef{L}{X8728E4B6856EAEC0}{}1981{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseData.actions.Error\index{BrowseData.actions.Error@\texttt{BrowseData.actions.Error}}1982\label{BrowseData.actions.Error}1983}\hfill{\scriptsize (global variable)}}\\198419851986After \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} (\ref{NCurses.BrowseGeneric}) application, which enters a break loop and admits returning to the1987application. The recommended user input for this action is the \textsc{E} key. }19881989}19901991}199219931994\chapter{\textcolor{Chapter }{Examples of Applications based on \texttt{NCurses.BrowseGeneric} }}\label{ch:appl}1995\logpage{[ 6, 0, 0 ]}1996\hyperdef{L}{X78D4F8EA79405AF9}{}1997{1998This 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;1999more details can be found in the \textsf{GAP} files, in the \texttt{app} directory of the package.20002001Only 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 table2002entries. The other examples in this chapter require some of the programming2003described in Chapter \ref{chap:browse-prg}.20042005The \textsf{GAP} examples in this chapter use the ``replay'' feature of \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}), see Section \ref{sec:features}. This means that the \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) based function is called between two calls of \texttt{BrowseData.SetReplay} (\ref{BrowseData.SetReplay}). If you want to paste these examples into the \textsf{GAP} session with the mouse then do not paste the final \texttt{BrowseData.SetReplay} (\ref{BrowseData.SetReplay}) call, since \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) would regard the additional input as a user interrupt.2006\section{\textcolor{Chapter }{The Operation \texttt{Browse}}}\label{sec:browseoper}2007\logpage{[ 6, 1, 0 ]}2008\hyperdef{L}{X813F90F7815AB5B3}{}2009{201020112012\subsection{\textcolor{Chapter }{Browse}}2013\logpage{[ 6, 1, 1 ]}\nobreak2014\hyperdef{L}{X7FDD696B7DD54A6E}{}2015{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Browse({\mdseries\slshape obj[, arec]})\index{Browse@\texttt{Browse}}2016\label{Browse}2017}\hfill{\scriptsize (operation)}}\\201820192020This operation displays the \textsf{GAP} object \mbox{\texttt{\mdseries\slshape 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.20212022Currently there are methods for matrices (see{\nobreakspace}\texttt{Browse} (\ref{Browse:for a list of lists})), for character tables (see{\nobreakspace}\texttt{Browse} (\ref{Browse:for character tables})) and for tables of marks (see{\nobreakspace}\texttt{Browse} (\ref{Browse:for tables of marks})). }20232024}202520262027\section{\textcolor{Chapter }{Matrix Display}}\label{sec:matrixdisp}2028\logpage{[ 6, 2, 0 ]}2029\hyperdef{L}{X7F6EE19480D10E2B}{}2030{2031The \textsf{GAP} library provides several \texttt{Display} (\textbf{Reference: Display}) methods for matrices. In order to cover the functionality of these methods, \textsf{Browse} provides the function \texttt{NCurses.BrowseDenseList} (\ref{NCurses.BrowseDenseList}) that uses the standard facilities of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}), i.{\nobreakspace}e., one can scroll in the matrix, searching and sorting are2032provided etc.20332034The idea is to customize this function for different special cases, and to2035install corresponding \texttt{Browse} (\ref{Browse}) methods. Examples are methods for matrices over finite fields and residue2036class rings of the rational integers, see \texttt{Browse} (\ref{Browse:for a list of lists}).20372038The code can be found in the file \texttt{app/matdisp.g} of the package.20392040\subsection{\textcolor{Chapter }{NCurses.BrowseDenseList}}2041\logpage{[ 6, 2, 1 ]}\nobreak2042\hyperdef{L}{X8295F85D87118C83}{}2043{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{NCurses.BrowseDenseList({\mdseries\slshape list, arec})\index{NCurses.BrowseDenseList@\texttt{NCurses.BrowseDenseList}}2044\label{NCurses.BrowseDenseList}2045}\hfill{\scriptsize (function)}}\\2046\textbf{\indent Returns:\ }2047nothing.2048204920502051Let \mbox{\texttt{\mdseries\slshape list}} be a dense list whose entries are lists, for example a matrix, and let \mbox{\texttt{\mdseries\slshape arec}} be a record. This function displays \mbox{\texttt{\mdseries\slshape list}} in a window, as a two-dimensional array with row and column positions as row2052and column labels, respectively.20532054The following components of \mbox{\texttt{\mdseries\slshape arec}} are supported.2055\begin{description}2056\item[{\texttt{header}}] If bound, the value must be a valid value of the \texttt{work.header} component of a browse table, see \texttt{BrowseData.IsBrowseTable} (\ref{BrowseData.IsBrowseTable}); for example, the value can be a list of strings. If this component is not2057bound then the browse table has no header.2058\item[{\texttt{convertEntry}}] If bound, the value must be a unary function that returns a string describing2059its argument. The default is the operation \texttt{String} (\textbf{Reference: String}). Another possible value is \texttt{NCurses.ReplaceZeroByDot}, which returns the string \texttt{"."} if the argument is a zero element in the sense of \texttt{IsZero} (\textbf{Reference: IsZero}), and returns the \texttt{String} (\textbf{Reference: String}) value otherwise. For each entry in a row of \mbox{\texttt{\mdseries\slshape list}}, the \texttt{convertEntry} value is shown in the browse table.2060\item[{\texttt{labelsRow}}] If bound, the value must be a list of row label rows for \mbox{\texttt{\mdseries\slshape list}}, as described in Section \texttt{BrowseData.IsBrowseTable} (\ref{BrowseData.IsBrowseTable}). The default is \texttt{[ [ "1" ], [ "2" ], ... ]}.2061\item[{\texttt{labelsCol}}] If bound, the value must be a list of column label rows for \mbox{\texttt{\mdseries\slshape list}}, as described in Section \texttt{BrowseData.IsBrowseTable} (\ref{BrowseData.IsBrowseTable}). The default is \texttt{[ [ "1", "2", ... ] ]}.2062\end{description}206320642065The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available. }2066206720682069\subsection{\textcolor{Chapter }{Browse (for a list of lists)}}2070\logpage{[ 6, 2, 2 ]}\nobreak2071\hyperdef{L}{X7AD78A0B7BEDBB20}{}2072{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Browse({\mdseries\slshape list})\index{Browse@\texttt{Browse}!for a list of lists}2073\label{Browse:for a list of lists}2074}\hfill{\scriptsize (method)}}\\2075\textbf{\indent Returns:\ }2076nothing.2077207820792080Several methods for the operation \texttt{Browse} (\ref{Browse}) are installed for the case that the argument is a list of lists. These methods2081cover a default method for lists of lists and the \texttt{Display} (\textbf{Reference: Display}) methods for matrices over finite fields and residue class rings of the2082rational integers. Note that matrices over finite prime fields, small2083extension fields, and large extension fields are displayed differently, and2084the same holds for the corresponding \texttt{Browse} (\ref{Browse}) methods.208520862087\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2088!gapprompt@gap>| !gapinput@n:= [ 14, 14, 14, 14 ];;|2089!gapprompt@gap>| !gapinput@input:= Concatenation( n, n, n, "Q" );; # ``do nothing and quit''|2090!gapprompt@gap>| !gapinput@BrowseData.SetReplay( input );|2091!gapprompt@gap>| !gapinput@Browse( RandomMat( 10, 10, Integers ) );|2092!gapprompt@gap>| !gapinput@BrowseData.SetReplay( input );|2093!gapprompt@gap>| !gapinput@Browse( RandomMat( 10, 10, GF(3) ) );|2094!gapprompt@gap>| !gapinput@BrowseData.SetReplay( input );|2095!gapprompt@gap>| !gapinput@Browse( RandomMat( 10, 10, GF(4) ) );|2096!gapprompt@gap>| !gapinput@BrowseData.SetReplay( input );|2097!gapprompt@gap>| !gapinput@Browse( RandomMat( 10, 10, Integers mod 6 ) );|2098!gapprompt@gap>| !gapinput@BrowseData.SetReplay( input );|2099!gapprompt@gap>| !gapinput@Browse( RandomMat( 10, 10, GF( NextPrimeInt( 2^16 ) ) ) );|2100!gapprompt@gap>| !gapinput@BrowseData.SetReplay( input );|2101!gapprompt@gap>| !gapinput@Browse( RandomMat( 10, 10, GF( 2^20 ) ) );|2102!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|2103\end{Verbatim}2104}21052106}210721082109\section{\textcolor{Chapter }{Character Table Display}}\label{sec:ctbldisp}2110\logpage{[ 6, 3, 0 ]}2111\hyperdef{L}{X8720923F7FDE5223}{}2112{2113The \textsf{GAP} library provides a \texttt{Display} (\textbf{Reference: Display}) method for character tables that breaks the table into columns fitting on the2114screen. \textsf{Browse} provides an alternative, using the standard facilities of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}), i.{\nobreakspace}e., one can scroll in the matrix of character values,2115searching and sorting are provided etc.21162117The \texttt{Browse} (\ref{Browse}) method for character tables can be called instead of \texttt{Display} (\textbf{Reference: Display}). For convenience, one can additionally make this function the default \texttt{Display} (\textbf{Reference: Display}) method for character tables, by assigning it to the \texttt{Display} component in the global record \texttt{CharacterTableDisplayDefaults.User}, see{\nobreakspace} (\textbf{Reference: Printing Character Tables}); for example, one can do this in one's \texttt{gaprc} file, see{\nobreakspace} (\textbf{Reference: The gap.ini and gaprc files}). (This can be undone by unbinding the component \texttt{CharacterTableDisplayDefaults.User.Display}.)21182119The function \texttt{BrowseDecompositionMatrix} (\ref{BrowseDecompositionMatrix}) can be used to display decomposition matrices for Brauer character tables.21202121\subsection{\textcolor{Chapter }{Browse (for character tables)}}2122\logpage{[ 6, 3, 1 ]}\nobreak2123\hyperdef{L}{X870C744182073CF6}{}2124{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Browse({\mdseries\slshape tbl[, options]})\index{Browse@\texttt{Browse}!for character tables}2125\label{Browse:for character tables}2126}\hfill{\scriptsize (method)}}\\212721282129This method displays the character table \mbox{\texttt{\mdseries\slshape tbl}} in a window. The optional record \mbox{\texttt{\mdseries\slshape options}} describes what shall be displayed, the supported components and the default2130values are described in{\nobreakspace} (\textbf{Reference: Printing Character Tables}).21312132The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available.213321342135\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2136!gapprompt@gap>| !gapinput@if TestPackageAvailability( "CTblLib" ) = true then|2137!gapprompt@>| !gapinput@ BrowseData.SetReplay( Concatenation(|2138!gapprompt@>| !gapinput@ # scroll in the table|2139!gapprompt@>| !gapinput@ "DRULdddddrrrrrlluu",|2140!gapprompt@>| !gapinput@ # select an entry and move it around|2141!gapprompt@>| !gapinput@ "seddrruuuddlll",|2142!gapprompt@>| !gapinput@ # search for the pattern 135 (six times)|2143!gapprompt@>| !gapinput@ "/135", [ NCurses.keys.ENTER ], "nnnnn",|2144!gapprompt@>| !gapinput@ # deselect the entry, select the first column|2145!gapprompt@>| !gapinput@ "qLsc",|2146!gapprompt@>| !gapinput@ # sort and categorize by this column|2147!gapprompt@>| !gapinput@ "sc",|2148!gapprompt@>| !gapinput@ # select the first row, move down the selection|2149!gapprompt@>| !gapinput@ "srdddd",|2150!gapprompt@>| !gapinput@ # expand the selected category, scroll the selection down|2151!gapprompt@>| !gapinput@ "xd",|2152!gapprompt@>| !gapinput@ # and quit the application|2153!gapprompt@>| !gapinput@ "Q" ) );|2154!gapprompt@>| !gapinput@ Browse( CharacterTable( "HN" ) );|2155!gapprompt@>| !gapinput@ BrowseData.SetReplay( false );|2156!gapprompt@>| !gapinput@fi;|2157\end{Verbatim}215821592160\emph{Implementation remarks}: The first part of the code in the \texttt{Browse} (\ref{Browse}) method for character tables is almost identical with the code for extracting2161the 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.2162Character names and (if applicable) indicator values are used as row labels,2163and centralizer orders, power maps, and class names are used as column labels.2164The identifier of the table is used as the static header. When an irrational2165entry is selected, a description of this entry is shown in the dynamic footer.21662167The standard modes in \texttt{BrowseData} (\ref{BrowseData}) (except the \texttt{help} mode) have been extended by three new actions. The first two of them open2168pagers giving an overview of all irrationalities in the table, or of all those2169irrationalities that have been shown on the screen in the current call,2170respectively. The corresponding user inputs are the \textsc{I} and the \textsc{i} key. (The names assigned to the irrationalities are generated column-wise. If2171one just scrolls through the table, without jumping, then these names coincide2172with the names generated by the default \texttt{Display} (\textbf{Reference: 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.) The2173third new action, which is associated with the \textsc{p} key, toggles the visibility status of the column label rows for centralizer2174orders and power maps.21752176An individual \texttt{minyx} function does not only check whether the desired table fits into the window2177but also whether a table with too high column labels (centralizer orders and2178power maps) would fit if these labels get collapsed via the \textsc{p} key. In this case, the labels are automatically collapsed, and the \textsc{p} key is disabled.21792180In order to keep the required space small also for large character tables,2181caching of formatted matrix entries is disabled, and the strings to be2182displayed 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 one2183for all table rows is set in advance, so one need not inspect a whole2184character if only a few values of it shall be shown.21852186Special functions are provided for sorting (concerning the comparison of2187character values, which can be integers or irrationalities) and categorizing2188the table by a column (the value in the category row involves the class name2189of the column in question).21902191The code can be found in the file \texttt{app/ctbldisp.g} of the package. }2192219321942195\subsection{\textcolor{Chapter }{BrowseDecompositionMatrix}}2196\logpage{[ 6, 3, 2 ]}\nobreak2197\hyperdef{L}{X7D80A56D853C9655}{}2198{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseDecompositionMatrix({\mdseries\slshape modtbl[, b][, options]})\index{BrowseDecompositionMatrix@\texttt{BrowseDecompositionMatrix}}2199\label{BrowseDecompositionMatrix}2200}\hfill{\scriptsize (function)}}\\220122022203This method displays the decomposition matrix of (the \mbox{\texttt{\mdseries\slshape b}}-th block of) the Brauer character table \mbox{\texttt{\mdseries\slshape modtbl}} in a window. The arguments are the same as for \texttt{LaTeXStringDecompositionMatrix} (\textbf{Reference: LaTeXStringDecompositionMatrix}).22042205The positions of the ordinary and modular irreducible characters are shown in2206the labels of the rows and columns, respectively, that are indexed by these2207characters. When an entry in the decomposition matrix is selected then2208information about the degrees of these characters is shown in the table2209footer.22102211The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available.221222132214\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2215!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation(|2216!gapprompt@>| !gapinput@ # select the first entry|2217!gapprompt@>| !gapinput@ "se",|2218!gapprompt@>| !gapinput@ # scroll in the table|2219!gapprompt@>| !gapinput@ "drrrr",|2220!gapprompt@>| !gapinput@ # keep the table open for a while|2221!gapprompt@>| !gapinput@ [ 14, 14, 14, 14, 14 ],|2222!gapprompt@>| !gapinput@ # and quit the application|2223!gapprompt@>| !gapinput@ "Q" ) );|2224!gapprompt@gap>| !gapinput@BrowseDecompositionMatrix( CharacterTable( "J1" ) mod 2 );|2225!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|2226\end{Verbatim}222722282229The code can be found in the file \texttt{app/ctbldisp.g} of the package. }22302231}223222332234\section{\textcolor{Chapter }{Table of Marks Display}}\label{sec:tomdisp}2235\logpage{[ 6, 4, 0 ]}2236\hyperdef{L}{X80E9A03780DE8891}{}2237{2238The \textsf{GAP} library provides a \texttt{Display} (\textbf{Reference: Display}) method for tables of marks that breaks the table into columns fitting on the2239screen. Similar to the situation with character tables, see2240Section{\nobreakspace}\ref{sec:ctbldisp}, but with a much simpler implementation, \textsf{Browse} provides an alternative based on the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}).22412242\texttt{Browse} (\ref{Browse}) can be called instead of \texttt{Display} (\textbf{Reference: Display}) for tables of marks, cf.{\nobreakspace} (\textbf{Reference: Printing Tables of Marks}).22432244\subsection{\textcolor{Chapter }{Browse (for tables of marks)}}2245\logpage{[ 6, 4, 1 ]}\nobreak2246\hyperdef{L}{X7F4BD9C580BBBAA4}{}2247{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Browse({\mdseries\slshape tom[, options]})\index{Browse@\texttt{Browse}!for tables of marks}2248\label{Browse:for tables of marks}2249}\hfill{\scriptsize (method)}}\\225022512252This method displays the table of marks \mbox{\texttt{\mdseries\slshape tom}} in a window. The optional record \mbox{\texttt{\mdseries\slshape options}} describes what shall be displayed, the supported components and the default2253values are described in{\nobreakspace} (\textbf{Reference: Printing Tables of Marks}).22542255The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available.225622572258\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2259!gapprompt@gap>| !gapinput@if TestPackageAvailability( "TomLib" ) = true then|2260!gapprompt@>| !gapinput@ BrowseData.SetReplay( Concatenation(|2261!gapprompt@>| !gapinput@ # scroll in the table|2262!gapprompt@>| !gapinput@ "DDRRR",|2263!gapprompt@>| !gapinput@ # search for the (exact) value 100 (three times)|2264!gapprompt@>| !gapinput@ "/100",|2265!gapprompt@>| !gapinput@ [ NCurses.keys.DOWN, NCurses.keys.DOWN, NCurses.keys.RIGHT ],|2266!gapprompt@>| !gapinput@ [ NCurses.keys.DOWN, NCurses.keys.DOWN, NCurses.keys.DOWN ],|2267!gapprompt@>| !gapinput@ [ NCurses.keys.RIGHT, NCurses.keys.ENTER ], "nn",|2268!gapprompt@>| !gapinput@ # no more occurrences of 100, confirm|2269!gapprompt@>| !gapinput@ [ NCurses.keys.ENTER ],|2270!gapprompt@>| !gapinput@ # and quit the application|2271!gapprompt@>| !gapinput@ "Q" ) );|2272!gapprompt@>| !gapinput@ Browse( TableOfMarks( "A10" ) );|2273!gapprompt@>| !gapinput@ BrowseData.SetReplay( false );|2274!gapprompt@>| !gapinput@ fi;|2275\end{Verbatim}227622772278\emph{Implementation remarks}: Rows and columns are indexed by their positions. The identifier of the table2279is used as the static header, there is no footer.22802281In order to keep the required space small also for large tables of marks,2282caching of formatted matrix entries is disabled, and the strings to be2283displayed 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 one2284for the table rows is set in advance. (For example, the table of marks of the2285group with identifier \texttt{"O8+(2)"}, with $11171$ rows and columns, can be shown with \texttt{Browse} (\ref{Browse}) in a \textsf{GAP} session requiring about $100$ MB.)22862287The code can be found in the file \texttt{app/tomdisp.g} of the package. }22882289}229022912292\section{\textcolor{Chapter }{Table of Contents of \textsf{AtlasRep}}}\label{sec:atlasdisp}2293\logpage{[ 6, 5, 0 ]}2294\hyperdef{L}{X80370827793813FD}{}2295{2296The \textsf{GAP} package \textsf{AtlasRep} (see{\nobreakspace}\cite{AtlasRep}) is an interface to a database of representations and related data. The table2297of 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 data for later use.2298\subsection{\textcolor{Chapter }{BrowseAtlasInfo}}\logpage{[ 6, 5, 1 ]}2299\hyperdef{L}{X8411AF928194C5AB}{}2300{2301\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseAtlasInfo({\mdseries\slshape [listofnames, ]["contents", sources, ][...]})\index{BrowseAtlasInfo@\texttt{BrowseAtlasInfo}!overview of groups}2302\label{BrowseAtlasInfo:overview of groups}2303}\hfill{\scriptsize (function)}}\\2304\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseAtlasInfo({\mdseries\slshape gapname[, std][, ...]})\index{BrowseAtlasInfo@\texttt{BrowseAtlasInfo}!overview for one group}2305\label{BrowseAtlasInfo:overview for one group}2306}\hfill{\scriptsize (function)}}\\2307\textbf{\indent Returns:\ }2308the list of ``clicked'' info records.2309231023112312This function shows the information available via the \textsf{GAP} package \textsf{AtlasRep} in a browse table, cf. Section{\nobreakspace} (\textbf{AtlasRep: Accessing Data of the AtlasRep Package}) in the \textsf{AtlasRep} manual.23132314The optional arguments can be used to restrict the table to public or private2315data, or to show an overview for one particular group. The arguments are the2316same as for \texttt{DisplayAtlasInfo} (\textbf{AtlasRep: DisplayAtlasInfo}), see the documentation of this function for details. (Note that additional2317conditions such as \texttt{IsPermGroup} (\textbf{Reference: IsPermGroup}) can be entered also in the case that no \mbox{\texttt{\mdseries\slshape gapname}} is given. In this situation, the additional conditions are evaluated for the ``second level tables'' that are opened by ``clicking'' on a table row or entry.)23182319When one ``clicks'' on one of the table rows or entries then a browse table with an overview of2320the information available for this group is shown, and ``clicking'' on one of the rows in these tables adds the corresponding info record (see \texttt{OneAtlasGeneratingSetInfo} (\textbf{AtlasRep: OneAtlasGeneratingSetInfo})) to the list of return values of \texttt{BrowseAtlasInfo}.23212322The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available.23232324The following example shows how \texttt{BrowseAtlasInfo} can be used to fetch info records about permutation representations of the2325alternating 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 data available2326for $A_5$; moving down two rows and hitting the \textsc{Enter} key again causes the second representation to be added to the result list;2327hitting \textsc{Q} closes the second window, and we are back in the overview table; we move the2328selection down twice (to the row for the group $A_6$), and choose the first representation for this group; finally we leave the2329table, and the return value is the list with the data for the two2330representations.233123322333\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2334!gapprompt@gap>| !gapinput@d:= [ NCurses.keys.DOWN ];; r:= [ NCurses.keys.RIGHT ];;|2335!gapprompt@gap>| !gapinput@c:= [ NCurses.keys.ENTER ];;|2336!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation(|2337!gapprompt@>| !gapinput@ "/A5", # Find the string A5 ...|2338!gapprompt@>| !gapinput@ d, d, r, # ... such that just the word matches,|2339!gapprompt@>| !gapinput@ c, # start the search,|2340!gapprompt@>| !gapinput@ c, # click the table entry A5,|2341!gapprompt@>| !gapinput@ d, d, # move down two rows,|2342!gapprompt@>| !gapinput@ c, # click the row for this representation,|2343!gapprompt@>| !gapinput@ "Q", # quit the second level table,|2344!gapprompt@>| !gapinput@ d, d, # move down two rows,|2345!gapprompt@>| !gapinput@ c, # click the table entry A6,|2346!gapprompt@>| !gapinput@ d, # move down one row,|2347!gapprompt@>| !gapinput@ c, # click the first row,|2348!gapprompt@>| !gapinput@ "Q", # quit the second level table,|2349!gapprompt@>| !gapinput@ "Q" ) ); # and quit the application.|2350!gapprompt@gap>| !gapinput@if IsBound( BrowseAtlasInfo ) and IsBound( AtlasProgramInfo ) then|2351!gapprompt@>| !gapinput@ tworeps:= BrowseAtlasInfo();|2352!gapprompt@>| !gapinput@ else|2353!gapprompt@>| !gapinput@ tworeps:= [ fail ];|2354!gapprompt@>| !gapinput@ fi;|2355!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|2356!gapprompt@gap>| !gapinput@if fail in tworeps then|2357!gapprompt@>| !gapinput@ Print( "no access to the Web ATLAS\n" );|2358!gapprompt@>| !gapinput@ else|2359!gapprompt@>| !gapinput@ Print( List( tworeps, x -> x.identifier[1] ), "\n" );|2360[ "A5", "A6" ]2361!gapprompt@>| !gapinput@ fi;|2362\end{Verbatim}236323642365\emph{Implementation remarks}: The first browse table shown has a static header, no footer and row labels,2366one row of column labels describing the type of data summarized in the2367columns.23682369Row and column separators are drawn as grids (cf.{\nobreakspace}\texttt{NCurses.Grid} (\ref{NCurses.Grid})) composed from the special characters described in Section{\nobreakspace}\ref{ssec:ncursesLines}, using the component \texttt{work.SpecialGrid} of the browse table, see \texttt{BrowseData} (\ref{BrowseData}).23702371When 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 data for the given group2372is shown; in this table, ``click'' results in adding the info for the selected row to the result list, and a2373message about this addition is shown in the footer row. One can choose further2374data, return to the first browse table, and perhaps iterate the process for2375other groups. When the first level table is left, the list of info records for2376the chosen data is returned.23772378For the two kinds of browse tables, the standard modes in \texttt{BrowseData} (\ref{BrowseData}) (except the \texttt{help} mode) have been extended by a new action that opens a pager giving an overview2379of all data that have been chosen in the current call. The corresponding user2380input is the \textsc{Y} key.23812382This function is available only if the \textsf{GAP} package \textsf{AtlasRep} is available.23832384The code can be found in the file \texttt{app/atlasbrowse.g} of the package. }23852386}238723882389\section{\textcolor{Chapter }{Access to \textsf{GAP} Manuals{\textendash}a Variant}}\label{sec:manualdisp}2390\logpage{[ 6, 6, 0 ]}2391\hyperdef{L}{X7CF999297B331E01}{}2392{2393A \textsf{Browse} adapted way to access several manuals is to show the hierarchy of books,2394chapters, sections, and subsections as collapsible category rows, and to2395regard the contents of each subsection as a data row of a matrix with only one2396column.23972398This application is mainly intended as an example with table cells that exceed2399the screen, and as an example with several category levels.24002401\subsection{\textcolor{Chapter }{BrowseGapManuals}}2402\logpage{[ 6, 6, 1 ]}\nobreak2403\hyperdef{L}{X7D79DF9181A15EDF}{}2404{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseGapManuals({\mdseries\slshape [start]})\index{BrowseGapManuals@\texttt{BrowseGapManuals}}2405\label{BrowseGapManuals}2406}\hfill{\scriptsize (function)}}\\240724082409This 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 optional2410argument \mbox{\texttt{\mdseries\slshape start}} describes the initial status, admissible values are the strings \texttt{"inline/collapsed"}, \texttt{"inline/expanded"}, \texttt{"pager/collapsed"}, and \texttt{"pager/expanded"}.24112412In 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}).24132414In the \texttt{collapsed} cases, all category rows are collapsed, and the first row is selected; typical2415next steps are moving down the selection and expanding single category rows.2416In the \texttt{expanded} cases, all category rows are expanded, and nothing is selected; a typical next2417step in the \texttt{inline/expanded} case is a search for a string in the manuals. (Note that searching in quite2418slow: For viewing a part of a manual, the file with the corresponding section2419is read into \textsf{GAP}, the text is formatted, the relevant part is cut out from the section,2420perhaps markup is stripped off, and finally the search is performed in the2421resulting strings.)24222423If no argument is given then the user is asked for selecting an initial2424status, using \texttt{NCurses.Select} (\ref{NCurses.Select}).24252426The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available.242724282429\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2430!gapprompt@gap>| !gapinput@n:= [ 14, 14, 14 ];; # ``do nothing''|2431!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation(|2432!gapprompt@>| !gapinput@ "xdxd", # expand a Tutorial section|2433!gapprompt@>| !gapinput@ n, "Q" ) ); # and quit|2434!gapprompt@gap>| !gapinput@BrowseGapManuals( "inline/collapsed" );|2435!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation(|2436!gapprompt@>| !gapinput@ "/Browse", [ NCurses.keys.ENTER ], # search for "Browse"|2437!gapprompt@>| !gapinput@ "xdxddxd", # expand a section|2438!gapprompt@>| !gapinput@ n, "Q" ) ); # and quit|2439!gapprompt@gap>| !gapinput@BrowseGapManuals( "inline/collapsed" );|2440!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|2441\end{Verbatim}244224432444\emph{Implementation remarks}: The browse table has a dynamic header showing the name of the currently2445selected manual, no footer, no row or column labels, and exactly one column of2446fixed width equal to the screen width. The category rows are precomputed,2447i.{\nobreakspace}e., they do not arise from a table column; this way, the2448contents of each data cell can be computed on demand, as soon as it is shown2449on the screen, in particular the category hierarchy is computed without2450reading the manuals into \textsf{GAP}. Also, the data rows are not cached. There is no return value. The heights of2451many cells are bigger than the screen height, so scrolling is a mixture of2452scrolling to the next cell and scrolling inside a cell. The different initial2453states are realized via executing different initial steps before the table is2454shown to the user.24552456For the variants that show the manuals in a pager, the code temporarily2457replaces 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,2458the default \texttt{show} function writes this text directly to the screen, but this is used already by2459the browse table.24602461The implementation should be regarded as a sketch.24622463For 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 lines2464that arise, because of the highlighting problem mentioned in2465Section{\nobreakspace}\ref{NCurses.IsAttributeLine}.24662467Some heuristics used in the code are due to deficiencies of the manual2468formats.24692470For the inline variant of the browse table, the titles of chapters, sections,2471and subsections are \emph{not} regarded as parts of the actual text since they appear already as category2472rows; 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.24732474The 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 for2475determining whether several functions define the same subsection, in the sense2476that there is a common description text after a series of manual lines2477introducing different functions. In such cases, the browse table contains a2478category row for each of these functions (with its own number), but the2479corresponding text appears only under the \emph{last} of these category rows, the data rows for the others are empty. (This problem2480does not occur in the \textsf{GAPDoc} manual format because this introduces explicit subsection titles, involving2481only the \emph{first} of several function definitions.)24822483Also, index entries and sectioning entries in \texttt{manual.six} files of manuals in \textsf{GAPDoc} format are not explicitly distinguished.24842485The code can be found in the file \texttt{app/manual.g} of the package. }24862487}248824892490\section{\textcolor{Chapter }{Overview of Bibliographies}}\label{sec:gapbibl}2491\logpage{[ 6, 7, 0 ]}2492\hyperdef{L}{X846751CC7F54F51D}{}2493{2494The function \texttt{BrowseBibliography} (\ref{BrowseBibliography}) can be used to turn the contents of bibliography files in BibTeX or BibXMLext2495format (see (\textbf{GAPDoc: The BibXMLext Format})) into a Browse table, such that one can scroll in the list, search for2496entries, sort by year, sort and categorize by authors etc.24972498The default bibliography used by \texttt{BrowseBibliography} (\ref{BrowseBibliography}) is the bibliography of \textsf{GAP} related publications, see{\nobreakspace}\cite{GAPBibliography}. The \textsf{Browse} package contains a (perhaps outdated) version of this bibliography. One can2499get an updated version as follows.25002501\texttt{wget -N http://www.gap-system.org/Doc/Bib/gap-publishednicer.bib}25022503The columns of the Browse table that is shown by \texttt{BrowseBibliography} (\ref{BrowseBibliography}) can be customized, two examples for that are given by the functions \texttt{BrowseBibliographySporadicSimple} (\textbf{AtlasRep: BrowseBibliographySporadicSimple}) and \texttt{BrowseBibliographyGapPackages} (\ref{BrowseBibliographyGapPackages}).25042505The function \texttt{BrowseMSC} (\ref{BrowseMSC}) shows an overview of the AMS Mathematics Subject Classification codes.25062507\subsection{\textcolor{Chapter }{BrowseBibliography}}2508\logpage{[ 6, 7, 1 ]}\nobreak2509\hyperdef{L}{X7F0FE4CC7F46ABF3}{}2510{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseBibliography({\mdseries\slshape [bibfiles]})\index{BrowseBibliography@\texttt{BrowseBibliography}}2511\label{BrowseBibliography}2512}\hfill{\scriptsize (function)}}\\2513\textbf{\indent Returns:\ }2514a record as returned by \texttt{ParseBibXMLExtFiles} (\textbf{GAPDoc: ParseBibXMLextFiles}).2515251625172518This function shows the list of bibliography entries in the files given by \mbox{\texttt{\mdseries\slshape bibfiles}}, which may be a string or a list of strings (denoting a filename or a list of2519filenames, respectively) or a record (see below for the supported components).25202521If no argument is given then the file \texttt{bibl/gap-publishednicer.bib} in the \textsf{Browse} package directory is taken, and \texttt{"GAP Bibliography"} is used as the header.25222523Another perhaps interesting data file that should be available in the \textsf{GAP} distribution is \texttt{doc/manualbib.xml}. This file can be located as follows.252425252526\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2527!gapprompt@gap>| !gapinput@file:= Filename( DirectoriesLibrary( "doc" ), "manualbib.xml" );;|2528\end{Verbatim}252925302531Both Bib{\TeX} format and the \textsf{XML} based extended format provided by the \textsf{GAPDoc} package are supported by \texttt{BrowseBibliography}, see Chapter{\nobreakspace} (\textbf{GAPDoc: Utilities for Bibliographies}).25322533In the case of Bib{\TeX} format input, first a conversion to the extended format takes place, via \texttt{StringBibAsXMLext} (\textbf{GAPDoc: StringBibAsXMLext}) and \texttt{ParseBibXMLextString} (\textbf{GAPDoc: ParseBibXMLextString}). Note that syntactically incorrect entries are rejected in this conversion2534{\textendash}this is signaled with \texttt{InfoBibTools} (\textbf{GAPDoc: InfoBibTools}) warnings{\textendash} and that only a subset of the possible {\LaTeX} markup is recognized {\textendash}other markup appears in the browse table2535except that the leading backslash is removed.25362537In both cases of input, the problem arises that in visual mode, currently we2538can show only ASCII characters (and the symbols in \texttt{NCurses.lineDraw}, but these are handled differently, see Section{\nobreakspace}\ref{ssec:ncursesLines}). Therefore, we use the function \texttt{SimplifiedUnicodeString} (\textbf{GAPDoc: SimplifiedUnicodeString}) for replacing other unicode characters by ASCII text.25392540The return value is a record as returned by \texttt{ParseBibXMLExtFiles} (\textbf{GAPDoc: ParseBibXMLextFiles}), its \texttt{entries} component corresponds to the bibliography entries that have been ``clicked'' in visual mode. This record can be used as input for \texttt{WriteBibFile} (\textbf{GAPDoc: WriteBibFile}) or \texttt{WriteBibXMLextFile} (\textbf{GAPDoc: WriteBibXMLextFile}), in order to produce a bibliography file, or it can be used as input for \texttt{StringBibXMLEntry} (\textbf{GAPDoc: StringBibXMLEntry}), in order to produce strings from the entries, in various formats.25412542The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available.254325442545\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2546!gapprompt@gap>| !gapinput@# sort and categorize by year, scroll down, expand a category row|2547!gapprompt@gap>| !gapinput@BrowseData.SetReplay( "scrrscsedddddxdddddQ" );|2548!gapprompt@gap>| !gapinput@BrowseBibliography();;|2549!gapprompt@gap>| !gapinput@# sort & categorize by authors, expand all category rows, scroll down|2550!gapprompt@gap>| !gapinput@BrowseData.SetReplay( "scscXseddddddQ" );|2551!gapprompt@gap>| !gapinput@BrowseBibliography();;|2552!gapprompt@gap>| !gapinput@# sort and categorize by journal, search for a journal name, expand|2553!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation( "scrrrsc/J. Algebra",|2554!gapprompt@>| !gapinput@ [ NCurses.keys.ENTER ], "nxdddQ" ) );|2555!gapprompt@gap>| !gapinput@BrowseBibliography();;|2556!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|2557\end{Verbatim}255825592560\emph{Implementation remarks}: The browse table has a dynamic header (showing the number of entries, which2561can vary when the table is restricted), no footer and row labels; one row of2562column labels is given by the descriptions of the table columns (authors,2563title, year, journal, MSC code).25642565Row and column separators are drawn as grids (cf.{\nobreakspace}\texttt{NCurses.Grid} (\ref{NCurses.Grid})) composed from the special characters described in Section{\nobreakspace}\ref{ssec:ncursesLines}, using the component \texttt{work.SpecialGrid} of the browse table, see \texttt{BrowseData} (\ref{BrowseData}).25662567For categorizing by authors (or by MSC codes), the sort parameter \texttt{"split rows on categorizing"} is set to \texttt{"yes"}, so the authors (codes) are distributed to different category rows, hence2568each entry appears once for each of its authors (or its MSC codes) in the2569categorized table. When a data row or an entry in a data row is selected, ``click'' adds the corresponding bibliographhy entry to the result.25702571The width of the title column is preset; usually titles are too long for one2572line, and the contents of this column is formatted as a paragraph, using the2573function \texttt{FormatParagraph} (\textbf{GAPDoc: FormatParagraph}). For the authors and journal columns, maximal widths are prescribed, and \texttt{FormatParagraph} (\textbf{GAPDoc: FormatParagraph}) is used for longer entries.25742575For four columns, the sort parameters are defined as follows: The \emph{authors} and \emph{MSC code} columns do not become hidden when the table is categorized according to this2576column, sorting by the \emph{year} yields a \emph{de}scending order, and the category rows arising from these columns and the \emph{journal} column show the numbers of the data rows that belong to them.25772578Those standard modes in \texttt{BrowseData} (\ref{BrowseData}) where an entry or a row of the table is selected have been extended by three2579new actions, which open a pager showing the Bib{\TeX}, HTML, and Text format of the selected entry, respectively. The corresponding2580user inputs are the \textsc{vb}, \textsc{vh}, and \textsc{vt}. If the \emph{MSC code} column is available then also the user input \textsc{vm} is admissible; it opens a pager showing the descriptions of the MSC codes2581attached to the selected entry.25822583This function requires some of the utilities provided by the \textsf{GAP} package \textsf{GAPDoc} (see{\nobreakspace}\cite{GAPDoc}), such as \texttt{FormatParagraph} (\textbf{GAPDoc: FormatParagraph}), \texttt{NormalizeNameAndKey} (\textbf{GAPDoc: NormalizeNameAndKey}), \texttt{NormalizedNameAndKey} (\textbf{GAPDoc: NormalizedNameAndKey}), \texttt{ParseBibFiles} (\textbf{GAPDoc: ParseBibFiles}), \texttt{ParseBibXMLextFiles} (\textbf{GAPDoc: ParseBibXMLextFiles}), \texttt{ParseBibXMLextString} (\textbf{GAPDoc: ParseBibXMLextString}), \texttt{RecBibXMLEntry} (\textbf{GAPDoc: RecBibXMLEntry}), and \texttt{StringBibAsXMLext} (\textbf{GAPDoc: StringBibAsXMLext}).25842585The code can be found in the file \texttt{app/gapbibl.g} of the package.25862587The browse table can be customized by entering a record as the argument of \texttt{BrowseBibliography}, with the following supported components.2588\begin{description}2589\item[{\texttt{files}}] a nonempty list of filenames containing the data to be shown; there is no2590default for this component.2591\item[{\texttt{filesshort}}] a list of the same length as the \texttt{files} component, the entries are strings which are shown in the \texttt{"sourcefilename"} column of the table (if this column is present); the default is the list of2592filenames.2593\item[{\texttt{filecontents}}] a list of the same length as the \texttt{files} component, the entries are strings which are shown as category values when the2594table is categorized by the \texttt{"sourcefilename"} column; the default is the list of filenames.2595\item[{\texttt{header}}] is the constant part of the header shown above the browse table, the default2596is the first filename.2597\item[{\texttt{columns}}] is a list of records that are valid as the second argument of \texttt{DatabaseAttributeAdd} (\ref{DatabaseAttributeAdd}), where the first argument is a database id enumerator created from the2598bibliography entries in the files in question. Each entry (and also the2599corresponding identifier) of this database id enumerator is a list of records2600obtained from \texttt{ParseBibXMLextFiles} (\textbf{GAPDoc: ParseBibXMLextFiles}) and \texttt{RecBibXMLEntry} (\textbf{GAPDoc: RecBibXMLEntry}), or from \texttt{ParseBibFiles} (\textbf{GAPDoc: ParseBibFiles}), such that the list elements are regarded as equal, in the sense that their2601fingerprints (see below) are equal. The records in the \texttt{columns} list are available for constructing the desired browse table, the actual2602appearance is controlled by the \texttt{choice} component described below. Columns showing authors, title, year, journal, MSC2603code, and filename are predefined and need not be listed here.2604\item[{\texttt{choice}}] a list of strings denoting the \texttt{identifier} components of those columns that shall actually be shown in the table, the2605default is \texttt{[ "authors", "title", "year", "journal", "mrclass" ]}.2606\item[{\texttt{fingerprint}}] a list of strings denoting component names of the entries of the database id2607enumerator that is constructed from the data (see above); two data records are2608regarded as equal if the values of these components are equal; the default is \texttt{[ "mrnumber", "title", "authorAsList", "editorAsList", "author" ]}.2609\item[{\texttt{sortKeyFunction}}] either \texttt{fail} or a function that takes a record as returned by \texttt{RecBibXMLEntry} (\textbf{GAPDoc: RecBibXMLEntry}) and returns a list that is used for comparing and thus sorting the records;2610the default is \texttt{fail}, which means that the rows of the table appear in the same ordering as in the2611source files.2612\end{description}2613}2614261526162617\subsection{\textcolor{Chapter }{BrowseBibliographyGapPackages}}2618\logpage{[ 6, 7, 2 ]}\nobreak2619\hyperdef{L}{X7E4B5E277D08987B}{}2620{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseBibliographyGapPackages({\mdseries\slshape })\index{BrowseBibliographyGapPackages@\texttt{BrowseBibliographyGapPackages}}2621\label{BrowseBibliographyGapPackages}2622}\hfill{\scriptsize (function)}}\\2623\textbf{\indent Returns:\ }2624a record as returned by \texttt{BrowseBibliography} (\ref{BrowseBibliography}).2625262626272628This function collects the information from the \texttt{*.bib} and \texttt{*bib.xml} files in those subdirectories of installed \textsf{GAP} packages which contain the package documentation, and shows it in a Browse2629table, using the function \texttt{BrowseBibliography} (\ref{BrowseBibliography}).26302631\emph{This function is experimental.} The result is not really satisfactory, for the following reasons.263226332634\begin{itemize}2635\item Duplicate entries may occur, due to subtle differences in various source2636files.2637\item The source files may contain more than what is actually cited in the package2638manuals.2639\item It may happen that some \texttt{*.bib} or \texttt{*bib.xml} file is accidentally distributed with the package but is not intended to serve2640as package bibliography.2641\item The heuristics for rewriting {\LaTeX} code is of course not perfect; thus strange symbols may occur in the Browse2642table.2643\end{itemize}2644}2645264626472648\subsection{\textcolor{Chapter }{BrowseMSC}}2649\logpage{[ 6, 7, 3 ]}\nobreak2650\hyperdef{L}{X81F1558678ACDB4A}{}2651{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseMSC({\mdseries\slshape })\index{BrowseMSC@\texttt{BrowseMSC}}2652\label{BrowseMSC}2653}\hfill{\scriptsize (function)}}\\2654\textbf{\indent Returns:\ }2655nothing.2656265726582659This function shows the currently valid MSC codes in a browse table that is2660categorized by the \texttt{..-XX} and the \texttt{...xx} codes. (Use \textsc{X} for expanding all categories or \textsc{x} for expanding the currently selected category.) Due to the categorization,2661only two columns of the table are visible, showing the codes and their2662descriptions. }26632664}266526662667\section{\textcolor{Chapter }{Profiling \textsf{GAP} functions{\textendash}a Variant}}\label{sec:profiledisp}2668\logpage{[ 6, 8, 0 ]}2669\hyperdef{L}{X837BDF547FF0EA31}{}2670{2671A \textsf{Browse} adapted way to evaluate profiling results is to show the overview that is2672printed by the \textsf{GAP} function \texttt{DisplayProfile} (\textbf{Reference: DisplayProfile}) in a \textsf{Browse} table, which allows one to sort the profiled functions according to the2673numbers of calls, the time spent, etc., and to search for certain functions2674one is interested in.26752676\subsection{\textcolor{Chapter }{BrowseProfile}}2677\logpage{[ 6, 8, 1 ]}\nobreak2678\hyperdef{L}{X7B42091982DE7AE7}{}2679{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseProfile({\mdseries\slshape [functions, ][mincount, mintime]})\index{BrowseProfile@\texttt{BrowseProfile}}2680\label{BrowseProfile}2681}\hfill{\scriptsize (function)}}\\268226832684The arguments and their meaning are the same as for the function \texttt{DisplayProfile} (\textbf{Reference: DisplayProfile}), in the sense that the lines printed by that function correspond to the rows2685of the list that is shown by \texttt{BrowseProfile}. Initially, the table is sorted in the same way as the list shown by \texttt{BrowseProfile}; sorting the table by any of the first five columns will yield a2686non-increasing order of the rows.26872688The threshold values \mbox{\texttt{\mdseries\slshape mincount}} and \mbox{\texttt{\mdseries\slshape mintime}} can be changed in visual mode via the user input \textsc{e}. If mouse events are enabled (see \texttt{NCurses.UseMouse} (\ref{NCurses.UseMouse})) then one can also use a mouse click on the current parameter value shown in2689the table header in order to enter the mode for changing the parameters.26902691When a row or an entry in a row is selected, ``click'' shows the code of the corresponding function in a pager (see \texttt{NCurses.Pager} (\ref{NCurses.Pager})) whenever this is possible, as follows. If the function was read from a file2692then this file is opened, if the function was entered interactively then the2693code of the function is shown in the format produced by \texttt{Print} (\textbf{Reference: Print}); other functions (for example \textsf{GAP} kernel functions) cannot be shown, one gets an alert message (see \texttt{NCurses.Alert} (\ref{NCurses.Alert})) in such a case.26942695The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available.269626972698\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2699!gapprompt@gap>| !gapinput@n:= [ 14, 14, 14, 14, 14 ];; # ``do nothing''|2700!gapprompt@gap>| !gapinput@ProfileOperationsAndMethods( true ); # collect some data|2701!gapprompt@gap>| !gapinput@ConjugacyClasses( PrimitiveGroup( 24, 1 ) );;|2702!gapprompt@gap>| !gapinput@ProfileOperationsAndMethods( false );|2703!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation(|2704!gapprompt@>| !gapinput@ "scso", # sort by column 1,|2705!gapprompt@>| !gapinput@ n,|2706!gapprompt@>| !gapinput@ "rso", # sort by column 2,|2707!gapprompt@>| !gapinput@ n,|2708!gapprompt@>| !gapinput@ "rso", # sort by column 3,|2709!gapprompt@>| !gapinput@ n,|2710!gapprompt@>| !gapinput@ "q", # deselect the column,|2711!gapprompt@>| !gapinput@ "/Centralizer", [ NCurses.keys.ENTER ], # search for a function,|2712!gapprompt@>| !gapinput@ n, "Q" ) ); # and quit|2713!gapprompt@gap>| !gapinput@BrowseProfile();|2714!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|2715\end{Verbatim}271627172718\emph{Implementation remarks}: The browse table has a dynamic header, which shows the current values of \mbox{\texttt{\mdseries\slshape mincount}} and \mbox{\texttt{\mdseries\slshape mintime}}, and a dynamic footer, which shows the sums of counts and timings for the2719rows in the table (label \texttt{TOTAL}) and if applicable the sums for the profiled functions not shown in the table2720(label \texttt{OTHER}). There are no row labels, and the obvious column labels. There is no return2721value.27222723The standard modes in \texttt{BrowseData} (\ref{BrowseData}) (except the \texttt{help} mode) have been modified by adding a new action for changing the threshold2724parameters \mbox{\texttt{\mdseries\slshape mincount}} and \mbox{\texttt{\mdseries\slshape mintime}} (user input \textsc{e}). The way how this in implemented made it necessary to change the standard ``reset'' action (user input \textsc{!}) of the table; note that resetting (a sorting or filtering of) the table must2725not make those rows visible that shall be hidden because of the threshold2726parameters.27272728The code can be found in the file \texttt{app/profile.g} of the package. }27292730}273127322733\section{\textcolor{Chapter }{Variables defined in \textsf{GAP} packages{\textendash}a Variant}}\label{sec:pkgvardisp}2734\logpage{[ 6, 9, 0 ]}2735\hyperdef{L}{X87B30F7387C0E531}{}2736{2737A \textsf{Browse} adapted way to list the variables that are defined in a \textsf{GAP} package is to show the overview that is printed by the \textsf{GAP} function \texttt{ShowPackageVariables} (\textbf{Reference: ShowPackageVariables}) in a \textsf{Browse} table.27382739\subsection{\textcolor{Chapter }{BrowsePackageVariables}}2740\logpage{[ 6, 9, 1 ]}\nobreak2741\hyperdef{L}{X8030B1688335783D}{}2742{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowsePackageVariables({\mdseries\slshape pkgname[, version][, arec]})\index{BrowsePackageVariables@\texttt{BrowsePackageVariables}}2743\label{BrowsePackageVariables}2744}\hfill{\scriptsize (function)}}\\2745\textbf{\indent Returns:\ }2746nothing.2747274827492750The arguments can be the same as for \texttt{ShowPackageVariables} (\textbf{Reference: ShowPackageVariables}), that is, \mbox{\texttt{\mdseries\slshape pkgname}} is the name of a \textsf{GAP} package, and the optional arguments \mbox{\texttt{\mdseries\slshape version}} and \mbox{\texttt{\mdseries\slshape arec}} are a version number of this package and a record used for customizing the2751output, respectively.27522753Alternatively, the second argument can be the output \texttt{info} of \texttt{PackageVariablesInfo} (\textbf{Reference: PackageVariablesInfo}) for the package in question, instead of the version number.27542755\texttt{BrowsePackageVariables} opens a browse table that shows the global variables that become bound and the2756methods that become installed when \textsf{GAP} loads the package \mbox{\texttt{\mdseries\slshape pkgname}}.27572758The table is categorized by the kinds of variables (new or redeclared2759operations, methods, info classes, synonyms, other globals). The column ``Doc.?'' distinguishes undocumented and documented variables, so one can use this2760column as a filter or for categorizing. The column ``Filename'' shows the names of the package files. Clicking a selected row of the table2761opens the relevant package file at the code in question.27622763The idea behind the argument \texttt{info} is that using the same arguments as for \texttt{ShowPackageVariables} (\textbf{Reference: ShowPackageVariables}) does not allow one to apply \texttt{BrowsePackageVariables} to packages that have been loaded before the \textsf{Browse} package. Thus one can compute the underlying data \texttt{info} first, using \texttt{PackageVariablesInfo} (\textbf{Reference: PackageVariablesInfo}), then load the \textsf{Browse} package, and finally call \texttt{BrowsePackageVariables}.27642765For example, the overview of package variables for \textsf{Browse} can be shown by starting \textsf{GAP} without packages and then entering the following lines.276627672768\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2769!gapprompt@gap>| !gapinput@pkgname:= "Browse";;|2770!gapprompt@gap>| !gapinput@info:= PackageVariablesInfo( pkgname, "" );;|2771!gapprompt@gap>| !gapinput@LoadPackage( "Browse" );;|2772!gapprompt@gap>| !gapinput@BrowsePackageVariables( pkgname, info );|2773\end{Verbatim}277427752776If the arguments are the same as for \texttt{ShowPackageVariables} (\textbf{Reference: ShowPackageVariables}) then this function is actually called, with the consequence that the package2777gets loaded when \texttt{BrowsePackageVariables} is called. This is not the case if the output of \texttt{PackageVariablesInfo} (\textbf{Reference: PackageVariablesInfo}) is entered as the second argument. }27782779}278027812782\section{\textcolor{Chapter }{Configuring User preferences{\textendash}a Variant}}\label{sec:userpref}2783\logpage{[ 6, 10, 0 ]}2784\hyperdef{L}{X7CD025147D528741}{}2785{2786A \textsf{Browse} adapted way to show and edit \textsf{GAP}'s user preferences is to show the overview that is printed by the \textsf{GAP} function \texttt{ShowUserPreferences} (\textbf{Reference: ShowUserPreferences}) in a \textsf{Browse} table.27872788\subsection{\textcolor{Chapter }{BrowseUserPreferences}}2789\logpage{[ 6, 10, 1 ]}\nobreak2790\hyperdef{L}{X7A7B712E7A06449F}{}2791{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseUserPreferences({\mdseries\slshape package1, package2, ...})\index{BrowseUserPreferences@\texttt{BrowseUserPreferences}}2792\label{BrowseUserPreferences}2793}\hfill{\scriptsize (function)}}\\2794\textbf{\indent Returns:\ }2795nothing.2796279727982799The arguments are the same as for \texttt{ShowUserPreferences} (\textbf{Reference: ShowUserPreferences}), that is, calling the function with no argument yields an overview of all2800known user preferences, and if one or more strings \mbox{\texttt{\mdseries\slshape package1}}, $\ldots$ are given then only the user preferences for these packages are shown.28012802\texttt{BrowseUserPreferences} opens a browse table with the following columns:280328042805\begin{description}2806\item[{``Package''}] contains the names of the \textsf{GAP} packages to which the user preferences belong,2807\item[{``Pref. names''}] contains the names of the user preferences, and2808\item[{``Description''}] contains the \texttt{description} texts from the \texttt{DeclareUserPreference} (\textbf{Reference: DeclareUserPreference}) calls and the default values (if applicable), and the actual values.2809\end{description}281028112812When one ``clicks'' on one of the table rows or entries then the values of the user preference in2813question can be edited. If a list of admissible values is known then this2814means that one can choose from this list via \texttt{NCurses.Select} (\ref{NCurses.Select}), otherwise one can enter the desired value as text.28152816The values of the user preferences are not changed before one closes the2817browse table. When the table is left and if one has changed at least one2818value, one is asked whether the changes shall be applied.281928202821\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2822!gapprompt@gap>| !gapinput@d:= [ NCurses.keys.DOWN ];; |2823!gapprompt@gap>| !gapinput@c:= [ NCurses.keys.ENTER ];; |2824!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation(|2825!gapprompt@>| !gapinput@ "/PackagesToLoad", # enter a search string,|2826!gapprompt@>| !gapinput@ c, # start the search,|2827!gapprompt@>| !gapinput@ c, # edit the entry (a list of choices),|2828!gapprompt@>| !gapinput@ " ", d, # toggle the first four values,|2829!gapprompt@>| !gapinput@ " ", d, #|2830!gapprompt@>| !gapinput@ " ", d, #|2831!gapprompt@>| !gapinput@ " ", d, #|2832!gapprompt@>| !gapinput@ c, # submit the values,|2833!gapprompt@>| !gapinput@ "Q", # quit the table,|2834!gapprompt@>| !gapinput@ c ) ); # choose "cancel": do not apply the changes.|2835!gapprompt@gap>| !gapinput@BrowseUserPreferences();|2836!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|2837\end{Verbatim}283828392840The code can be found in the file \texttt{app/userpref.g} of the package. }28412842}284328442845\section{\textcolor{Chapter }{Overview of \textsf{GAP} Data}}\label{sec:datadisp}2846\logpage{[ 6, 11, 0 ]}2847\hyperdef{L}{X86C730A07855238D}{}2848{2849The \textsf{GAP} system contains several data collections such as libraries of groups and2850character tables. Clearly the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) can be used to visualize interesting information about such data collections,2851in the form of an ``overview table'' whose rows correspond to the objects in the collection; each column of the2852table shows a piece of information about the objects. (One possibility to2853create such overviews is given by \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}).)28542855\subsection{\textcolor{Chapter }{BrowseGapData}}2856\logpage{[ 6, 11, 1 ]}\nobreak2857\hyperdef{L}{X850C786C87A4877B}{}2858{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseGapData({\mdseries\slshape })\index{BrowseGapData@\texttt{BrowseGapData}}2859\label{BrowseGapData}2860}\hfill{\scriptsize (function)}}\\2861\textbf{\indent Returns:\ }2862the return value of the chosen application if there is one.2863286428652866The function \texttt{BrowseGapData} shows the choices in the list \texttt{BrowseData.GapDataOverviews}, in a browse table with one column. When an entry is ``clicked'' then the associated function is called, and the table of choices is closed.28672868The idea is that each entry of \texttt{BrowseData.GapDataOverviews} describes an overview of a data collection.28692870The \textsf{Browse} package provides overviews of2871\begin{itemize}2872\item the current AMS Mathematics Subject Classification codes (see \texttt{BrowseMSC} (\ref{BrowseMSC})),2873\item the contents of the \textsf{AtlasRep} package \cite{AtlasRep} (only if this package is loaded, see Section{\nobreakspace}\ref{sec:atlasdisp}),2874\item \index{BrowseConwayPolynomials@\texttt{BrowseConwayPolynomials}!see BrowseGapData} the Conway polynomials in \textsf{GAP} (calls \texttt{BrowseConwayPolynomials()}),2875\item profile information for \textsf{GAP} functions (see Section{\nobreakspace}\ref{sec:profiledisp}),2876\item the list of \textsf{GAP} related bibliography entries in the file \texttt{bibl/gap-publishednicer.bib} of the \textsf{Browse} package (see Section{\nobreakspace}\ref{sec:gapbibl}),2877\item the \textsf{GAP} manuals (see Section{\nobreakspace}\ref{sec:manualdisp}),2878\item \index{BrowseGapMethods@\texttt{BrowseGapMethods}!see BrowseGapData} \textsf{GAP} operations and methods (calls \texttt{BrowseGapMethods()}),2879\item \index{BrowseGapPackages@\texttt{BrowseGapPackages}!see BrowseGapData} the installed \textsf{GAP} packages (calls \texttt{BrowseGapPackages()}),2880\item \textsf{GAP}'s user preferences (see Section{\nobreakspace}\ref{sec:userpref}),2881\item the contents of the \textsf{TomLib} package \cite{TomLib} (only if this package is loaded, see Section{\nobreakspace}\ref{sect:tomlibinfo}),2882\end{itemize}288328842885Other \textsf{GAP} packages may add more overviews, using the function \texttt{BrowseGapDataAdd} (\ref{BrowseGapDataAdd}). For example, there are overviews of2886\begin{itemize}2887\item the bibliographies in the \textsf{ATLAS} of Finite Groups \cite{CCN85} and in the \textsf{ATLAS} of Brauer Characters \cite{JLPW95} (see \texttt{BrowseBibliographySporadicSimple} (\textbf{AtlasRep: BrowseBibliographySporadicSimple})),2888\item atomic irrationalities that occur in character tables in the \textsf{ATLAS} of Finite Groups \cite{CCN85} or the \textsf{ATLAS} of Brauer Characters \cite{JLPW95} (see Section \texttt{BrowseCommonIrrationalities} (\textbf{CTblLib: BrowseCommonIrrationalities})),2889\item the differences between the versions of the character table data in the \textsf{CTblLib} package (see Section \texttt{BrowseCTblLibDifferences} (\textbf{CTblLib: BrowseCTblLibDifferences})),2890\item the information in the \textsf{GAP} Character Table Library (see Section \texttt{BrowseCTblLibInfo} (\textbf{CTblLib: BrowseCTblLibInfo})),2891\item an overview of minimal degrees of representations of groups from the \textsf{ATLAS} of Group Representations (see Section \texttt{BrowseMinimalDegrees} (\textbf{AtlasRep: BrowseMinimalDegrees})).2892\end{itemize}289328942895Except that always one table cell is selected, the full functionality of the2896function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available.289728982899\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2900!gapprompt@gap>| !gapinput@n:= [ 14, 14, 14 ];; # ``do nothing''|2901!gapprompt@gap>| !gapinput@# open the overview of Conway polynomials|2902!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation( "/Conway Polynomials",|2903!gapprompt@>| !gapinput@ [ NCurses.keys.ENTER, NCurses.keys.ENTER ], "srdddd", n, "Q" ) );|2904!gapprompt@gap>| !gapinput@BrowseGapData();;|2905!gapprompt@gap>| !gapinput@# open the overview of GAP packages|2906!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation( "/GAP Packages",|2907!gapprompt@>| !gapinput@ [ NCurses.keys.ENTER, NCurses.keys.ENTER ], "/Browse",|2908!gapprompt@>| !gapinput@ [ NCurses.keys.ENTER ], "n", n, "Q" ) );|2909!gapprompt@gap>| !gapinput@BrowseGapData();;|2910!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|2911\end{Verbatim}291229132914\emph{Implementation remarks}: The browse table has a static header, a dynamic footer showing the2915description of the currently selected entry, no row or column labels, and2916exactly one column of fixed width equal to the screen width. If the chosen2917application has a return value then this is returned by \texttt{BrowseGapData}, otherwise nothing is returned. The component \texttt{work.SpecialGrid} of the browse table is used to draw a border around the list of choices and2918another border around the footer. Only one mode is needed in which an entry is2919selected.29202921The code can be found in the file \texttt{app/gapdata.g} of the package. }2922292329242925\subsection{\textcolor{Chapter }{BrowseGapDataAdd}}2926\logpage{[ 6, 11, 2 ]}\nobreak2927\hyperdef{L}{X7FC24FCE7A0C6058}{}2928{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseGapDataAdd({\mdseries\slshape title, call, ret, documentation})\index{BrowseGapDataAdd@\texttt{BrowseGapDataAdd}}2929\label{BrowseGapDataAdd}2930}\hfill{\scriptsize (function)}}\\293129322933This function extends the list \texttt{BrowseData.GapDataOverviews} by a new entry. The list is used by \texttt{BrowseGapData} (\ref{BrowseGapData}).29342935\mbox{\texttt{\mdseries\slshape title}} must be a string of length at most $76$; it will be shown in the browse table that is opened by \texttt{BrowseGapData} (\ref{BrowseGapData}). \mbox{\texttt{\mdseries\slshape call}} must be a function that takes no arguments; it will be called when \mbox{\texttt{\mdseries\slshape title}} is ``clicked''. \mbox{\texttt{\mdseries\slshape ret}} must be \texttt{true} if \mbox{\texttt{\mdseries\slshape call}} has a return value and if \texttt{BrowseGapData} (\ref{BrowseGapData}) shall return this value, and \texttt{false} otherwise. \mbox{\texttt{\mdseries\slshape documentation}} must be a string that describes what happens when the function \mbox{\texttt{\mdseries\slshape call}} is called; it will be shown in the footer of the table opened by \texttt{BrowseGapData} (\ref{BrowseGapData}) when \mbox{\texttt{\mdseries\slshape title}} is selected. }29362937}293829392940\section{\textcolor{Chapter }{Navigating in a Directory Tree}}\label{sec:filetree}2941\logpage{[ 6, 12, 0 ]}2942\hyperdef{L}{X7E3FDA927E62D963}{}2943{2944A natural way to visualize the contents of a directory is via a tree whose2945leaves denote plain files, and the other vertices denote subdirectories. \textsf{Browse} provides a function based on \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) for displaying such trees; the leaves correspond to the data rows, and the2946other vertices correspond to category rows.29472948\subsection{\textcolor{Chapter }{BrowseDirectory}}2949\logpage{[ 6, 12, 1 ]}\nobreak2950\hyperdef{L}{X859682DE8397261E}{}2951{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseDirectory({\mdseries\slshape [dir]})\index{BrowseDirectory@\texttt{BrowseDirectory}}2952\label{BrowseDirectory}2953}\hfill{\scriptsize (function)}}\\2954\textbf{\indent Returns:\ }2955a list of the ``clicked'' filenames.2956295729582959If no argument is given then the contents of the current directory is shown,2960see \texttt{DirectoryCurrent} (\textbf{Reference: DirectoryCurrent}). If a directory object \mbox{\texttt{\mdseries\slshape dir}} (see \texttt{Directory} (\textbf{Reference: Directory})) is given as the only argument then the contents of this directory is shown;2961alternatively, \mbox{\texttt{\mdseries\slshape dir}} may also be a string which is then understood as a directory path.29622963The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available.296429652966\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]2967!gapprompt@gap>| !gapinput@n:= [ 14, 14, 14 ];; # ``do nothing''|2968!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation(|2969!gapprompt@>| !gapinput@ "q", # leave the selection|2970!gapprompt@>| !gapinput@ "X", # expand all categories|2971!gapprompt@>| !gapinput@ "/filetree", [ NCurses.keys.ENTER ], # search for "filetree"|2972!gapprompt@>| !gapinput@ n, "Q" ) ); # and quit|2973!gapprompt@gap>| !gapinput@dir:= DirectoriesPackageLibrary( "Browse", "" )[1];;|2974!gapprompt@gap>| !gapinput@if IsBound( BrowseDirectory ) then|2975!gapprompt@>| !gapinput@ BrowseDirectory( dir );|2976!gapprompt@>| !gapinput@ fi;|2977!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|2978\end{Verbatim}297929802981\emph{Implementation remarks}: The browse table has a static header, no footer, no row or column labels,2982and exactly one data column. The category rows are precomputed,2983i.{\nobreakspace}e., they do not arise from a table column. The tree structure2984is visualized via a special grid that is shown in the separator column in2985front of the table column; the width of this column is computed from the2986largest nesting depth of files. For technical reasons, category rows2987representing \emph{empty} directories are realized via ``dummy'' table rows; a special \texttt{ShowTables} function guarantees that these rows are always hidden.29882989When a data row or an entry in this row is selected, ``click'' adds the corresponding filename to the result list. Initially, the first row2990is selected. (So if you want to search in the whole tree then you should quit2991this selection by hitting the \textsc{q} key.)29922993The category hierarchy is computed using \texttt{DirectoryContents} (\textbf{Reference: DirectoryContents}).29942995This function is available only if the \textsf{GAP} package \textsf{IO} (see{\nobreakspace}\cite{IO}) is available, because the check for cycles uses the function \texttt{IO{\textunderscore}stat} (\textbf{IO: IO{\textunderscore}stat}) from this package.29962997The code can be found in the file \texttt{app/filetree.g} of the package. }29982999}300030013002\section{\textcolor{Chapter }{A Puzzle}}\label{sec:mnpuzzle}3003\logpage{[ 6, 13, 0 ]}3004\hyperdef{L}{X7FAE33037D09CC4E}{}3005{3006\index{game!A Puzzle} 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 by3007successively exchanging the empty square and a neighboring square such that in3008the end, the empty cell is again in the bottom right corner. \begin{center}3009\begin{tabular}{|c|c|c|c|}\hline3010$ 7$&3011$13$&3012$14$&3013$ 2$\\3014\hline3015$ 1$&3016$ 4$&3017$15$&3018$11$\\3019\hline3020$ 6$&3021$ 8$&3022$ 3$&3023$ 9$\\3024\hline3025$10$&3026$ 5$&3027$12$&3028$ $\\3029\hline3030\end{tabular}\\[2mm]3031\end{center}30323033The aim of the game is to order the numbered squares via these moves.30343035For the case $m = n = 4$, the puzzle is (erroneously?) known under the name ``Sam Loyd's Fifteen'', see{\nobreakspace}\cite{LoydFifteenWeb} and{\nobreakspace}\cite{HistGames} for more information and references.30363037\subsection{\textcolor{Chapter }{BrowsePuzzle}}3038\logpage{[ 6, 13, 1 ]}\nobreak3039\hyperdef{L}{X7EF5FCBD7DAFFAF3}{}3040{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowsePuzzle({\mdseries\slshape [m, n[, pi]]})\index{BrowsePuzzle@\texttt{BrowsePuzzle}}3041\label{BrowsePuzzle}3042}\hfill{\scriptsize (function)}}\\3043\textbf{\indent Returns:\ }3044a record describing the initial and final status of the puzzle.3045304630473048This function shows the rectangle in a window.30493050The arguments \mbox{\texttt{\mdseries\slshape m}} and \mbox{\texttt{\mdseries\slshape 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 via3051a permutation \mbox{\texttt{\mdseries\slshape pi}}, the default is a random element in the alternating group on the points $1, 2, \ldots, \mbox{\texttt{\mdseries\slshape m}} \mbox{\texttt{\mdseries\slshape n}} - 1$. (Note that the game has not always a solution.)30523053In any case, the empty cell is selected, and the selection can be moved to3054neighboring cells via the arrow keys, or to any place in the same row or3055column via a mouse click.30563057The 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 transpositions that were needed).3058\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]3059!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation(|3060!gapprompt@>| !gapinput@ BrowsePuzzleSolution.steps, "Q" ) );|3061!gapprompt@gap>| !gapinput@BrowsePuzzle( 4, 4, BrowsePuzzleSolution.init );;|3062!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|3063\end{Verbatim}3064An implementation using only mouse clicks but no key strokes is available in3065the \textsf{GAP} package \textsf{XGAP} (see{\nobreakspace}\cite{XGAP}).30663067\emph{Implementation remarks}: The game board is implemented via a browse table, without row and column3068labels, with static header, dynamic footer, and individual \texttt{minyx} function. Only one mode is needed in which one cell is selected, and besides3069the standard actions for quitting the table, asking for help, and saving the3070current window contents, only the four moves via the arrow keys and mouse3071clicks are admissible. \index{mouse events}30723073Some standard \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) functionality, such as scrolling, selecting, and searching, are not available3074in this application.30753076The code can be found in the file \texttt{app/puzzle.g} of the package. }30773078}307930803081\section{\textcolor{Chapter }{Peg Solitaire}}\label{sec:solitaire}3082\logpage{[ 6, 14, 0 ]}3083\hyperdef{L}{X7FFF943D78A403C9}{}3084{3085\index{game!Peg Solitaire} \index{solitaire game} Peg solitaire is a board game for one player. The game board consists of3086several holes some of which contain pegs. In each step of the game, one peg is3087moved horizontally or vertically to an empty hole at distance two, by jumping3088over a neighboring peg which is then removed from the board.308930903091\begin{center}3092\begin{tabular}{ccccccc}3093\cline{3-5}3094& & \multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3095\multicolumn{1}{|c|}{$\circ$} & & \\3096\cline{3-5}3097& & \multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3098\multicolumn{1}{|c|}{$\circ$} & & \\3099\hline3100\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3101\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3102\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3103\multicolumn{1}{|c|}{$\circ$} \\3104\hline3105\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3106\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{ } &3107\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3108\multicolumn{1}{|c|}{$\circ$} \\3109\hline3110\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3111\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3112\multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3113\multicolumn{1}{|c|}{$\circ$} \\3114\hline3115& & \multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3116\multicolumn{1}{|c|}{$\circ$} & & \\3117\cline{3-5}3118& & \multicolumn{1}{|c}{$\circ$} & \multicolumn{1}{|c}{$\circ$} &3119\multicolumn{1}{|c|}{$\circ$} & & \\3120\cline{3-5}3121\end{tabular}3122\end{center}312331243125We consider the game that in the beginning, exactly one hole is empty, and in3126the end, exactly one peg is left.31273128\subsection{\textcolor{Chapter }{PegSolitaire}}3129\logpage{[ 6, 14, 1 ]}\nobreak3130\hyperdef{L}{X82C8691380FCB674}{}3131{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{PegSolitaire({\mdseries\slshape [format, ][nrholes, ][twoModes]})\index{PegSolitaire@\texttt{PegSolitaire}}3132\label{PegSolitaire}3133}\hfill{\scriptsize (function)}}\\313431353136This function shows the game board in a window.31373138If the argument \mbox{\texttt{\mdseries\slshape format}} is one of the strings \texttt{"small"} or \texttt{"large"} then small or large pegs are shown, the default is \texttt{"small"}.31393140Three shapes of the game board are supported, with $33$, $37$, and $45$ holes, respectively; this number can be specified via the argument \mbox{\texttt{\mdseries\slshape 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 final3141peg 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 to3142be placed in the bottom right position.31433144If a Boolean \mbox{\texttt{\mdseries\slshape twoModes}} is entered as an argument then it determines whether a browse table with one3145or two modes is used; the default \texttt{false} yields a browse table with only one mode.31463147In any case, one cell of the board is selected, and the selection can be moved3148to neighboring cells via the arrow keys. A peg in the selected cell jumps over3149a neighboring peg to an adjacent hole via the \texttt{j} key followed by the appropriate arrow key.315031513152\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]3153!gapprompt@gap>| !gapinput@for n in [ 33, 37, 45 ] do|3154!gapprompt@>| !gapinput@ BrowseData.SetReplay( Concatenation(|3155!gapprompt@>| !gapinput@ PegSolitaireSolutions.( String( n ) ), "Q" ) );|3156!gapprompt@>| !gapinput@ PegSolitaire( n );|3157!gapprompt@>| !gapinput@ PegSolitaire( "large", n );|3158!gapprompt@>| !gapinput@ PegSolitaire( n, true );|3159!gapprompt@>| !gapinput@ PegSolitaire( "large", n, true );|3160!gapprompt@>| !gapinput@od;|3161!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|3162\end{Verbatim}316331643165For more information such as variations of the game and references,3166see{\nobreakspace}\cite{PegSolitaireWeb}. Also the solutions stored in the variable \texttt{PegSolitaireSolutions} have been taken from this web page.31673168\emph{Implementation remarks}: The game board is implemented via a browse table, without row and column3169labels, with static header, dynamic footer, and individual \texttt{minyx} function. In fact, two implementations are provided. The first one needs only3170one mode in which one cell is selected; moving the selection and jumping with3171the peg in the selected cell in one of the four directions are the supported3172user actions. The second implementation needs two modes, one for moving the3173selection and one for jumping.31743175Some standard \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) functionality, such as scrolling, selecting, and searching, are not available3176in this application.31773178The code can be found in the file \texttt{app/solitair.g} of the package. }31793180}318131823183\section{\textcolor{Chapter }{Rubik's Cube}}\label{sec:rubikscube}3184\logpage{[ 6, 15, 0 ]}3185\hyperdef{L}{X862CB73B7E0BE170}{}3186{3187\index{game!Rubik's Cube} We visualize the transformations of Rubik's magic cube in a model that is3188given by ``unfolding'' the faces and numbering them as follows.318931903191\begin{center}3192\begin{tabular}{cccccccccccc}3193\cline{4-6}3194& & & \multicolumn{1}{|c}{1} & \multicolumn{1}{c}{2} &3195\multicolumn{1}{c|}{3} & & & & & & \\3196& & & \multicolumn{1}{|c}{4} & \multicolumn{1}{c}{top} &3197\multicolumn{1}{c|}{5} & & & & & & \\3198& & & \multicolumn{1}{|c}{6} & \multicolumn{1}{c}{7} &3199\multicolumn{1}{c|}{8} & & & & & & \\3200\hline3201\multicolumn{1}{|c}{9} & \multicolumn{1}{c}{10} &3202\multicolumn{1}{c}{11} & \multicolumn{1}{|c}{17} &3203\multicolumn{1}{c}{18} & \multicolumn{1}{c}{19} &3204\multicolumn{1}{|c}{25} & \multicolumn{1}{c}{26} &3205\multicolumn{1}{c}{27} & \multicolumn{1}{|c}{33} &3206\multicolumn{1}{c}{34} & \multicolumn{1}{c|}{35} \\3207\multicolumn{1}{|c}{12} & \multicolumn{1}{c}{left} &3208\multicolumn{1}{c}{13} & \multicolumn{1}{|c}{20} &3209\multicolumn{1}{c}{front} & \multicolumn{1}{c}{21} &3210\multicolumn{1}{|c}{28} & \multicolumn{1}{c}{right} &3211\multicolumn{1}{c}{29} & \multicolumn{1}{|c}{36} &3212\multicolumn{1}{c}{back} & \multicolumn{1}{c|}{37} \\3213\multicolumn{1}{|c}{14} & \multicolumn{1}{c}{15} &3214\multicolumn{1}{c}{16} & \multicolumn{1}{|c}{22} &3215\multicolumn{1}{c}{23} & \multicolumn{1}{c}{24} &3216\multicolumn{1}{|c}{30} & \multicolumn{1}{c}{31} &3217\multicolumn{1}{c}{32} & \multicolumn{1}{|c}{38} &3218\multicolumn{1}{c}{39} & \multicolumn{1}{c|}{40} \\3219\hline3220& & & \multicolumn{1}{|c}{41} & \multicolumn{1}{c}{42} &3221\multicolumn{1}{c|}{43} & & & & & & \\3222& & & \multicolumn{1}{|c}{44} & \multicolumn{1}{c}{down} &3223\multicolumn{1}{c|}{45} & & & & & & \\3224& & & \multicolumn{1}{|c}{46} & \multicolumn{1}{c}{47} &3225\multicolumn{1}{c|}{48} & & & & & & \\3226\cline{4-6}3227\end{tabular}3228\end{center}322932303231Clockwise turns of the six layers (top, left, front, right, back, and down)3232are represented by the following permutations.323332343235\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]3236!gapprompt@gap>| !gapinput@cubegens := [|3237!gapprompt@>| !gapinput@ ( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19),|3238!gapprompt@>| !gapinput@ ( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35),|3239!gapprompt@>| !gapinput@ (17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11),|3240!gapprompt@>| !gapinput@ (25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24),|3241!gapprompt@>| !gapinput@ (33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27),|3242!gapprompt@>| !gapinput@ (41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)|3243!gapprompt@>| !gapinput@];;|3244\end{Verbatim}3245\textsf{GAP} computations analyzing this permutation group have been part of the3246announcements of \textsf{GAP}{\nobreakspace}3 releases. For a \textsf{GAP}{\nobreakspace}4 equivalent, see{\nobreakspace}\cite{RubiksCubeGAPWeb}. For more information and references (not \textsf{GAP} related) about Rubik's cube, see{\nobreakspace}\cite{RubiksCubeWeb}.32473248\subsection{\textcolor{Chapter }{BrowseRubiksCube}}3249\logpage{[ 6, 15, 1 ]}\nobreak3250\hyperdef{L}{X8100659E81FFE9A2}{}3251{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseRubiksCube({\mdseries\slshape [format, ][pi]})\index{BrowseRubiksCube@\texttt{BrowseRubiksCube}}3252\label{BrowseRubiksCube}3253}\hfill{\scriptsize (function)}}\\325432553256This function shows the model of the cube in a window.32573258If the argument \mbox{\texttt{\mdseries\slshape format}} is one of the strings \texttt{"small"} or \texttt{"large"} then small or large cells are shown, the default is \texttt{"small"}.32593260The argument \mbox{\texttt{\mdseries\slshape pi}} is the initial permutation of the faces, the default is a random permutation3261in the cube group, see{\nobreakspace} (\textbf{Reference: Random}).32623263Supported 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 letters3264for counter-clockwise turns. If the terminal supports colors, according to the3265global variable \texttt{NCurses.attrs.has{\textunderscore}colors} (\ref{NCurses.attrs.hascolors}), the input \textsc{s} switches between a screen that shows only the colors of the faces and a screen3266that shows the numbers; the color screen is the default.32673268The 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.)32693270In the following example, a word in terms of the generators is used to3271initialize the browse table, and then the letters in this word are used as a3272series of input steps, except that in between, the display is switched once3273from colors to numbers and back.327432753276\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]3277!gapprompt@gap>| !gapinput@choice:= List( [ 1 .. 30 ], i -> Random( [ 1 .. 6 ] ) );;|3278!gapprompt@gap>| !gapinput@input:= List( "tlfrbd", IntChar ){ choice };;|3279!gapprompt@gap>| !gapinput@BrowseData.SetReplay( Concatenation(|3280!gapprompt@>| !gapinput@ input{ [ 1 .. 20 ] },|3281!gapprompt@>| !gapinput@ "s", # switch to number display|3282!gapprompt@>| !gapinput@ input{ [ 21 .. 25 ] },|3283!gapprompt@>| !gapinput@ "s", # switch to color display|3284!gapprompt@>| !gapinput@ input{ [ 26 .. 30 ] },|3285!gapprompt@>| !gapinput@ "Q" ) );; # quit the browse table|3286!gapprompt@gap>| !gapinput@BrowseRubiksCube( Product( cubegens{ choice } ) );;|3287!gapprompt@gap>| !gapinput@BrowseRubiksCube( "large", Product( cubegens{ choice } ) );;|3288!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|3289\end{Verbatim}3290\emph{Implementation remarks}: The cube is implemented via a browse table, without row and column labels,3291with static header, dynamic footer, and individual \texttt{minyx} function. Only one mode is needed, and besides the standard actions for3292quitting the table, asking for help, and saving the current window contents,3293only the twelve moves and the switch between color and number display are3294admissible.32953296Switching 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}.32973298Row and column separators of the browse table are whitespace of height and3299width one. The separating lines are drawn using an individual \texttt{SpecialGrid} function in the browse table. Note that the relevant cells do not form a3300rectangular array.33013302Some standard \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) functionality, such as scrolling, selecting, and searching, are not available3303in this application.33043305The code can be found in the file \texttt{app/rubik.g} of the package. }33063307}330833093310\section{\textcolor{Chapter }{Changing Sides}}\label{sec:knight}3311\logpage{[ 6, 16, 0 ]}3312\hyperdef{L}{X7ADD618186541123}{}3313{3314\index{game!Changing Sides} We consider a $5$ by $5$ board of squares filled with two types of stones, as follows. The square in3315the middle is left empty.331633173318\begin{center}3319\begin{tabular}{|c|c|c|c|c|}3320\hline3321\rule[-6pt]{0pt}{18pt}$\times$&$\times$&$\times$&$\times$&$\times$\\3322\hline3323\rule[-6pt]{0pt}{18pt}$\circ$&$\times$&$\times$&$\times$&$\times$\\3324\hline3325\rule[-6pt]{0pt}{18pt}$\circ$&$\circ$&&$\times$&$\times$\\3326\hline3327\rule[-6pt]{0pt}{18pt}$\circ$&$\circ$&$\circ$&$\circ$&$\times$\\3328\hline3329\rule[-6pt]{0pt}{18pt}$\circ$&$\circ$&$\circ$&$\circ$&$\circ$\\3330\hline3331\end{tabular}3332\end{center}333333343335The aim of the game is to exchange the two types of stones via a sequence of3336single steps that move one stone to the empty position on the board. Only3337those 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.33383339This game has been part of the MacTutor system \cite{MacTutor}.33403341\subsection{\textcolor{Chapter }{BrowseChangeSides}}3342\logpage{[ 6, 16, 1 ]}\nobreak3343\hyperdef{L}{X7FCFC5858584F46E}{}3344{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseChangeSides({\mdseries\slshape })\index{BrowseChangeSides@\texttt{BrowseChangeSides}}3345\label{BrowseChangeSides}3346}\hfill{\scriptsize (function)}}\\334733483349This function shows the game board in a window.33503351Each move is encoded as a sequence of three arrow keys; there are $24$ admissible inputs.335233533354\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]3355!gapprompt@gap>| !gapinput@for entry in BrowseChangeSidesSolutions do|3356!gapprompt@>| !gapinput@ BrowseData.SetReplay( Concatenation( entry, "Q" ) );|3357!gapprompt@>| !gapinput@ BrowseChangeSides();|3358!gapprompt@>| !gapinput@od;|3359!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|3360\end{Verbatim}336133623363\emph{Implementation remarks}: The game board is implemented via a browse table, without row and column3364labels, with static header, dynamic footer, and individual \texttt{minyx} function. Only one mode is needed, and besides the standard actions for3365quitting the table, asking for help, and saving the current window contents,3366only moves via combinations of the four arrow keys are admissible.33673368The separating lines are drawn using an individual \texttt{SpecialGrid} function in the browse table.33693370Some standard \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) functionality, such as scrolling, selecting, and searching, are not available3371in this application.33723373The code can be found in the file \texttt{app/knight.g} of the package. }33743375}337633773378\section{\textcolor{Chapter }{Sudoku}}\label{sec:sudoku}3379\logpage{[ 6, 17, 0 ]}3380\hyperdef{L}{X7DDE46668321B5E9}{}3381{3382\index{game!Sudoku} 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 each3383row, 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.338433853386\begin{center}3387\setlength{\unitlength}{1.8ex}3388\begin{picture}(18,18)3389\multiput(0,0)(2,0){10}{\line(0,1){18}}3390\multiput(0,0)(0,2){10}{\line(1,0){18}}3391\linethickness{0.3ex}3392\multiput(0,0)(6,0){4}{\line(0,1){18}}3393\multiput(0,0)(0,6){4}{\line(1,0){18}}3394\put(13,17){\makebox(0,0){$5$}}3395\put( 3,15){\makebox(0,0){$1$}}3396\put( 5,15){\makebox(0,0){$5$}}3397\put( 7,15){\makebox(0,0){$4$}}3398\put(11,15){\makebox(0,0){$6$}}3399\put(15,15){\makebox(0,0){$2$}}3400\put( 1,13){\makebox(0,0){$9$}}3401\put( 9,13){\makebox(0,0){$5$}}3402\put(13,13){\makebox(0,0){$3$}}3403\put( 1,11){\makebox(0,0){$6$}}3404\put( 5,11){\makebox(0,0){$4$}}3405\put( 7, 9){\makebox(0,0){$8$}}3406\put( 1, 7){\makebox(0,0){$8$}}3407\put( 7, 7){\makebox(0,0){$9$}}3408\put(15, 7){\makebox(0,0){$5$}}3409\put(17, 7){\makebox(0,0){$3$}}3410\put(11, 5){\makebox(0,0){$5$}}3411\put( 3, 3){\makebox(0,0){$4$}}3412\put(11, 3){\makebox(0,0){$7$}}3413\put(17, 3){\makebox(0,0){$2$}}3414\put( 5, 1){\makebox(0,0){$9$}}3415\put( 7, 1){\makebox(0,0){$1$}}3416\put(13, 1){\makebox(0,0){$8$}}3417\end{picture}3418\end{center}34193420The \textsf{Browse} package contains functions to create, play and solve these games. There are3421basic command line functions for this, which we describe first, and there is a3422user interface \texttt{PlaySudoku} (\ref{PlaySudoku}) which is implemented using the generic browse functionality described in3423Chapter \ref{chap:browse-user}.34243425\subsection{\textcolor{Chapter }{Sudoku.Init}}3426\logpage{[ 6, 17, 1 ]}\nobreak3427\hyperdef{L}{X789D3D4C818F4BC2}{}3428{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Sudoku.Init({\mdseries\slshape [arg]})\index{Sudoku.Init@\texttt{Sudoku.Init}}3429\label{Sudoku.Init}3430}\hfill{\scriptsize (function)}}\\3431\textbf{\indent Returns:\ }3432A record describing a Sudoku board or \texttt{fail}.3433343434353436This function constructs a record describing a Sudoku game. This is used by3437the other functions described below. There a several possibilities for the3438argument \mbox{\texttt{\mdseries\slshape arg}}.3439\begin{description}3440\item[{\mbox{\texttt{\mdseries\slshape arg}} is a string}] The entries of a Sudoku board are numbered row-wise from 1 to 81. A board is3441encoded 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).3442Such strings can be used for \mbox{\texttt{\mdseries\slshape arg}}.3443\item[{\mbox{\texttt{\mdseries\slshape arg}} is a matrix}] A Sudoku board can also be encoded as a 9 by 9-matrix, that is a list of 93444lists of length 9, whose (i,j)-th entry is the (i,j)-th entry of the board as3445integer if it is not empty. Empty entries of the board correspond to unbound3446entries in the matrix.3447\item[{\mbox{\texttt{\mdseries\slshape arg}} is a list of integers}] Instead of the matrix just described the argument can also be given by the3448concatenation of the rows of the matrix (so, a list of integers and holes).3449\end{description}3450345134523453\begin{Verbatim}[commandchars=!@A,fontsize=\small,frame=single,label=Example]3454!gapprompt@gap>A !gapinput@game := Sudoku.Init(" 3 68 | 85 1 69| 97 53| 79 |\A3455!gapprompt@>A !gapinput@ 6 47 |45 2 |89 2 1 | 4 8 7 | ");;A3456\end{Verbatim}3457}3458345934603461\subsection{\textcolor{Chapter }{Sudoku.Place}}3462\logpage{[ 6, 17, 2 ]}\nobreak3463\hyperdef{L}{X86A5C6CE79DD67EE}{}3464{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Sudoku.Place({\mdseries\slshape game, i, n})\index{Sudoku.Place@\texttt{Sudoku.Place}}3465\label{Sudoku.Place}3466}\hfill{\scriptsize (function)}}\\3467\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Sudoku.Remove({\mdseries\slshape game, i})\index{Sudoku.Remove@\texttt{Sudoku.Remove}}3468\label{Sudoku.Remove}3469}\hfill{\scriptsize (function)}}\\3470\textbf{\indent Returns:\ }3471The changed \mbox{\texttt{\mdseries\slshape game}}.3472347334743475Here \mbox{\texttt{\mdseries\slshape game}} is a record describing a Sudoku board, as returned by \texttt{Sudoku.Init} (\ref{Sudoku.Init}). The argument \mbox{\texttt{\mdseries\slshape i}} is the number of an entry, counted row-wise from 1 to 81, and \mbox{\texttt{\mdseries\slshape n}} is an integer from 1 to 9 to be placed on the board. These functions change \mbox{\texttt{\mdseries\slshape game}}.34763477\texttt{Sudoku.Place} tries to place number \mbox{\texttt{\mdseries\slshape n}} on entry \mbox{\texttt{\mdseries\slshape i}}. It is an error if entry \mbox{\texttt{\mdseries\slshape i}} is not empty. The number is not placed if \mbox{\texttt{\mdseries\slshape n}} is already used in the row, column or subsquare of entry \mbox{\texttt{\mdseries\slshape i}}. In this case the component \texttt{game.impossible} is bound.34783479\texttt{Sudoku.Remove} tries to remove the number placed on position \mbox{\texttt{\mdseries\slshape i}} of the board. It does not change the board if entry \mbox{\texttt{\mdseries\slshape i}} is empty, or if entry \mbox{\texttt{\mdseries\slshape i}} was given when the board \mbox{\texttt{\mdseries\slshape game}} was created. In the latter case \texttt{game.impossible} is bound.348034813482\begin{Verbatim}[commandchars=!@A,fontsize=\small,frame=single,label=Example]3483!gapprompt@gap>A !gapinput@game := Sudoku.Init(" 3 68 | 85 1 69| 97 53| 79 |\A3484!gapprompt@>A !gapinput@ 6 47 |45 2 |89 2 1 | 4 8 7 | ");;A3485!gapprompt@gap>A !gapinput@Sudoku.Place(game, 1, 3);; # 3 is already in first rowA3486!gapprompt@gap>A !gapinput@IsBound(game.impossible);A3487true3488!gapprompt@gap>A !gapinput@Sudoku.Place(game, 1, 2);; # 2 is not in row, col or subsquareA3489!gapprompt@gap>A !gapinput@IsBound(game.impossible);A3490false3491\end{Verbatim}3492}3493349434953496\subsection{\textcolor{Chapter }{Sudoku.RandomGame}}3497\logpage{[ 6, 17, 3 ]}\nobreak3498\hyperdef{L}{X8401B31A879F9F9F}{}3499{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Sudoku.RandomGame({\mdseries\slshape [seed]})\index{Sudoku.RandomGame@\texttt{Sudoku.RandomGame}}3500\label{Sudoku.RandomGame}3501}\hfill{\scriptsize (function)}}\\3502\textbf{\indent Returns:\ }3503A pair \texttt{[str, seed]} of string and seed.3504350535063507The optional argument \mbox{\texttt{\mdseries\slshape seed}}, if given, must be an integer. If not given some random integer from the3508current \textsf{GAP} session is used. This function returns a random proper Sudoku game, where the3509board is described by a string \texttt{str}, as explained in \texttt{Sudoku.Init} (\ref{Sudoku.Init}). With the same \mbox{\texttt{\mdseries\slshape seed}} the same board is returned.35103511The games computed by this function have the property that after removing any3512given entry the puzzle does no longer have a unique solution.351335143515\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]3516!gapprompt@gap>| !gapinput@Sudoku.RandomGame(5833750);|3517[ " 1 2 43 2 68 72 8 6 2 1 9 8 8 3 9 \351847 3 7 18 ", 5833750 ]3519!gapprompt@gap>| !gapinput@last = Sudoku.RandomGame(last[2]);|3520true3521\end{Verbatim}3522}3523352435253526\subsection{\textcolor{Chapter }{Sudoku.SimpleDisplay}}3527\logpage{[ 6, 17, 4 ]}\nobreak3528\hyperdef{L}{X86917AC57C25A68F}{}3529{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Sudoku.SimpleDisplay({\mdseries\slshape game})\index{Sudoku.SimpleDisplay@\texttt{Sudoku.SimpleDisplay}}3530\label{Sudoku.SimpleDisplay}3531}\hfill{\scriptsize (function)}}\\353235333534Displays a Sudoku board on the terminal. (But see \texttt{PlaySudoku} (\ref{PlaySudoku}) for a fancier interface.)353535363537\begin{Verbatim}[commandchars=!@A,fontsize=\small,frame=single,label=Example]3538!gapprompt@gap>A !gapinput@game := Sudoku.Init(" 3 68 | 85 1 69| 97 53| 79 |\A3539!gapprompt@>A !gapinput@ 6 47 |45 2 |89 2 1 | 4 8 7 | ");;A3540!gapprompt@gap>A !gapinput@Sudoku.SimpleDisplay(game);A35413 | 6|8354285| 1| 6935439|7 | 533544-----------3545| |7935466 | 47|354745 | 2 |3548-----------354989 | 2| 135504 | 8| 73551| |3552\end{Verbatim}3553}3554355535563557\subsection{\textcolor{Chapter }{Sudoku.DisplayString}}3558\logpage{[ 6, 17, 5 ]}\nobreak3559\hyperdef{L}{X81F98C6C7C8415AB}{}3560{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Sudoku.DisplayString({\mdseries\slshape game})\index{Sudoku.DisplayString@\texttt{Sudoku.DisplayString}}3561\label{Sudoku.DisplayString}3562}\hfill{\scriptsize (function)}}\\356335643565The string returned by this function can be used to display the Sudoku board \mbox{\texttt{\mdseries\slshape game}} on the terminal, using \texttt{PrintFormattedString} (\textbf{GAPDoc: PrintFormattedString}). The result depends on the value of \texttt{GAPInfo.TermEncoding}.356635673568\begin{Verbatim}[commandchars=!@A,fontsize=\small,frame=single,label=Example]3569!gapprompt@gap>A !gapinput@game := Sudoku.Init(" 3 68 | 85 1 69| 97 53| 79 |\A3570!gapprompt@>A !gapinput@ 6 47 |45 2 |89 2 1 | 4 8 7 | ");;A3571!gapprompt@gap>A !gapinput@str:= Sudoku.DisplayString( game );;A3572!gapprompt@gap>A !gapinput@PrintFormattedString( str );A3573+===+===+===+===+===+===+===+===+===+3574| | 3 | | | | 6 | 8 | | |3575+---+---+---+---+---+---+---+---+---+3576| | 8 | 5 | | | 1 | | 6 | 9 |3577+---+---+---+---+---+---+---+---+---+3578| | | 9 | 7 | | | | 5 | 3 |3579+===+===+===+===+===+===+===+===+===+3580| | | | | | | 7 | 9 | |3581+---+---+---+---+---+---+---+---+---+3582| | 6 | | | 4 | 7 | | | |3583+---+---+---+---+---+---+---+---+---+3584| 4 | 5 | | | 2 | | | | |3585+===+===+===+===+===+===+===+===+===+3586| 8 | 9 | | | | 2 | | 1 | |3587+---+---+---+---+---+---+---+---+---+3588| | 4 | | | | 8 | | 7 | |3589+---+---+---+---+---+---+---+---+---+3590| | | | | | | | | |3591+===+===+===+===+===+===+===+===+===+3592\end{Verbatim}3593}3594359535963597\subsection{\textcolor{Chapter }{Sudoku.OneSolution}}3598\logpage{[ 6, 17, 6 ]}\nobreak3599\hyperdef{L}{X7C73C6D08293B3B8}{}3600{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Sudoku.OneSolution({\mdseries\slshape game})\index{Sudoku.OneSolution@\texttt{Sudoku.OneSolution}}3601\label{Sudoku.OneSolution}3602}\hfill{\scriptsize (function)}}\\3603\textbf{\indent Returns:\ }3604A completed Sudoku board that solves \mbox{\texttt{\mdseries\slshape game}}, or \texttt{fail}.3605360636073608Here \mbox{\texttt{\mdseries\slshape game}} must be a Sudoku board as returned by \texttt{Sudoku.Init} (\ref{Sudoku.Init}). It is not necessary that \mbox{\texttt{\mdseries\slshape game}} describes a proper Sudoku game (has a unique solution). It may have several3609solutions, then one random solution is returned. Or it may have no solution,3610then \texttt{fail} is returned.361136123613\begin{Verbatim}[commandchars=!@A,fontsize=\small,frame=single,label=Example]3614!gapprompt@gap>A !gapinput@Sudoku.SimpleDisplay(Sudoku.OneSolution(Sudoku.Init(" 3")));A3615493|876|2513616861|542|7393617527|193|6483618-----------3619942|618|5733620156|739|4823621738|425|9163622-----------3623289|354|1673624375|961|8243625614|287|3953626\end{Verbatim}3627}3628362936303631\subsection{\textcolor{Chapter }{Sudoku.UniqueSolution}}3632\logpage{[ 6, 17, 7 ]}\nobreak3633\hyperdef{L}{X865DDBDC7E16217F}{}3634{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Sudoku.UniqueSolution({\mdseries\slshape game})\index{Sudoku.UniqueSolution@\texttt{Sudoku.UniqueSolution}}3635\label{Sudoku.UniqueSolution}3636}\hfill{\scriptsize (function)}}\\3637\textbf{\indent Returns:\ }3638A completed Sudoku board that solves \mbox{\texttt{\mdseries\slshape game}}, or \texttt{false}, or \texttt{fail}.3639364036413642Here \mbox{\texttt{\mdseries\slshape game}} must be a Sudoku board as returned by \texttt{Sudoku.Init} (\ref{Sudoku.Init}). It is not necessary that \mbox{\texttt{\mdseries\slshape 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.364336443645\begin{Verbatim}[commandchars=!@A,fontsize=\small,frame=single,label=Example]3646!gapprompt@gap>A !gapinput@s := " 5 | 154 6 2 |9 5 3 |6 4 | 8 |8 9 53\A3647!gapprompt@>A !gapinput@| 5 | 4 7 2| 91 8 ";;A3648!gapprompt@gap>A !gapinput@sol := Sudoku.UniqueSolution(Sudoku.Init(s));;A3649!gapprompt@gap>A !gapinput@Sudoku.SimpleDisplay(sol);A3650438|219|5763651715|436|9283652962|758|3143653-----------3654694|573|2813655153|862|7493656827|941|6533657-----------3658281|695|4373659546|387|1923660379|124|8653661\end{Verbatim}3662}3663366436653666\subsection{\textcolor{Chapter }{PlaySudoku}}3667\logpage{[ 6, 17, 8 ]}\nobreak3668\hyperdef{L}{X7D19224478E86BB4}{}3669{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{PlaySudoku({\mdseries\slshape [arg]})\index{PlaySudoku@\texttt{PlaySudoku}}3670\label{PlaySudoku}3671}\hfill{\scriptsize (function)}}\\3672\textbf{\indent Returns:\ }3673A record describing the latest status of a Sudoku board.3674367536763677This function allows one to solve Sudoku puzzles interactively. There are3678several possibilities for the optional argument \mbox{\texttt{\mdseries\slshape arg}}. It can either be a string, matrix or list of holes and integers as described3679in \texttt{Sudoku.Init} (\ref{Sudoku.Init}), or a board as returned by \texttt{Sudoku.Init} (\ref{Sudoku.Init}). Furthermore \mbox{\texttt{\mdseries\slshape 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.36803681The usage of this function is self-explanatory, pressing the \textsc{?} key displays a help screen. Here, we mention two keys with a particular3682action: Pressing the \textsc{h} key you get a hint, either an empty entry is filled or the program tells you3683that there is no solution (so you must delete some entries and try others).3684Pressing the \textsc{s} key the puzzle is solved by the program or it tells you that there is no or no3685unique solution.36863687\emph{Implementation remarks}: The game board is implemented via a browse table, without row and column3688labels, with static header, dynamic footer, and individual \texttt{minyx} function. Two modes are supported, with the standard actions for quitting the3689table and asking for help; one cell is selected in each mode. The first mode3690provides actions for moving the selected cell via arrow keys, for changing the3691value in the selected cell, for getting a hint or the (unique) solution.3692(Initial entries of the matrix cannot be changed via user input. They are3693shown in boldface.) The second mode serves for error handling: When the user3694enters an invalid number, i.{\nobreakspace}e., a number that occurs already in3695the current row or column or subsquare, then the application switches to this3696mode, which causes that a message is shown in the footer, and the invalid3697entry is shown in red and blinking; similarly, error mode is entered if a hint3698or solution does not exist.36993700The separating lines are drawn using an individual \texttt{SpecialGrid} function in the browse table, since they cannot be specified within the3701generic browse table functions.37023703Some standard \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) functionality, such as scrolling, selecting, and searching, are not available3704in this application.37053706The code can be found in the file \texttt{app/sudoku.g} of the package. }3707370837093710\subsection{\textcolor{Chapter }{Sudoku.HTMLGame}}3711\logpage{[ 6, 17, 9 ]}\nobreak3712\hyperdef{L}{X804D66D67B908F30}{}3713{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Sudoku.HTMLGame({\mdseries\slshape game})\index{Sudoku.HTMLGame@\texttt{Sudoku.HTMLGame}}3714\label{Sudoku.HTMLGame}3715}\hfill{\scriptsize (function)}}\\3716\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{Sudoku.LaTeXGame({\mdseries\slshape game})\index{Sudoku.LaTeXGame@\texttt{Sudoku.LaTeXGame}}3717\label{Sudoku.LaTeXGame}3718}\hfill{\scriptsize (function)}}\\3719\textbf{\indent Returns:\ }3720A string with HTML or {\LaTeX} code, respectively.3721372237233724The argument of these functions is a record describing a Sudoku game. These3725functions return code for including the current status of the board into a3726webpage or a {\LaTeX} document. }37273728}372937303731\section{\textcolor{Chapter }{Utility for \textsf{GAP} Demos}}\label{sec:rldemo}3732\logpage{[ 6, 18, 0 ]}3733\hyperdef{L}{X7BCE1AE37EFCE91D}{}3734{3735This application can be used with \textsf{GAP} if the user interface has \texttt{readline} support. The purpose is to simplify the typing during a demonstration of \textsf{GAP} commands.37363737The file format to specify \textsf{GAP} code for a demonstration is very simple: it contains blocks of lines with \textsf{GAP} input, separated by lines starting with a \texttt{\%} character. Comments in such a file can be added to one or several lines3738starting with \texttt{\%}. Here is the content of an example file \texttt{demo.demo}:373937403741\begin{verbatim}3742% Add comments after a % character at the beginning of a line.3743% A comment can have several lines.3744% Here is a multi-line input block:3745g := MathieuGroup(11);;3746cl := ConjugacyClasses(g);3747% Calling a help page3748?MathieuGroup3749% The next line contains a comment in the GAP session:3750a := 12;; b := 13;; # assign two numbers3751%3752a*b;3753%3754\end{verbatim}3755A demonstration can be loaded into a \textsf{GAP} session with the command37563757\subsection{\textcolor{Chapter }{LoadDemoFile}}3758\logpage{[ 6, 18, 1 ]}\nobreak3759\hyperdef{L}{X80F418C5835C62BA}{}3760{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{LoadDemoFile({\mdseries\slshape demoname, demofile[, singleline]})\index{LoadDemoFile@\texttt{LoadDemoFile}}3761\label{LoadDemoFile}3762}\hfill{\scriptsize (function)}}\\3763\textbf{\indent Returns:\ }3764Nothing.3765376637673768This function loads a demo file in the format described above. The argument \mbox{\texttt{\mdseries\slshape demoname}} is a string containing a name for the demo, and \mbox{\texttt{\mdseries\slshape demofile}} is the file name containing the demo.37693770If the optional argument \mbox{\texttt{\mdseries\slshape singleline}} is given and its value is \texttt{true}, the demo behaves differently with respect to input blocks that span several3771lines. By default full blocks are treated as a single input line for \texttt{readline} (maybe spanning several physical lines in the terminal). If \mbox{\texttt{\mdseries\slshape singleline}} is \texttt{true} then all input lines of a block except the last one are sent to \textsf{GAP} and are evaluated automatically before the last line of the block is3772displayed.3773\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]3774!gapprompt@gap>| !gapinput@dirs := DirectoriesPackageLibrary("Browse");;|3775!gapprompt@gap>| !gapinput@demofile := Filename(dirs, "../app/demo.demo");;|3776!gapprompt@gap>| !gapinput@LoadDemoFile("My first demo", demofile);|3777!gapprompt@gap>| !gapinput@LoadDemoFile("My first demo (single lines)", demofile, true);|3778\end{Verbatim}3779}37803781Many demos can be loaded at the same time. They are used with the \textsc{PageDown} and \textsc{PageUp} keys.37823783The \textsc{PageUp} key leads to a (Browse) menu which allows one to choose a demo to start (if3784several are loaded), to stop a demo or to move to another position in the3785current demo (e.g., to go back to a previous point or to skip part of a demo).37863787The next input block of the current demo is copied into the current input line3788of the \textsf{GAP} session by pressing the \textsc{PageDown} key. This line is not yet sent to \textsf{GAP}, use the \textsc{Return} key if you want to evaluate the input. (You can also still edit the input line3789before evaluation.)37903791So, in the simplest case a demo can be done by just pressing \textsc{PageDown} and \textsc{Return} in turns. But it is always possible to type extra input during a demo by hand3792or to change the input lines from the demo file before evaluation. It is no3793problem if commands are interrupted by \textsc{Ctrl-C}. During a demo you are in a normal \textsf{GAP} session, this application only saves you some typing. The input lines from the3794demo are put into the history of the session as if they were typed by hand.37953796Try it yourself with the two demos loaded in the example. This also shows the3797different behaviour between default and single line mode. }37983799}3800380138023803\appendix380438053806\chapter{\textcolor{Chapter }{Some Tools for Database Handling}}\label{chap:brdbattr}3807\logpage{[ "A", 0, 0 ]}3808\hyperdef{L}{X85D4199E82A7DFA5}{}3809{3810Two aims of the tools described in this appendix are3811\begin{itemize}3812\item speeding up selection functions such as \texttt{AllCharacterTableNames} (\textbf{CTblLib: AllCharacterTableNames}) for certain data libraries of \textsf{GAP} (with not too many entries), in the sense that users can extend the list of3813attributes that are treated in a special way3814\item and a programmatic extension for rendering overviews of information about the3815contents of databases, using \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}).3816\end{itemize}381738183819The \textsf{GAP} objects introduced for that are \emph{database id enumerators} (see \ref{subsect:dbidenum}) and \emph{database attributes} (see \ref{subsect:dbattr}).38203821Contrary to the individual interfaces to the \textsf{GAP} manuals (see Section \ref{sec:manualdisp}), the \textsf{GAP} bibliography (see Section \ref{sec:gapbibl}), and the overviews of \textsf{GAP} packages, \textsf{GAP} methods, and Conway polynomials available in \textsf{GAP} (see Section \ref{sec:datadisp}), the approach that will be described here assumes a special way to access3822database entries. Thus it depends on the structure of a given database whether3823the tools described here are useful, or whether an individual interface fits3824better. Perhaps the example shown in Section \ref{sect:dbidenumxpl} gives an impression what is possible.3825\section{\textcolor{Chapter }{\textsf{GAP} Objects for Database Handling}}\label{sect:dbobjects}3826\logpage{[ "A", 1, 0 ]}3827\hyperdef{L}{X7A0B84C37CB9DFA3}{}3828{38293830\subsection{\textcolor{Chapter }{Database Id Enumerators}}\label{subsect:dbidenum}3831\logpage{[ "A", 1, 1 ]}3832\hyperdef{L}{X7999CF7F79ACA240}{}3833{3834A \emph{database id enumerator} is a record \mbox{\texttt{\mdseries\slshape r}} with at least the following components.383538363837\begin{description}3838\item[{\texttt{identifiers}}] a list of ``identifiers'' of the database entries, which provides a bijection with these entries,3839\item[{\texttt{entry}}] a function that takes \mbox{\texttt{\mdseries\slshape r}} and an entry in the \texttt{identifiers} list, and returns the corresponding database entry,3840\item[{\texttt{attributes}}] the record whose components are the database attribute records (see Section \ref{subsect:dbattr}) for \mbox{\texttt{\mdseries\slshape r}}; this components is automatically initialized when \mbox{\texttt{\mdseries\slshape r}} is created with \texttt{DatabaseIdEnumerator} (\ref{DatabaseIdEnumerator}); database attributes can be entered with \texttt{DatabaseAttributeAdd} (\ref{DatabaseAttributeAdd}).3841\end{description}384238433844If the \texttt{identifiers} list may change over the time (because the database is extended or corrected)3845then the following components are supported. They are used by \texttt{DatabaseIdEnumeratorUpdate} (\ref{DatabaseIdEnumeratorUpdate}).384638473848\begin{description}3849\item[{\texttt{version}}] a \textsf{GAP} object that describes the version of the \texttt{identifiers} component, this can be for example a string describing the time of the last3850change (this time need not coincide with the time of the last update); the3851default value (useful only for the case that the \texttt{identifiers} component is never changed) is an empty string,3852\item[{\texttt{update}}] a function that takes \mbox{\texttt{\mdseries\slshape r}} as its argument, replaces its \texttt{identifiers} and \texttt{version} values by up-to-date versions if necessary (for example by downloading the3853data), and returns \texttt{true} or \texttt{false}, depending on whether the update process was successful or not; the default3854value is \texttt{ReturnTrue} (\textbf{Reference: ReturnTrue}),3855\end{description}385638573858The following component is optional.385938603861\begin{description}3862\item[{\texttt{isSorted}}] \texttt{true} means that the \texttt{identifiers} list is sorted w.r.t. \textsf{GAP}'s ordering \texttt{\texttt{\symbol{92}}{\textless}}; the default is \texttt{false}.3863\end{description}386438653866The idea behind database id enumerator objects is that such an object defines3867the set of data covered by database attributes (see Section \ref{subsect:dbattr}), it provides the mapping between identifiers and the actual entries of the3868database, and it defines when precomputed data of database attributes are3869outdated. }387038713872\subsection{\textcolor{Chapter }{Database Attributes}}\label{subsect:dbattr}3873\logpage{[ "A", 1, 2 ]}3874\hyperdef{L}{X7D2804F97EE18BA5}{}3875{3876A \emph{database attribute} is a record \mbox{\texttt{\mdseries\slshape a}} whose components belong to the aspects of \emph{defining} the attribute, \emph{accessing} the attribute's data, \emph{computing} (and recomputing) data, \emph{storing} data on files, and \emph{checking} data. (Additional parameters used for creating browse table columns from3877database attributes are described in Section \ref{subsect:attr-browse-comp}.)38783879The following components are \emph{defining}, except \texttt{description} they are mandatory.388038813882\begin{description}3883\item[{\texttt{idenumerator}}] the database id enumerator to which the attribute \mbox{\texttt{\mdseries\slshape a}} is related,3884\item[{\texttt{identifier}}] a string that identifies \mbox{\texttt{\mdseries\slshape a}} among all database attributes for the underlying database id enumerator (this3885is used by \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}) and when the data of \mbox{\texttt{\mdseries\slshape a}} are entered with \texttt{DatabaseAttributeSetData} (\ref{DatabaseAttributeSetData}), for example when precomputed values are read from a file),3886\item[{\texttt{description}}] a string that describes the attribute in human readable form (currently just3887for convenience, the default is an empty string).3888\end{description}388938903891The following components are used for \emph{accessing} data. Except \texttt{type}, they are optional, but enough information must be provided in order to make3892the database attribute meaningful. If an individual \texttt{attributeValue} function is available then this function decides what is needed; for the3893default function \texttt{DatabaseAttributeValueDefault} (\ref{DatabaseAttributeValueDefault}), at least one of the components \texttt{name}, \texttt{data}, \texttt{datafile} must be bound (see \texttt{DatabaseAttributeValueDefault} (\ref{DatabaseAttributeValueDefault}) for the behaviour in this case).389438953896\begin{description}3897\item[{\texttt{type}}] one of the strings \texttt{"values"} or \texttt{"pairs"}; the format of the component \texttt{data} is different for these cases,3898\item[{\texttt{name}}] if bound, a string that is the name of a \textsf{GAP} function such that the database attribute encodes the values of this function3899for the database entries; besides the computation of attribute values on3900demand (see \texttt{DatabaseAttributeValueDefault} (\ref{DatabaseAttributeValueDefault})), this component can be used by selection functions such as \texttt{OneCharacterTableName} (\textbf{CTblLib: OneCharacterTableName}) or \texttt{AllCharacterTableNames} (\textbf{CTblLib: AllCharacterTableNames}), which take \textsf{GAP} functions and prescribed return values as their arguments {\textendash}of3901course these functions must then be prepared to deal with database attributes.3902\item[{\texttt{data}}] if bound, the data for this attribute; if the component \texttt{type} has the value \texttt{"values"} then the value is a list, where the entry at position \mbox{\texttt{\mdseries\slshape i}}, if bound, belongs to the \mbox{\texttt{\mdseries\slshape i}}-th entry of the \texttt{identifiers} list of \texttt{idenumerator}; if \texttt{type} is \texttt{"pairs"} then the value is a record with the components \texttt{automatic} and \texttt{nonautomatic}, and the values of these components are lists such that each entry is a list3903of length two whose first entry occurs in the \texttt{identifiers} list of \mbox{\texttt{\mdseries\slshape a}}\texttt{.idenumerator} and whose second entry encodes the corresponding attribute value,3904\item[{\texttt{datafile}}] if bound, the absolute name of a file that contains the data for this3905attribute,3906\item[{\texttt{attributeValue}}] a function that takes \mbox{\texttt{\mdseries\slshape a}} and an \texttt{identifiers} entry of its \texttt{idenumerator} value, and returns the attribute value for this identifier; typically this is \emph{not} a table cell data object that can be shown in a browse table, cf. the \texttt{viewValue} component; the default is \texttt{DatabaseAttributeValueDefault} (\ref{DatabaseAttributeValueDefault}) (Note that using individual \texttt{attributeValue} functions, one can deal with database attributes independent of actually3907stored data, for example without precomputed values, such that the values are3908computed on demand and afterwards are cached.),3909\item[{\texttt{dataDefault}}] a \textsf{GAP} object that is regarded as the attribute value for those database entries for3910which \texttt{data}, \texttt{datafile}, and \texttt{name} do not provide values; the default value is an empty string \texttt{""},3911\item[{\texttt{eval}}] if this component is bound, the value is assumed to be a function that takes \mbox{\texttt{\mdseries\slshape a}} and a value from its \texttt{data} component, and returns the actual attribute value; this can be useful if one3912does not want to create all attribute values in advance, because this would be3913space or time consuming; another possible aspect of the \texttt{eval} component is that it may be used to strip off comments that are perhaps3914contained in \texttt{data} entries,3915\item[{\texttt{isSorted}}] if this component is bound to \texttt{true} and if \texttt{type} is \texttt{"pairs"} then it is assumed that the two lists in the \texttt{data} record of \mbox{\texttt{\mdseries\slshape a}} are sorted w.r.t. \textsf{GAP}'s ordering \texttt{\texttt{\symbol{92}}{\textless}}; the default is \texttt{false},3916\end{description}391739183919The following optional components are needed for \emph{computing} (or recomputing) data with \texttt{DatabaseAttributeCompute} (\ref{DatabaseAttributeCompute}). This is useful mainly for databases which can change over the time.392039213922\begin{description}3923\item[{\texttt{version}}] the \textsf{GAP} object that is the \texttt{version} component of the \texttt{idenumerator} component at the time when the stored data were entered; this value is used by \texttt{DatabaseIdEnumeratorUpdate} (\ref{DatabaseIdEnumeratorUpdate}) for deciding whether the attribute values are outdated; if \mbox{\texttt{\mdseries\slshape a}}\texttt{.datafile} is bound then it is assumed that the \texttt{version} component is set when this file is read, for example in the function \texttt{DatabaseAttributeSetData} (\ref{DatabaseAttributeSetData}),3924\item[{\texttt{update}}] a function that takes \mbox{\texttt{\mdseries\slshape a}} as its argument, adjusts its data components to the current values of \mbox{\texttt{\mdseries\slshape a}}\texttt{.dbidenum} if necessary, sets the \texttt{version} component to that of \mbox{\texttt{\mdseries\slshape a}}\texttt{.dbidenum}, and returns \texttt{true} or \texttt{false}, depending on whether the update process was successful or not; the default3925value is \texttt{ReturnTrue} (\textbf{Reference: ReturnTrue}),3926\item[{\texttt{neededAttributes}}] a list of attribute \texttt{identifier} strings such that the values of these attributes are needed in the3927computations for the current one, and therefore these should be3928updated/recomputed in advance; it is assumed that the \texttt{neededAttributes} components of all database attributes of \mbox{\texttt{\mdseries\slshape a}}\texttt{.idenumerator} define a partial ordering; the default is an empty list,3929\item[{\texttt{prepareAttributeComputation}}] a function with argument \mbox{\texttt{\mdseries\slshape a}} that must be called before the computations for the current attribute are3930started; the default value is \texttt{ReturnTrue} (\textbf{Reference: ReturnTrue}),3931\item[{\texttt{cleanupAfterAttibuteComputation}}] a function with argument \mbox{\texttt{\mdseries\slshape a}} that must be called after the computations for the current attribute are3932finished; the default value is \texttt{ReturnTrue} (\textbf{Reference: ReturnTrue}), and3933\item[{\texttt{create}}] a function that takes a database attribute and an entry in the \texttt{identifiers} list of its database id enumerator, and returns either the entry that shall be3934stored in the \texttt{data} component, as the value for the given identifier (if this value shall be3935stored in the \texttt{data} component of \mbox{\texttt{\mdseries\slshape a}}) or the \texttt{dataDefault} component of \mbox{\texttt{\mdseries\slshape a}} (if this value shall \emph{not} be stored); in order to get the actual attribute value, the \texttt{eval} function of \mbox{\texttt{\mdseries\slshape a}}, if bound, must be called with the return value. This function may assume3936that the \texttt{prepareAttributeComputation} function has been called in advance, and that the \texttt{cleanupAfterAttibuteComputation} function will be called later. The \texttt{create} function is \emph{not} intended to compute an individual attribute value on demand, use a \texttt{name} component for that. (A stored \texttt{name} function is used to provide a default for the \texttt{create} function; without \texttt{name} component, there is no default for \texttt{create}.)3937\end{description}393839393940The following optional component is needed for \emph{storing} data on files.39413942394339443945\begin{description}3946\item[{\texttt{string}}] if bound, a function that takes the pair consisting of an identifier and the3947return value of the \texttt{create} function for this identifier, and returns a string that shall represent this3948value when the data are printed to a file; the default function returns the \texttt{String} (\textbf{Reference: String}) value of the second argument.3949\end{description}395039513952The following optional component is needed for \emph{checking} stored data.395339543955\begin{description}3956\item[{\texttt{check}}] a function that takes a string that occurs in the \texttt{identifiers} list of the \texttt{idenumerator} record, and returns \texttt{true} if the attribute value stored for this string is reasonable, and something3957different from \texttt{true} if an error was detected. (One could argue that these tests can be performed3958also when the values are computed, but consistency checks may involve several3959entries; besides that, checking may be cheaper than recomputing.)3960\end{description}3961}396239633964\subsection{\textcolor{Chapter }{How to Deal with Database Id Enumerators and Database Attributes}}\label{subsect:db-how-to-use}3965\logpage{[ "A", 1, 3 ]}3966\hyperdef{L}{X7B3913E28493563F}{}3967{3968The idea is to start with a database id enumerator (see \ref{subsect:dbidenum}), constructed with \texttt{DatabaseIdEnumerator} (\ref{DatabaseIdEnumerator}), and to define database attributes for it (see \ref{subsect:dbattr}), using \texttt{DatabaseAttributeAdd} (\ref{DatabaseAttributeAdd}). The attribute values can be precomputed and stored on files, or they are3969computed when the attribute gets defined, or they are computed on demand.39703971The function \texttt{DatabaseAttributeCompute} (\ref{DatabaseAttributeCompute}) can be used to ``refresh'' the attribute values, that is, all values or selected values can be3972recomputed; this can be necessary for example when the underlying database id3973enumerator gets extended.39743975In data files, the function \texttt{DatabaseAttributeSetData} (\ref{DatabaseAttributeSetData}) can be used to fill the \texttt{data} component of the attribute. }3976397739783979\subsection{\textcolor{Chapter }{DatabaseIdEnumerator}}3980\logpage{[ "A", 1, 4 ]}\nobreak3981\hyperdef{L}{X7AE32F217CF16EDF}{}3982{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DatabaseIdEnumerator({\mdseries\slshape arec})\index{DatabaseIdEnumerator@\texttt{DatabaseIdEnumerator}}3983\label{DatabaseIdEnumerator}3984}\hfill{\scriptsize (function)}}\\3985\textbf{\indent Returns:\ }3986a shallow copy of the record \mbox{\texttt{\mdseries\slshape arec}}, extended by default values.3987398839893990For a record \mbox{\texttt{\mdseries\slshape arec}}, \texttt{DatabaseIdEnumerator} checks whether the mandatory components of a database id enumerator (see3991Section \ref{subsect:dbidenum}) are present, initializes the \texttt{attributes} component, sets the defaults for unbound optional components (see \ref{subsect:attr-browse-comp}), and returns the resulting record.39923993A special database attribute (see Section \ref{subsect:dbattr}) with \texttt{identifier} value \texttt{"self"} is constructed automatically for the returned record by \texttt{DatabaseIdEnumerator}; its \texttt{attributeValue} function simply returns its second argument (the identifier). The optional3994components of this attribute are derived from components of the database id3995enumerator, so these components (see \ref{subsect:attr-browse-comp}) are supported for \mbox{\texttt{\mdseries\slshape arec}}. A typical use of the \texttt{"self"} attribute is to provide the first column in browse tables constructed by \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}). }3996399739983999\subsection{\textcolor{Chapter }{DatabaseAttributeAdd}}4000\logpage{[ "A", 1, 5 ]}\nobreak4001\hyperdef{L}{X8573522782D939FE}{}4002{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DatabaseAttributeAdd({\mdseries\slshape dbidenum, arec})\index{DatabaseAttributeAdd@\texttt{DatabaseAttributeAdd}}4003\label{DatabaseAttributeAdd}4004}\hfill{\scriptsize (function)}}\\400540064007For a database id enumerator \mbox{\texttt{\mdseries\slshape dbidenum}} and a record \mbox{\texttt{\mdseries\slshape arec}}, \texttt{DatabaseAttributeAdd} checks whether the mandatory components of a database attribute, except \texttt{idenumerator}, are present in \mbox{\texttt{\mdseries\slshape arec}} (see Section \ref{subsect:dbattr}), sets the \texttt{idenumerator} component, and sets the defaults for unbound optional components (see \ref{subsect:attr-browse-comp}). }4008400940104011\subsection{\textcolor{Chapter }{DatabaseAttributeValueDefault}}4012\logpage{[ "A", 1, 6 ]}\nobreak4013\hyperdef{L}{X7C8DB23E79567A60}{}4014{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DatabaseAttributeValueDefault({\mdseries\slshape attr, id})\index{DatabaseAttributeValueDefault@\texttt{DatabaseAttributeValueDefault}}4015\label{DatabaseAttributeValueDefault}4016}\hfill{\scriptsize (function)}}\\4017\textbf{\indent Returns:\ }4018the value of the database attribute \mbox{\texttt{\mdseries\slshape attr}} at \mbox{\texttt{\mdseries\slshape id}}.4019402040214022For a database attribute \mbox{\texttt{\mdseries\slshape attr}} and an entry \mbox{\texttt{\mdseries\slshape id}} of the \texttt{identifiers} list of the underlying database id enumerator, \texttt{DatabaseAttributeValueDefault} takes the \texttt{data} entry for \mbox{\texttt{\mdseries\slshape id}}, applies the \texttt{eval} function of \mbox{\texttt{\mdseries\slshape attr}} to it if available and returns the result.40234024So the question is how to get the \texttt{data} entry.40254026First, if the \texttt{data} component of \mbox{\texttt{\mdseries\slshape attr}} is not bound then the file given by the \texttt{datafile} component of \mbox{\texttt{\mdseries\slshape attr}}, if available, is read, and otherwise \texttt{DatabaseAttributeCompute} (\ref{DatabaseAttributeCompute}) is called; afterwards it is assumed that the \texttt{data} component is bound.40274028The further steps depend on the \texttt{type} value of \mbox{\texttt{\mdseries\slshape attr}}.40294030If the \texttt{type} value of \mbox{\texttt{\mdseries\slshape attr}} is \texttt{"pairs"} then the \texttt{data} entry for \mbox{\texttt{\mdseries\slshape id}} is either contained in the \texttt{automatic} or in the \texttt{nonautomatic} list of \mbox{\texttt{\mdseries\slshape attr}}\texttt{.data}, or it is given by the \texttt{dataDefault} value of \mbox{\texttt{\mdseries\slshape attr}}. (So a perhaps available \texttt{name} function is \emph{not} used to compute the value for a missing \texttt{data} entry.)40314032If the \texttt{type} value of \mbox{\texttt{\mdseries\slshape attr}} is \texttt{"values"} then the \texttt{data} entry for \mbox{\texttt{\mdseries\slshape id}} is computed as follows. Let $n$ be the position of \mbox{\texttt{\mdseries\slshape id}} in the \texttt{identifiers} component of the database id enumerator. If the $n$-th entry of the \texttt{data} component of \mbox{\texttt{\mdseries\slshape attr}} is bound then take it; otherwise if the \texttt{name} component is bound then apply it to \mbox{\texttt{\mdseries\slshape id}} and take the return value; otherwise take the \texttt{dataDefault} value.40334034If one wants to introduce a database attribute where this functionality is not4035suitable then another {\textendash}more specific{\textendash} function must be4036entered as the component \texttt{attributeValue} of such an attribute. }4037403840394040\subsection{\textcolor{Chapter }{DatabaseIdEnumeratorUpdate}}4041\logpage{[ "A", 1, 7 ]}\nobreak4042\hyperdef{L}{X80A909727E3C8311}{}4043{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DatabaseIdEnumeratorUpdate({\mdseries\slshape dbidenum})\index{DatabaseIdEnumeratorUpdate@\texttt{DatabaseIdEnumeratorUpdate}}4044\label{DatabaseIdEnumeratorUpdate}4045}\hfill{\scriptsize (function)}}\\4046\textbf{\indent Returns:\ }4047\texttt{true} or \texttt{false}.4048404940504051For a database id enumerator \mbox{\texttt{\mdseries\slshape dbidenum}} (see Section \ref{subsect:dbidenum}), \texttt{DatabaseIdEnumeratorUpdate} first calls the \texttt{update} function of \mbox{\texttt{\mdseries\slshape dbidenum}}. Afterwards, the \texttt{update} components of those of its \texttt{attributes} records are called for which the \texttt{version} component differs from that of \mbox{\texttt{\mdseries\slshape dbidenum}}.40524053The order in which the database attributes are updates is determined by the \texttt{neededAttributes} component.40544055The return value is \texttt{true} if all these functions return \texttt{true}, and \texttt{false} otherwise.40564057When \texttt{DatabaseIdEnumeratorUpdate} has returned \texttt{true}, the data described by \mbox{\texttt{\mdseries\slshape dbidenum}} and its database attributes are consistent and up to date. }4058405940604061\subsection{\textcolor{Chapter }{DatabaseAttributeCompute}}4062\logpage{[ "A", 1, 8 ]}\nobreak4063\hyperdef{L}{X812075CE7A01EA04}{}4064{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DatabaseAttributeCompute({\mdseries\slshape dbidenum, attridentifier[, what]})\index{DatabaseAttributeCompute@\texttt{DatabaseAttributeCompute}}4065\label{DatabaseAttributeCompute}4066}\hfill{\scriptsize (function)}}\\4067\textbf{\indent Returns:\ }4068\texttt{true} or \texttt{false}.4069407040714072This function returns \texttt{false} if \mbox{\texttt{\mdseries\slshape dbidenum}} is not a database id enumerator, or if it does not have a database attribute4073with \texttt{identifier} value \mbox{\texttt{\mdseries\slshape attridentifier}}, or if this attribute does not have a \texttt{create} function.40744075Otherwise the \texttt{prepareAttributeComputation} function is called, the \texttt{data} entries for the database attribute are (re)computed, the \texttt{cleanupAfterAttibuteComputation} function is called, and \texttt{true} is returned.40764077The optional argument \mbox{\texttt{\mdseries\slshape what}} determines which values are computed. Admissible values are4078\begin{description}4079\item[{\texttt{"all"}}] all \texttt{identifiers} entries of \mbox{\texttt{\mdseries\slshape dbidenum}},4080\item[{\texttt{"automatic"} (the default)}] the same as \texttt{"all"} if the \texttt{type} value of the database attribute is \texttt{"values"}, otherwise only the values for the \texttt{"automatic"} component are computed,4081\item[{\texttt{"new"}}] stored values are not recomputed.4082\end{description}4083}4084408540864087\subsection{\textcolor{Chapter }{DatabaseAttributeSetData}}4088\logpage{[ "A", 1, 9 ]}\nobreak4089\hyperdef{L}{X87A8B19C82E9FF0B}{}4090{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{DatabaseAttributeSetData({\mdseries\slshape dbidenum, attridentifier, version, data})\index{DatabaseAttributeSetData@\texttt{DatabaseAttributeSetData}}4091\label{DatabaseAttributeSetData}4092}\hfill{\scriptsize (function)}}\\409340944095Let \mbox{\texttt{\mdseries\slshape dbidenum}} be a database id enumerator (see Section \ref{subsect:dbidenum}), \mbox{\texttt{\mdseries\slshape attridentifier}} be a string that is the \texttt{identifier} value of a database attribute of \mbox{\texttt{\mdseries\slshape dbidenum}}, \mbox{\texttt{\mdseries\slshape data}} be the \texttt{data} list or record for the database attribute (depending on its \texttt{type} value), and \mbox{\texttt{\mdseries\slshape version}} be the corresponding \texttt{version} value.40964097\texttt{DatabaseAttributeSetData} sets the \texttt{data} and \texttt{version} components of the attribute. This function can be used for example in data4098files. }40994100}410141024103\section{\textcolor{Chapter }{Using Database Attributes for Browse Tables}}\label{sect:dbbrowse}4104\logpage{[ "A", 2, 0 ]}4105\hyperdef{L}{X80E9CFA17EE7817A}{}4106{41074108\subsection{\textcolor{Chapter }{Browse Relevant Components of Database Attributes}}\label{subsect:attr-browse-comp}4109\logpage{[ "A", 2, 1 ]}4110\hyperdef{L}{X7A2DD7827CBBD735}{}4111{4112The following optional components of database id enumerators and database4113attributes are used by \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}).411441154116\begin{description}4117\item[{\texttt{viewLabel}}] if bound, a table cell data object (see \texttt{BrowseData.IsBrowseTableCellData} (\ref{BrowseData.IsBrowseTableCellData})) that gives a \emph{short} description of the attribute, which is used as the column label in browse4118tables created with \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}); the default for database attributes is the \texttt{name} component, if bound, and otherwise the \texttt{identifier} component; the default for database id enumerators is the string \texttt{"name"},4119\item[{\texttt{viewValue}}] if bound, a function that takes the output of the \texttt{attributeValue} function and returns a table cell data object (see \texttt{BrowseData.IsBrowseTableCellData} (\ref{BrowseData.IsBrowseTableCellData})) that is used as the entry of the corresponding column in browse tables4120created with \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}); the default is \texttt{String} (\textbf{Reference: String}),4121\item[{\texttt{viewSort}}] if bound, a comparison function that takes two database attribute values and4122returns \texttt{true} if the first value is regarded as smaller than the second when the column4123corresponding to the attribute in the browse table constructed by \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}) gets sorted, and \texttt{false} otherwise; the default is \textsf{GAP}'s \texttt{\texttt{\symbol{92}}{\textless}} operation,4124\item[{\texttt{sortParameters}}] if bound, a list in the same format as the last argument of \texttt{BrowseData.SetSortParameters}, which is used for the column corresponding to the attribute in the browse4125table constructed by \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}); the default is an empty list,4126\item[{\texttt{widthCol}}] if bound, the width of the column in the browse table constructed by \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}); if a column width is prescribed this way then the function stored in the \texttt{attributeValue} component must return either a list of attribute lines that fit into the4127column or a plain string (which then gets formatted as required); there is no4128default for this component, meaning that the column width is computed as the4129maximum of the widths of the column label and of all entries in the column if4130no value is bound,4131\item[{\texttt{align}}] if bound, the alignment of the values in the column of the browse table4132constructed by \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}); admissible values are substrings of \texttt{"bclt"}, see \texttt{BrowseData.IsBrowseTableCellData} (\ref{BrowseData.IsBrowseTableCellData}); the default is right and vertically centered, but note that if the \texttt{viewValues} function returns a record (see \texttt{BrowseData.IsBrowseTableCellData} (\ref{BrowseData.IsBrowseTableCellData})) then the alignment prescribed by this record is preferred,4133\item[{\texttt{categoryValue}}] if bound, a function that is similar to the \texttt{viewValue} component but may return a different value; for example if the column in the4134browse table belongs to a property and the \texttt{viewValue} function returns something like \texttt{"+"} or \texttt{"-"}, it may be useful that the category rows show a textual description of the4135property values; the default value is the \texttt{viewValue} component; if the value is a record then its \texttt{rows} component is taken for forming category rows, if the value is an attribute4136line (see \texttt{NCurses.IsAttributeLine} (\ref{NCurses.IsAttributeLine})) then there is exactly this category row, and otherwise the value is regarded4137as a list of attribute lines, which is either concatenated to one category row4138or turned into individual category rows, depending on the \texttt{sortParameters} value.4139\end{description}4140}4141414241434144\subsection{\textcolor{Chapter }{BrowseTableFromDatabaseIdEnumerator}}4145\logpage{[ "A", 2, 2 ]}\nobreak4146\hyperdef{L}{X7F25A3E586653911}{}4147{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseTableFromDatabaseIdEnumerator({\mdseries\slshape dbidenum, labelids, columnids[, header[, footer[, choice]]]})\index{BrowseTableFromDatabaseIdEnumerator@\texttt{BrowseTableFromDatabaseIdEnumerator}}4148\label{BrowseTableFromDatabaseIdEnumerator}4149}\hfill{\scriptsize (function)}}\\4150\textbf{\indent Returns:\ }4151a record that can be used as the input of \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}).4152415341544155For a database id enumerator \mbox{\texttt{\mdseries\slshape dbidenum}} (see Section \ref{subsect:dbidenum}) and two lists \mbox{\texttt{\mdseries\slshape labelids}} and \mbox{\texttt{\mdseries\slshape columnids}} of \texttt{identifier} values of database attributes stored in \mbox{\texttt{\mdseries\slshape dbidenum}}, \texttt{BrowseTableFromDatabaseIdEnumerator} returns a browse table (see{\nobreakspace}\texttt{BrowseData.IsBrowseTable} (\ref{BrowseData.IsBrowseTable})) whose columns are given by the values of the specified database attributes.4156The columns listed in \mbox{\texttt{\mdseries\slshape labelids}} are used to provide row label columns of the browse table, the columns listed4157in \mbox{\texttt{\mdseries\slshape columnids}} yield main table columns. \mbox{\texttt{\mdseries\slshape columnids}} must be nonempty.41584159If the optional arguments \mbox{\texttt{\mdseries\slshape header}} and \mbox{\texttt{\mdseries\slshape footer}} are given then they must be lists or functions or records that are admissible4160for the \texttt{header} and \texttt{footer} components of the \texttt{work} record of the browse table, see \texttt{BrowseData.IsBrowseTable} (\ref{BrowseData.IsBrowseTable}).41614162The optional argument \mbox{\texttt{\mdseries\slshape choice}}, if given, must be a subset of \mbox{\texttt{\mdseries\slshape dbidenum}}\texttt{.identifiers}. The rows of the returned browse table are then restricted to this subset.41634164The returned browse table does not support ``Click'' events or return values. }41654166}416741684169\section{\textcolor{Chapter }{Example: Database Id Enumerators and Database Attributes}}\label{sect:dbidenumxpl}4170\logpage{[ "A", 3, 0 ]}4171\hyperdef{L}{X808BDD24857F3904}{}4172{4173As an example for the functions introduced in this appendix, we introduce the \emph{database of small integers}. For that, we fix a positive integer $n$ and consider the integers from $1$ to $n$ as the entries of our database. Using these integers as their own identifiers,4174we construct the database id enumerator.4175\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]4176!gapprompt@gap>| !gapinput@n:= 100;;|4177!gapprompt@gap>| !gapinput@smallintenum1:= DatabaseIdEnumerator( rec(|4178!gapprompt@>| !gapinput@ identifiers:= [ 1 .. n ],|4179!gapprompt@>| !gapinput@ entry:= function( dbidenum, id ) return id; end,|4180!gapprompt@>| !gapinput@ ) );;|4181\end{Verbatim}4182Examples of attributes for this database are the properties whether or not an4183integer is a prime or a prime power. There are global \textsf{GAP} functions \texttt{IsPrimeInt} (\textbf{Reference: IsPrimeInt}) and \texttt{IsPrimePowerInt} (\textbf{Reference: IsPrimePowerInt}) for computing these properties, so we can define these database attributes via4184a \texttt{name} component; we choose \texttt{"values"} as the \texttt{type} value, so the values (\texttt{true} or \texttt{false}) are stored in a list of length $n$ for each of the two database attributes.4185\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]4186!gapprompt@gap>| !gapinput@DatabaseAttributeAdd( smallintenum1, rec(|4187!gapprompt@>| !gapinput@ identifier:= "primes",|4188!gapprompt@>| !gapinput@ type:= "values",|4189!gapprompt@>| !gapinput@ name:= "IsPrimeInt",|4190!gapprompt@>| !gapinput@ ) );|4191!gapprompt@gap>| !gapinput@DatabaseAttributeAdd( smallintenum1, rec(|4192!gapprompt@>| !gapinput@ identifier:= "prime powers",|4193!gapprompt@>| !gapinput@ type:= "values",|4194!gapprompt@>| !gapinput@ name:= "IsPrimePowerInt",|4195!gapprompt@>| !gapinput@ ) );|4196\end{Verbatim}4197Similarly, we consider the prime factors as a database attribute.4198\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]4199!gapprompt@gap>| !gapinput@DatabaseAttributeAdd( smallintenum1, rec(|4200!gapprompt@>| !gapinput@ identifier:= "factors",|4201!gapprompt@>| !gapinput@ type:= "values",|4202!gapprompt@>| !gapinput@ name:= "Factors",|4203!gapprompt@>| !gapinput@ ) );|4204\end{Verbatim}4205Another example of an attribute of integers is the residue modulo $11$. We do not want to introduce a global \textsf{GAP} function for computing the value, so we use the \texttt{create} component in order to define the attribute; again, the values (integers from $0$ to $10$) are stored in a list of length $n$.4206\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]4207!gapprompt@gap>| !gapinput@DatabaseAttributeAdd( smallintenum1, rec(|4208!gapprompt@>| !gapinput@ identifier:= "residue mod 11",|4209!gapprompt@>| !gapinput@ type:= "values",|4210!gapprompt@>| !gapinput@ create:= function( attr, id ) return id mod 11; end,|4211!gapprompt@>| !gapinput@ ) );|4212\end{Verbatim}4213Some integers are values of \texttt{Factorial} (\textbf{Reference: Factorial}), and we want to record this information and show it in a browse table. For4214most integers, nothing is stored and shown for this attribute, so we choose4215the \texttt{type} value \texttt{"pairs"} and precompute the information for the \texttt{data} component. (The default for the \texttt{dataDefault} component is an empty string, which is fine; so we need not prescribe this4216component.)4217\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]4218!gapprompt@gap>| !gapinput@factorialdata:= function( n )|4219!gapprompt@>| !gapinput@ local result, i, f;|4220!gapprompt@>| !gapinput@ result:= []; i:= 1; f:= 1;;|4221!gapprompt@>| !gapinput@ while f <= n do|4222!gapprompt@>| !gapinput@ Add( result, [ f, i ] ); i:= i + 1; f:= f * i;|4223!gapprompt@>| !gapinput@ od;|4224!gapprompt@>| !gapinput@ return result;|4225!gapprompt@>| !gapinput@ end;;|4226!gapprompt@gap>| !gapinput@DatabaseAttributeAdd( smallintenum1, rec(|4227!gapprompt@>| !gapinput@ identifier:= "inverse factorial",|4228!gapprompt@>| !gapinput@ type:= "pairs",|4229!gapprompt@>| !gapinput@ data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),|4230!gapprompt@>| !gapinput@ isSorted:= true,|4231!gapprompt@>| !gapinput@ ) );|4232\end{Verbatim}4233We use this setup for creating a browse table. The integers are shown as the4234first column, using the \texttt{"self"} attribute. This attribute can be used as a column of row labels (useful if we4235want to keep the column visible when one scrolls the table to the right) or as4236a column in the main table (useful if we want to search for the values); here4237we choose the former possibility.4238\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]4239!gapprompt@gap>| !gapinput@t1:= BrowseTableFromDatabaseIdEnumerator( smallintenum1,|4240!gapprompt@>| !gapinput@ [ "self" ],|4241!gapprompt@>| !gapinput@ [ "primes", "prime powers", "factors", "residue mod 11",|4242!gapprompt@>| !gapinput@ "inverse factorial" ] );;|4243\end{Verbatim}4244The following session shows some of the features of the browse table.4245\begin{Verbatim}[commandchars=@|A,fontsize=\small,frame=single,label=Example]4246@gapprompt|gap>A @gapinput|nop:= [ 14, 14, 14, 14, 14, 14 ];; # ``do nothing''A4247@gapprompt|gap>A @gapinput|sample_session:= Concatenation(A4248@gapprompt|>A @gapinput| # categorize by the first column, expand categories, wait, resetA4249@gapprompt|>A @gapinput| nop, "scsc", nop, "X", nop, "!",A4250@gapprompt|>A @gapinput| # sort the residue column, wait, resetA4251@gapprompt|>A @gapinput| "scrrrso", nop, "!",A4252@gapprompt|>A @gapinput| # categorize by the inverse factorial columnA4253@gapprompt|>A @gapinput| "rscsrdx", nop, "!",A4254@gapprompt|>A @gapinput| # and quit the applicationA4255@gapprompt|>A @gapinput| "qQ" );;A4256@gapprompt|gap>A @gapinput|BrowseData.SetReplay( sample_session );A4257@gapprompt|gap>A @gapinput|NCurses.BrowseGeneric( t1 );A4258@gapprompt|gap>A @gapinput|BrowseData.SetReplay( false );A4259@gapprompt|gap>A @gapinput|Unbind( t1.dynamic.replay );A4260\end{Verbatim}4261(Note that the last statement above is necessary to run the session more than4262once.) The result is not too bad but we can improve the table, using the4263optional components of database attributes, as follows.4264\begin{itemize}4265\item The strings \texttt{"true"} and \texttt{"false"} shown for the Boolean valued database attributes can be replaced by the4266perhaps more suggestive strings \texttt{"+"} and \texttt{"-"} (or perhaps an empty string instead of \texttt{"-"}).4267\item The alignment of values inside their columns can be customized.4268\item When the browse table is categorized by a column then the values in this4269column do usually not provide suitable category rows; we can prescribe4270individual category values.4271\item The column labels can be customized.4272\item Where the lexicographic order is not appropriate for sorting table entries, we4273can prescribe an individual comparison function.4274\item Sort parameters can be customized.4275\item We can prescribe the width of a column, and thus distribute the attribute4276values for this column to several rows when the values are too long.4277\item Finally, in the call of \texttt{BrowseTableFromDatabaseIdEnumerator} (\ref{BrowseTableFromDatabaseIdEnumerator}), we can add a header to the browse table.4278\end{itemize}4279We create a new database id enumerator and the corresponding browse table, in4280order to be able to compare the behaviour of the two objects. However, we4281assume that the variables \texttt{n} and \texttt{factorialdata} are already available.4282\begin{Verbatim}[commandchars=@|G,fontsize=\small,frame=single,label=Example]4283@gapprompt|gap>G @gapinput|smallintenum2:= DatabaseIdEnumerator( rec(G4284@gapprompt|>G @gapinput| identifiers:= [ 1 .. n ],G4285@gapprompt|>G @gapinput| entry:= function( dbidenum, id ) return id; end,G4286@gapprompt|>G @gapinput| viewLabel:= "",G4287@gapprompt|>G @gapinput| ) );;G4288@gapprompt|gap>G @gapinput|DatabaseAttributeAdd( smallintenum2, rec(G4289@gapprompt|>G @gapinput| identifier:= "primes",G4290@gapprompt|>G @gapinput| type:= "values",G4291@gapprompt|>G @gapinput| name:= "IsPrimeInt",G4292@gapprompt|>G @gapinput| viewLabel:= "prime?",G4293@gapprompt|>G @gapinput| viewValue:= value -> BrowseData.ReplacedEntry( value,G4294@gapprompt|>G @gapinput| [ true, false ], [ "+", "-" ] ),G4295@gapprompt|>G @gapinput| sortParameters:= [ "add counter on categorizing", "yes" ],G4296@gapprompt|>G @gapinput| align:= "c",G4297@gapprompt|>G @gapinput| categoryValue:= value -> BrowseData.ReplacedEntry( value,G4298@gapprompt|>G @gapinput| [ true, false ], [ "prime", "nonprime" ] ),G4299@gapprompt|>G @gapinput| ) );G4300@gapprompt|gap>G @gapinput|DatabaseAttributeAdd( smallintenum2, rec(G4301@gapprompt|>G @gapinput| identifier:= "prime powers",G4302@gapprompt|>G @gapinput| type:= "values",G4303@gapprompt|>G @gapinput| name:= "IsPrimePowerInt",G4304@gapprompt|>G @gapinput| viewLabel:= "prime power?",G4305@gapprompt|>G @gapinput| viewValue:= value -> BrowseData.ReplacedEntry( value,G4306@gapprompt|>G @gapinput| [ true, false ], [ "+", "-" ] ),G4307@gapprompt|>G @gapinput| sortParameters:= [ "add counter on categorizing", "yes" ],G4308@gapprompt|>G @gapinput| align:= "c",G4309@gapprompt|>G @gapinput| categoryValue:= value -> BrowseData.ReplacedEntry( value,G4310@gapprompt|>G @gapinput| [ true, false ], [ "prime power", "not prime power" ] ),G4311@gapprompt|>G @gapinput| ) );G4312@gapprompt|gap>G @gapinput|DatabaseAttributeAdd( smallintenum2, rec(G4313@gapprompt|>G @gapinput| identifier:= "factors",G4314@gapprompt|>G @gapinput| type:= "values",G4315@gapprompt|>G @gapinput| name:= "Factors",G4316@gapprompt|>G @gapinput| viewLabel:= "factors",G4317@gapprompt|>G @gapinput| viewValue:= value -> JoinStringsWithSeparator( List( value, String ),G4318@gapprompt|>G @gapinput| " * "),G4319@gapprompt|>G @gapinput| widthCol:= 10,G4320@gapprompt|>G @gapinput| ) );G4321@gapprompt|gap>G @gapinput|DatabaseAttributeAdd( smallintenum2, rec(G4322@gapprompt|>G @gapinput| identifier:= "residue mod 11",G4323@gapprompt|>G @gapinput| type:= "values",G4324@gapprompt|>G @gapinput| create:= function( attr, id ) return id mod 11; end,G4325@gapprompt|>G @gapinput| viewSort:= BrowseData.SortAsIntegers,G4326@gapprompt|>G @gapinput| categoryValue:= res -> Concatenation( String( res ), " mod 11" ),G4327@gapprompt|>G @gapinput| ) );G4328@gapprompt|gap>G @gapinput|DatabaseAttributeAdd( smallintenum2, rec(G4329@gapprompt|>G @gapinput| identifier:= "inverse factorial",G4330@gapprompt|>G @gapinput| type:= "pairs",G4331@gapprompt|>G @gapinput| data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),G4332@gapprompt|>G @gapinput| isSorted:= true,G4333@gapprompt|>G @gapinput| categoryValue:= function( k )G4334@gapprompt|>G @gapinput| if k = "" thenG4335@gapprompt|>G @gapinput| return "(no factorial)";G4336@gapprompt|>G @gapinput| elseG4337@gapprompt|>G @gapinput| return Concatenation( String( k ), "!" );G4338@gapprompt|>G @gapinput| fi;G4339@gapprompt|>G @gapinput| end,G4340@gapprompt|>G @gapinput| ) );G4341@gapprompt|gap>G @gapinput|t2:= BrowseTableFromDatabaseIdEnumerator( smallintenum2,G4342@gapprompt|>G @gapinput| [ "self" ],G4343@gapprompt|>G @gapinput| [ "primes", "prime powers", "factors", "residue mod 11",G4344@gapprompt|>G @gapinput| "inverse factorial" ],G4345@gapprompt|>G @gapinput| t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;G4346\end{Verbatim}4347We run the same session as with the browse table for \texttt{smallintenum1}.4348\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]4349!gapprompt@gap>| !gapinput@BrowseData.SetReplay( sample_session );|4350!gapprompt@gap>| !gapinput@NCurses.BrowseGeneric( t2 );|4351!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|4352!gapprompt@gap>| !gapinput@Unbind( t2.dynamic.replay );|4353\end{Verbatim}4354Another possibility to change the look of the table is to combine the columns4355for the two Boolean valued database attributes in one column, by showing the4356string \texttt{"+"} for prime powers, as before, and showing this string in boldface red if the4357number in question is a prime. We implement this idea in the following4358database attribute. However, note that this can be a bad idea because text4359attributes may be not supported in the user's terminal (see Section \ref{ssec:ncursesAttrs}), or the user may have difficulties to see or to distinguish colors; also, it4360must be documented which information is encoded in the table, and the column4361label might be not sufficient for explaining what the text attributes mean.4362Alternatively, we could show for example combined symbols such as \texttt{++}, \texttt{+-}, \texttt{--} for primes, prime powers, and non-prime-powers, respectively. (We see that4363besides these issues, the required \textsf{GAP} code is more involved than what is needed for the examples above.)4364\begin{Verbatim}[commandchars=@|J,fontsize=\small,frame=single,label=Example]4365@gapprompt|gap>J @gapinput|DatabaseAttributeAdd( smallintenum2, rec(J4366@gapprompt|>J @gapinput| identifier:= "primes & prime powers",J4367@gapprompt|>J @gapinput| type:= "values",J4368@gapprompt|>J @gapinput| create:= function( attr, id )J4369@gapprompt|>J @gapinput| if IsPrimeInt( id ) thenJ4370@gapprompt|>J @gapinput| return 2;J4371@gapprompt|>J @gapinput| elif IsPrimePowerInt( id ) thenJ4372@gapprompt|>J @gapinput| return 1;J4373@gapprompt|>J @gapinput| elseJ4374@gapprompt|>J @gapinput| return 0;J4375@gapprompt|>J @gapinput| fi;J4376@gapprompt|>J @gapinput| end,J4377@gapprompt|>J @gapinput| viewLabel:= [ NCurses.attrs.BOLD + NCurses.ColorAttr( "red", -1 ),J4378@gapprompt|>J @gapinput| "prime", NCurses.attrs.NORMAL, " power?" ],J4379@gapprompt|>J @gapinput| viewValue:= value -> BrowseData.ReplacedEntry( value,J4380@gapprompt|>J @gapinput| [ 0, 1, 2 ], [ "-", "+",J4381@gapprompt|>J @gapinput| [ NCurses.attrs.BOLD + NCurses.ColorAttr( "red", -1 ),J4382@gapprompt|>J @gapinput| true, "+",J4383@gapprompt|>J @gapinput| NCurses.ColorAttr( "red", -1 ), false ] ] ),J4384@gapprompt|>J @gapinput| sortParameters:= [ "add counter on categorizing", "yes" ],J4385@gapprompt|>J @gapinput| align:= "c",J4386@gapprompt|>J @gapinput| categoryValue:= value -> BrowseData.ReplacedEntry( value,J4387@gapprompt|>J @gapinput| [ 0, 1, 2 ],J4388@gapprompt|>J @gapinput| [ "not prime power", "prime power, not prime", "prime" ] ),J4389@gapprompt|>J @gapinput| ) );J4390@gapprompt|gap>J @gapinput|t3:= BrowseTableFromDatabaseIdEnumerator( smallintenum2,J4391@gapprompt|>J @gapinput| [ "self" ],J4392@gapprompt|>J @gapinput| [ "primes & prime powers", "residue mod 11",J4393@gapprompt|>J @gapinput| "inverse factorial" ],J4394@gapprompt|>J @gapinput| t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;J4395@gapprompt|gap>J @gapinput|sample_session2:= Concatenation(J4396@gapprompt|>J @gapinput| # categorize by the first column, expand categories, wait, resetJ4397@gapprompt|>J @gapinput| nop, "scsc", nop, "X", nop, "!", "Q" );;J4398@gapprompt|gap>J @gapinput|BrowseData.SetReplay( sample_session2 );J4399@gapprompt|gap>J @gapinput|NCurses.BrowseGeneric( t3 );J4400@gapprompt|gap>J @gapinput|BrowseData.SetReplay( false );J4401@gapprompt|gap>J @gapinput|Unbind( t3.dynamic.replay );J4402\end{Verbatim}4403Now we want to consider the database as extendible, that is, we want to be4404able to increase $n$ after constructing the database attributes. For that, we use $n$ as the \texttt{version} value of the database id enumerator, and provide \texttt{version} and \texttt{update} components for all attributes.44054406Again, we start the construction from scratch.4407\begin{Verbatim}[commandchars=@|G,fontsize=\small,frame=single,label=Example]4408@gapprompt|gap>G @gapinput|smallintenum3:= DatabaseIdEnumerator( rec(G4409@gapprompt|>G @gapinput| identifiers:= [ 1 .. n ],G4410@gapprompt|>G @gapinput| entry:= function( dbidenum, id ) return id; end,G4411@gapprompt|>G @gapinput| viewLabel:= "",G4412@gapprompt|>G @gapinput| version:= n,G4413@gapprompt|>G @gapinput| update:= function( dbidenum )G4414@gapprompt|>G @gapinput| dbidenum.identifiers:= [ 1 .. n ];G4415@gapprompt|>G @gapinput| dbidenum.version:= n;G4416@gapprompt|>G @gapinput| return true;G4417@gapprompt|>G @gapinput| end,G4418@gapprompt|>G @gapinput| ) );;G4419@gapprompt|gap>G @gapinput|updateByUnbindData:= function( attr )G4420@gapprompt|>G @gapinput| Unbind( attr.data );G4421@gapprompt|>G @gapinput| return true;G4422@gapprompt|>G @gapinput| end;;G4423@gapprompt|gap>G @gapinput|DatabaseAttributeAdd( smallintenum3, rec(G4424@gapprompt|>G @gapinput| identifier:= "primes",G4425@gapprompt|>G @gapinput| type:= "values",G4426@gapprompt|>G @gapinput| name:= "IsPrimeInt",G4427@gapprompt|>G @gapinput| viewLabel:= "prime?",G4428@gapprompt|>G @gapinput| viewValue:= value -> BrowseData.ReplacedEntry( value,G4429@gapprompt|>G @gapinput| [ true, false ], [ "+", "-" ] ),G4430@gapprompt|>G @gapinput| sortParameters:= [ "add counter on categorizing", "yes" ],G4431@gapprompt|>G @gapinput| align:= "c",G4432@gapprompt|>G @gapinput| categoryValue:= value -> BrowseData.ReplacedEntry( value,G4433@gapprompt|>G @gapinput| [ true, false ], [ "prime", "nonprime" ] ),G4434@gapprompt|>G @gapinput| version:= n,G4435@gapprompt|>G @gapinput| update:= updateByUnbindData,G4436@gapprompt|>G @gapinput| ) );G4437@gapprompt|gap>G @gapinput|DatabaseAttributeAdd( smallintenum3, rec(G4438@gapprompt|>G @gapinput| identifier:= "prime powers",G4439@gapprompt|>G @gapinput| type:= "values",G4440@gapprompt|>G @gapinput| name:= "IsPrimePowerInt",G4441@gapprompt|>G @gapinput| viewLabel:= "prime power?",G4442@gapprompt|>G @gapinput| viewValue:= value -> BrowseData.ReplacedEntry( value,G4443@gapprompt|>G @gapinput| [ true, false ], [ "+", "-" ] ),G4444@gapprompt|>G @gapinput| sortParameters:= [ "add counter on categorizing", "yes" ],G4445@gapprompt|>G @gapinput| align:= "c",G4446@gapprompt|>G @gapinput| categoryValue:= value -> BrowseData.ReplacedEntry( value,G4447@gapprompt|>G @gapinput| [ true, false ], [ "prime power", "not prime power" ] ),G4448@gapprompt|>G @gapinput| version:= n,G4449@gapprompt|>G @gapinput| update:= updateByUnbindData,G4450@gapprompt|>G @gapinput| ) );G4451@gapprompt|gap>G @gapinput|DatabaseAttributeAdd( smallintenum3, rec(G4452@gapprompt|>G @gapinput| identifier:= "factors",G4453@gapprompt|>G @gapinput| type:= "values",G4454@gapprompt|>G @gapinput| name:= "Factors",G4455@gapprompt|>G @gapinput| viewLabel:= "factors",G4456@gapprompt|>G @gapinput| viewValue:= value -> JoinStringsWithSeparator( List( value, String ),G4457@gapprompt|>G @gapinput| " * "),G4458@gapprompt|>G @gapinput| widthCol:= 10,G4459@gapprompt|>G @gapinput| version:= n,G4460@gapprompt|>G @gapinput| update:= updateByUnbindData,G4461@gapprompt|>G @gapinput| ) );G4462@gapprompt|gap>G @gapinput|DatabaseAttributeAdd( smallintenum3, rec(G4463@gapprompt|>G @gapinput| identifier:= "residue mod 11",G4464@gapprompt|>G @gapinput| type:= "values",G4465@gapprompt|>G @gapinput| create:= function( attr, id ) return id mod 11; end,G4466@gapprompt|>G @gapinput| viewSort:= BrowseData.SortAsIntegers,G4467@gapprompt|>G @gapinput| categoryValue:= res -> Concatenation( String( res ), " mod 11" ),G4468@gapprompt|>G @gapinput| version:= n,G4469@gapprompt|>G @gapinput| update:= updateByUnbindData,G4470@gapprompt|>G @gapinput| ) );G4471@gapprompt|gap>G @gapinput|DatabaseAttributeAdd( smallintenum3, rec(G4472@gapprompt|>G @gapinput| identifier:= "inverse factorial",G4473@gapprompt|>G @gapinput| type:= "pairs",G4474@gapprompt|>G @gapinput| data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),G4475@gapprompt|>G @gapinput| isSorted:= true,G4476@gapprompt|>G @gapinput| categoryValue:= function( k )G4477@gapprompt|>G @gapinput| if k = "" thenG4478@gapprompt|>G @gapinput| return "(no factorial)";G4479@gapprompt|>G @gapinput| elseG4480@gapprompt|>G @gapinput| return Concatenation( String( k ), "!" );G4481@gapprompt|>G @gapinput| fi;G4482@gapprompt|>G @gapinput| end,G4483@gapprompt|>G @gapinput| version:= n,G4484@gapprompt|>G @gapinput| update:= function( attr )G4485@gapprompt|>G @gapinput| attr.data.automatic:= factorialdata( n );G4486@gapprompt|>G @gapinput| return true;G4487@gapprompt|>G @gapinput| end,G4488@gapprompt|>G @gapinput| ) );G4489\end{Verbatim}4490Now we can change the set of database entries by assigning a new value to the4491variable \texttt{n}, and then calling \texttt{DatabaseIdEnumeratorUpdate} (\ref{DatabaseIdEnumeratorUpdate}).4492\begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example]4493!gapprompt@gap>| !gapinput@n:= 200;;|4494!gapprompt@gap>| !gapinput@DatabaseIdEnumeratorUpdate( smallintenum3 );|4495true4496!gapprompt@gap>| !gapinput@t4:= BrowseTableFromDatabaseIdEnumerator( smallintenum3,|4497!gapprompt@>| !gapinput@ [ "self" ], [ "primes", "prime powers", "factors", "residue mod 11",|4498!gapprompt@>| !gapinput@ "inverse factorial" ],|4499!gapprompt@>| !gapinput@ t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;|4500!gapprompt@gap>| !gapinput@BrowseData.SetReplay( sample_session );|4501!gapprompt@gap>| !gapinput@NCurses.BrowseGeneric( t4 );|4502!gapprompt@gap>| !gapinput@BrowseData.SetReplay( false );|4503!gapprompt@gap>| !gapinput@Unbind( t4.dynamic.replay );|4504\end{Verbatim}4505}450645074508\section{\textcolor{Chapter }{Example: An Overview of the \textsf{GAP} Library of Tables of Marks }}\label{sect:tomlibinfo}4509\logpage{[ "A", 4, 0 ]}4510\hyperdef{L}{X8628EF6981A524B3}{}4511{4512The example shown in this section deals with \textsf{GAP}'s Library of Tables of Marks (the \textsf{TomLib} package \cite{TomLib}).45134514\subsection{\textcolor{Chapter }{BrowseTomLibInfo}}4515\logpage{[ "A", 4, 1 ]}\nobreak4516\hyperdef{L}{X844D143980A0E20D}{}4517{\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{BrowseTomLibInfo({\mdseries\slshape })\index{BrowseTomLibInfo@\texttt{BrowseTomLibInfo}}4518\label{BrowseTomLibInfo}4519}\hfill{\scriptsize (function)}}\\4520\textbf{\indent Returns:\ }4521nothing.4522452345244525This function shows the contents of the \textsf{GAP} Library of Tables of Marks (the \textsf{TomLib} package, see \cite{TomLib}) in a browse table.45264527The first call may take substantial time (about $40$ seconds), because the data files of the \textsf{TomLib} package are evaluated. This could be improved by precomputing and caching the4528values. Another possibility would be to call \texttt{BrowseTomLibInfo} once before creating a \textsf{GAP} workspace. The subsequent calls are not expensive.45294530The table rows correspond to the tables of marks, one column of row labels4531shows the identifier of the table. The columns of the table contain4532information about the group order, the number of conjugacy classes of4533subgroups, the identifiers of tables of marks with fusions to and from the4534given table, and the name of the file that contains the table of marks data.45354536The full functionality of the function \texttt{NCurses.BrowseGeneric} (\ref{NCurses.BrowseGeneric}) is available.453745384539\begin{Verbatim}[commandchars=@|F,fontsize=\small,frame=single,label=Example]4540@gapprompt|gap>F @gapinput|c:= [ NCurses.keys.ENTER ];;F4541@gapprompt|gap>F @gapinput|n:= [ 14, 14, 14 ];; # ``do nothing''F4542@gapprompt|gap>F @gapinput|BrowseData.SetReplay( Concatenation(F4543@gapprompt|>F @gapinput| "scrrsc", # categorize the list by source tables of fusions,F4544@gapprompt|>F @gapinput| "srdd", # choose a source table,F4545@gapprompt|>F @gapinput| "x", # expand the list of targets of fusionsF4546@gapprompt|>F @gapinput| n,F4547@gapprompt|>F @gapinput| "!", # revert the categorizationF4548@gapprompt|>F @gapinput| "q", # leave the mode in which a row is selectedF4549@gapprompt|>F @gapinput| "scrrrrsc", # categorize the list by filenamesF4550@gapprompt|>F @gapinput| "X", # expand all categoriesF4551@gapprompt|>F @gapinput| n,F4552@gapprompt|>F @gapinput| "!", # revert the categorizationF4553@gapprompt|>F @gapinput| "scso", # sort the list by group orderF4554@gapprompt|>F @gapinput| n,F4555@gapprompt|>F @gapinput| "!q", # revert the sorting and selectionF4556@gapprompt|>F @gapinput| "?", # open the help windowF4557@gapprompt|>F @gapinput| n,F4558@gapprompt|>F @gapinput| "Q", # close the help windowF4559@gapprompt|>F @gapinput| "/A5", c, # search for the first occurrence of "A5"F4560@gapprompt|>F @gapinput| n,F4561@gapprompt|>F @gapinput| "Q" ) );; # and quit the browse tableF4562@gapprompt|gap>F @gapinput|BrowseTomLibInfo();F4563@gapprompt|gap>F @gapinput|BrowseData.SetReplay( false );F4564\end{Verbatim}4565}45664567}45684569}45704571\def\bibname{References\logpage{[ "Bib", 0, 0 ]}4572\hyperdef{L}{X7A6F98FD85F02BFE}{}4573}45744575\bibliographystyle{alpha}4576\bibliography{browsebib.xml,manualbib.xml}45774578\addcontentsline{toc}{chapter}{References}45794580\def\indexname{Index\logpage{[ "Ind", 0, 0 ]}4581\hyperdef{L}{X83A0356F839C696F}{}4582}45834584\cleardoublepage4585\phantomsection4586\addcontentsline{toc}{chapter}{Index}458745884589\printindex45904591\newpage4592\immediate\write\pagenrlog{["End"], \arabic{page}];}4593\immediate\closeout\pagenrlog4594\end{document}459545964597