SS 1.3.3 (1)

NAME
ss - simple spreadsheet program

SYNOPSIS
ss [ -c ] [ -m ] [ -r ] [ -o ] [ -x ] [ -C ] [ -R ] [ -L ] [ file ]

DESCRIPTION
ss is a spreadsheet program (big surprise!).

It is not another Lotus 1-2-3(tm) or Excel(tm) or etc spreadsheet program that consumes megabytes of disk space and is full of whiz-bang graphics and fonts and so on and so forth that the average user (IMHO) needs and uses only infrequently.

ss is a character based program that should run on any standard ASCII terminal. It is based on rectangular tables much like a financial spreadsheet. When invoked it presents you with a table organized as rows and columns of cells - just like any ``normal'' spreadsheet program.

OPTIONS

-c  Start the program with input method set to 'CR terminated'. (See below)

-m  Start the program with automatic recalculation disabled. The spreadsheet will be recalculated only when the recalc command (see below) is used.

-r  Start the program with the recalculation being done in row order (default option).

-o  Start the program with the recalculation being done in column order.

-x  Cause the data files to be decrypted/encrypted when read/written. (This option may not be available at your site, depending on the capabilities of your computer system, check with your system administrator.)

-R  Start the program with automatic newline action set to increment the row (see below).

-C  Start the program with automatic newline action set to increment the column (see below).

-L  Start the program with automatic newline action set to move in whatever direction the cell-cursor last moved (see below).

file
    If invoked without a file argument, the table is initially empty. Otherwise file is read in.

All of these options can also be changed from within ss. Those changes will then be saved when the current spreadsheet is saved, and reloaded when that spreadsheet is read in from disk. Options specified when ss is invoked override options saved in the data file.

INTRODUCTION
ss is based upon the well-known (?) public domain spreadsheet program ``sc'', version 6.19.

ss is an ``un-moded'' program. It does not have separate input and output modes that you toggle between. To enter numbers into your spreadsheet, go ahead and start typing. You can enter text the same way, just do it (more detail on these operations below).

If your keyboard has Arrow keys and/or Page-Up and Page-Down keys, they should work as you expect them too. If they don't, talk to whomever installed this program on your system, it could be a simple terminfo/termcap problem. If your keyboard doesn't have cursor movement keys, relax. When you use ss you can also use the same cursor movement commands as emacs (more on that below, also).

There are a wide selection of financial and other ``standard'' spreadsheet functions that you can use. They are listed and explained in detail below. (Wow, sure must be a lot of stuff below!)

Finally, instead of forcing you to memorize bazillions of different commands, ss places most operations (Save, Move, etc) in menus. These menus are probably vaguely familiar to you, since they were inspired by a certain well-known DOS spreadsheet program. Go ahead, hit the ``/'' key. You probably will figure many things out without even reading on in this man page.

However, you probably should read on, because there's lot's to learn. I'd also hate to have typed all this in for nothing! :-)

NOTE: This man page assumes that the reader has a general familiarity with spreadsheet programs.

  Screen Layout
The screen is divided into four regions. The top line is for entering commands/data and displaying cell values. The second line is for messages from ss. The third line and the first four columns show the column and row numbers, from which are derived cell addresses, e.g. A0 for the cell in column A, row 0. Note that column names are case-insensitive: Entering A0 is equivalent to a0.

The rest of the screen forms a window looking at a portion of the table. The total number of table rows and columns displayed is set by curses(3) and may be overridden by setting the LINES and COLUMNS environment variables, respectively.

    [ Note to X-Windows users; Yes you can resize your terminal windows. The next time a command is processed, or the screen is redrawn, ss will figure things out and adjust itself. ]

The screen has three cursors: a cell cursor, indicated by a highlighted cell and a ``<'' on the screen, a menu cursor, indicated by a highlighted menu item (it functions much like the cell cursor), and a character cursor, indicated by the terminal's hardware cursor. The cell and character cursors are often the same. They differ when you type a command on the top line.

If a cell's numeric value is wider than the column width, the cell is filled with asterisks. If a cell's label string is wider than the column width, it is truncated at the start of the next non-blank cell in the row, if any.

  How Input Is Processed
Let's assume that you have just started ss, so that you are at the ``top-level'' of input processing. You enter a keystroke; a number or letter, arrow key or function key. The program reads your input and processes it as follows:

Control-key, Arrow key, or Function key
    The appropriate function is performed (ie: Move the cursor to the next row). See the section below entitled COMMANDS.

`/' The main top-level menu is displayed and the program enters ``menu-mode''. See the section below entitled MENUS.

`0-9',`-',`.',`+',`@'
    It is assumed that you are entering a number (or a numeric function, in the case of `@'), into the current cell.

`=' This is retained for compatibility with ``sc'' . It signals that you wish to enter a number/function in the current cell.

`"',`>',`<'
    These characters indicate that you want to enter a centered ("), right-justified (>), or left-justified (<) string (or string expression/function) into the cell.

    Note that when entering a string, a double quote (") is placed at the start of the input window. This is so the program can distinguish between constant strings (eg: "Beam Me Up!") and string functions or expressions (eg: @date(@now) ). If you are entering a string constant, just ignore the double quote and enter your string. A closing quote is not required. If you are entering a string function, just backspace over the quote to delete it, and then enter your function.

Default:
    The entry of any other character is taken to be a signal that you wish to enter a left-justified string. Unlike the previous item, in this instance no double quote is placed in the input buffer. This is nice, since most of the time you enter text this way, and don't have to deal with the double quote.

MENUS
The main (top-level) menu is invoked with the `/' key.

Menus are displayed on the top line of the screen. Each menu item is usually one (hopefully self-explanatory) word. Each menu item begins with a single letter (eg: ``F:File'').

The left-most item in a menu is initially highlighted. This is the ``menu-cursor''. By using the left/right arrow keys (or ^B/^F), the menu cursor can be moved left and right. As each menu item is highlighted, a one-line description of that command is displayed on the second line. Typing return will execute the currently selected menu item.

There is also a short-cut for choosing menu items: By typing the key corresponding to the first letter in any menu item- case is unimportant - you immediately select that menu item.

I tried to have all the highlighted letters match the first letter of their menu item, but unfortunately there had to be a few exceptions. Watch for those!

By entering <Delete> or <Backspace>, (your choice) you can back up one menu level.

By typing a <Space> you will abort out of a menu (no matter how deep you are into sub-menu's) back to the top-level of the program.

  Main Menu
F:File E:Edit C:Cell R:Row O:Column V:View I:Input M:Misc Q:Quit N:Name

With the exception of QuitandName, all menu items on the Main Menu invoke sub-menus. See below for explanations of those.

Quit
    Exit from the program. If there have been any changes in the spreadsheet since the last Load or Save command, ss asks about saving your data before exiting.

Name
    Display the current filename.

  File Sub-Menu
L:Load M:Merge S:Save A:SaveAs W:Write txt T:Tbl save(mode) Q:Quit

Load
    Load a new spreadsheet file from disk. Enter the name of a spreadsheet file to load, followed by <CR>. If encryption is enabled, the file is decrypted before it is loaded into the spreadsheet.

    NOTE: ss files are (currently) identical to ``sc'' data files.

Merge
    Merge the spreadsheet from the named file into the current one. Values and expressions defined in the named file are read into the current spreadsheet, overwriting the existing entries at matching cell locations.

Save
    Save the current spreadsheet into a file. If encryption is enabled, the file is encrypted before it is saved.

Save As
    Prompt the user to enter a filename, and then save the spreadsheet into a file with that name. If a <CR> is entered, the current default filename is used. The newly entered filename becomes the new default filename. If encryption is enabled, the file is encrypted before it is saved.

Write Txt
    Write a text-only listing of the current spreadsheet (No functions, etc) into a file in a form that matches its appearance on the screen.

    This differs from the ``Save'' commands in that files saved with those commands are intended to be reloaded with ``Load'', while ``Write txt'' produces a file for people to look at. Hidden rows or columns are not shown when the data is printed.

Table Save
    Write a text-only listing of the current spreadsheet to a file, but include delimiters suitable for processing by the tbl, LaTeX, TeX, or FrameMaker table processors.

    The tblstyle option (see the ``Table Style'' item on the Misc menu) controls which delimiters are output. The current setting of tblstyle is displayed in parentheses after the ``Tbl Save'' entry of the File menu. A question mark (?) indicates that no style has been defined (style 0).

Quit
    Exit from the program. This option is identical to the Quit option on the main top-most menu. (Actually the Quit option on the main top-most menu is identical to this option, but that really is irrelevant).

With the ``Save'', ``Write Text'', and ``Table Save'' commands, it is possible to save a subset of the spreadsheet to the output file. To do that, a range must be defined prior to invoking those commands. See the section below on Ranges, for instructions on defining a range.

With the ``Write Text'' and ``Table Save'' commands, if you try to write to the filename used with the most recent ``Load'' or ``Save/Save As'' commands, or to the file specified on the command line when ss was invoked, you are asked to confirm that the (potentially) dangerous operation is really what you want.

The four output commands, (``Save'', ``Save As'', ``Write Text'' and ``Table Save''), can pipe their (unencrypted only) output to a program. To use this feature, enter ``| program'' to the prompt asking for a filename. For example, to redirect the output of the ``Write Text'' command to the printer, you might enter ``| lpr -p''.

  Edit Sub-Menu
C:Copy E:Erase N:Name L:Lock U:Unlck F:Format I:Fill V:Valueize

Copy
    Copy a source range to a destination range. The source and destination may be different sizes. The result is always one or more full copies of the source. Copying a row to a row yields a row. Copying a column to a column yields a column. Copying a range to anything yields a range. Copying a row to a column or a column to a row yields a range with as many copies of the source as there are cells in the destination. This command can be used to duplicate a cell through an arbitrary range by making the source a single cell range such as b20:b20.

    The Source Range must be defined before selecting this command. You will be prompted to enter a destination range.

    BUG: You MUST enter a range, and the range WILL be copied. If you want to abort this operation the only current solution is to select your source range to also be your destination range. Then there will be a net effect of zero. This should be addressed in the next release.

Erase
    Clear a range. Cells cleared with this command may be recalled with the ``Yank'' or ``Merge'' commands under the Row or Column menus. (This is, of course, less than ideal - this awkwardness is an example of some of the problems that arose in converting from ``sc''.)

Name
    Invoke the Name sub-menu.

Lock
    This command will lock the current cell -- or a range of cells, if a range of cells is specified. Locking will make them immune to any type of editing. A locked cell can't be changed in anyway until it is unlocked.

UnLock
    In light of the previous command, the necessity of this command is obvious. This command will unlock a locked cell and make it editable.

Format
    Use this command to assign a value format string to a range of cells. See the section ``Formatting Cell Contents'' for details.

Fill
    Fill a range with constant values starting with a given value and increasing by a given increment. Each row is filled before moving on to the next row, if row order recalculation is set. Column order fills each column in the range before moving on to the next column. The start and increment numbers may be positive or negative. To fill all cells with the same value, give an increment of zero.

    Example: A Starting value and Increment of "2 5" (2 is the starting value, 5 is the increment) will result in the defined range being filled with the values 2 7 12 17 22 27 ...

    A Range must be defined before choosing this command or it will abort. (Filling a single cell is rather a silly thing to do).

Valueize
    Values only. This command removes the expressions from a range of cells, leaving just the values of the expressions.

    Example: A cell contains a function which currently evaluates to 12. Valueizing that cell would result in the function being removed, and the constant value 12 being inserted into the cell.

    BUG: ``Valueize'' is almost certainly not a real word.

The Copy and Erase parts of this section are rather klunky & kludgy. It needs work. One hoped for improvement is to re-do this section into a more Macintosh-like setup, with a CUT/COPY/PASTE type of interface. Hopefully this section will be cleaned up in the next release.

  Cell Sub-Menu
G:Goto M:Mark C:Copy marked cell L:edit Label V:edit Value

This menu deals with operations that affect the current cell only. All of these menu items have direct Control- or Function-Key equivalents. I suspect that the direct keyboard equivalents will prove to be more used than this menu. In which case, this menu may disappear with the next release.

Goto
    Go to a cell. ss prompts for a cell's name, a regular expression surrounded by quotes, or a number.

    If a cell's name such as ``ae122 '' or the name of a defined range is given, the cell cursor goes directly to that cell. If a quoted regular expression such as "Tax Table" or "^Jan [0-9]*$" is given, ss searches for a cell containing a string matching the regular expression. Note that you must use double quotes (") around a regular expression. See regex(3) or ed(1) for more details on the form of regular expressions.

    If a number is given, ss will search for a cell containing that number. Searches for either strings or numbers proceed forward from the current cell, wrapping back to a0 at the end of the table, and terminate at the current cell if the string or number is not found.

    You may also go to a cell with an ERROR (divide by zero, etc in this cell) or INVALID (references a cell containing an ERROR). Entering ``error'' (No quotes! Case unimportant) will take you to the next ERROR, while ``invalid'' takes you to the next invalid.

    The last goto command is saved, and can be re-issued by entering <return> at the Goto prompt.

Mark
    Mark a cell to be used as the source for the ``Copy Marked Cell'' command.

Copy Marked Cell
    Copy the last cell marked with the ``Mark'' command to the current cell, updating row and column references in its numeric or string expression, if any.

Edit Label

Edit Value
    Edit the string (value) associated with the current cell. A subset of ``emacs'' commands are used in this mode. See ``Emacs Command/Entry Editing'' below.

  Row & Column Sub-Menu's
I:Insert D:Delete Y:Yank M:Merge C:Copy H:Hide S:Show V:Valueize F:Fmt

With the exception of the ``Fmt'' item, the Row and Column Menus are identical. Fmt appears on the Column Menu only. The operations on the two menus are also identical, with the obvious explanation that Row menu commands operate on Rows, and Column menu commands operate on Columns.

Commands which move or copy cells also modify the row and column references in affected cell expressions. The references may be frozen by using the fixed operator or using the $ character in the reference to the cell. (See the section below: ``WORKING WITH SS'' - subsection ``Variable Names'')

Insert
    Insert some Rows or Columns. If a range is defined, insert the number of rows (columns) spanned by the range. If no range is defined, insert just one row (column). The new row (column) is empty.

    Rows (columns) will be inserted before the current one. In the case of a range, the `current' row (column) will be the top-most row (leftmost column).

Delete
    Delete some Rows or Columns. If a range is defined, delete the rows (columns) spanned by the range. If no range is defined, delete just the row (column) where the cell cursor is.

Yank
    Yank back a previously deleted set of cells, making room for them by inserting enough rows, or columns. They are inserted at the current cursor location.

    Note: Using the Row menu to Yank back a deleted Column will insert as many rows as were in the deleted column. The same is true of using the Column menu to yank back a deleted Row. These ``Features'' are probably bugs.

    Bug: (Feature?) This operation will also yank back cells erased with the ``Erase'' command on the Edit menu. In most of those cases though, you will probably want to use the Merge command to do that.

Merge
    This command also yanks back previously deleted cells. However, it does NOT insert rows or columns to make room for the yanked back material. The present contents of any cells (beginning at the current cell cursor location) will be overwritten.

    Unlike the yank command, a merged-back column will start at the current cell cursor location, it will NOT start in row 0. The same is true of merged-back rows.

    This command is the same, whether you select it through the Row menu or the Column menu.

    This operation will also yank back cells erased with the ``Erase'' command on the Edit menu.

    Note: This command really belongs on the Edit menu. However, it is temporarily staying here, to be by the Yank command, to which it is a ``partner''.

Copy
    Make a copy (actually, a duplicate) of the current row (column), and insert it into the spreadsheet to the right (below) of the current row (column).

    This command operates on only one row (column) at a time. Any defined range is ignored.

Hide
    Hide some rows (columns). If a range is defined, hide the number of rows (columns) spanned by the range. If no range is defined, hide just the current row (column).

    This keeps a row (column) from being displayed but keeps it in the spreadsheet. The status of the rows and columns is saved with the sheet so hidden rows and columns will be still be hidden when you reload the spreadsheet. Hidden rows or columns are not printed by the ``Write Txt'' command.

Show
    Show Hidden Row's (Columns). Shows the first hidden row(s) (columns) in the spreadsheet, starting at the top (left).

Valueize
    Valueize some rows (columns). If a range is defined, Valueize the number of rows (columns) spanned by the range. If no range is defined, valueize just the current row (column).

    See the section on ``Valueize'' under the Edit Menu (above) for more information.

Fmt (Format)
    This option appears on the Column menu only.

    Format the current column. (This is primarily useful for adjusting the column width.) There seems to be some overlap here between this function and the format function in the edit menu. (as you might have guessed, this function is a holdover from ``sc'' that I have not explored in any great depth.) SHOULD BE FIXED UP.

    (Here's the ``sc'' definition: Set the output format to be used for printing the numeric values in each cell in the current column. Enter three numbers: the total width in characters of the column, the number of digits to follow decimal points, and the format type. Format types are 0 for fixed point, 1 for scientific notation, 2 for engineering notation, and 3 for dates. Values are rounded off to the least significant digit displayed. )

  View Sub-Menu
C:Cell hiliting T:Top line disp. V:show Values E:show Expr. R:Recalc

The View menu contains operations that affect the users view of the spreadsheet.

Cell hiliting
    Enable/Disable Current cell highlighting. If enabled, the current cell is highlighted (using the terminal's standout mode, if available) in addition to being marked by the cell cursor. (DEFAULT: cell highlighting on)

Top line display
    Enable/Disable top line display of the current cell's contents. If enabled, the name and value of the current cell is displayed on the top line. If there is an associated label string, the first character of the string value is ``|'' for a centered string, ``<'' for a leftstring or ``>'' for a rightstring (see below), followed by "string" for a constant string or {expr} for a string expression. A constant string may be preceded with a backslash (`\'). In this case the constant string will be used as a ``wheel'' to fill a column, e.g. "\-" for a line in a column, and "\Yeh " for "Yeh Yeh Ye". If the cell has a numeric value, it follows as [value], which may be a constant or expression. (DEFAULT: top line display enabled)

Show Values
    Redraw the screen, highlighting all cells to be filled in. This is useful for finding values you need to provide or update in a form with which you aren't familiar or of which you have forgotten the details.

    It's also useful for checking a form you are creating. All cells which contain constant numeric values (not the result of a numeric expression) are highlighted temporarily, until the next screen change, however minor. To avoid ambiguity, the current range (if any) and current cell are not highlighted.

Show Expressions
    This command is similar to Show Values, but highlights cells which have expressions. It also displays the expressions in the highlighted cells as left-flushed strings, instead of the numeric values and/or label strings of those cells. This command makes it easier to check expressions, at least when they fit in their cells or the following cell(s) are blank so the expressions can overflow (like label strings). In the latter case, the overflow is not cleared on the next screen update, so you may want redraw the screen (via ^L) after this command in order to clean up the screen.

Recalc
    Recalculates the spreadsheet. (This is likely only useful if automatic recalculation is disabled. See the ``Input Sub-Menu'' below)

  Input Sub-Menu
A:Auto L:Label R:Rounding N:Newline action Z:Limits C:Cr terminate P:Pre-scale M:Macro The Input menu contains operations that control Input to the Spreadsheet.

Auto
    Enable/Disable automatic recalculation of the spreadsheet. When set, each change in the spreadsheet causes the entire spreadsheet be recalculated. Normally this is not noticeable, but for very large spreadsheets, it may be faster to clear automatic recalculation mode and update the spreadsheet via explicit requests to recalculate the spreadsheet. (DEFAULT: automatic recalculation on)

Label
    Enable/Disable automatic labeling of named ranges. If enabled, using the Define command (on the Name sub-menu) causes a label to be automatically generated in the cell to the left of the defined cell. This is only done if the cell to the left is empty. (DEFAULT: autolabeling enabled)

Rounding
    Selecting this menu item causes the spreadsheet to toggle between round-to-even (Also knowns as Banker's Round, the default) and round-to-infinity. In round-to-even, *.5 will round to the closest even number. Under round-to-infinity, *.5 will round up to the next integer.

Newline Action
    After each command which is terminated by a newline character is completed, one of three actions will occur:

    1) | No action (Default).
    2) | Move down one row.
    3) | Move right one column.
    4) | Move in the same direction
     | as the last Arrow key took us.

    This option toggles between those four actions.

Limits
    Set newline action limits. This option sets limits to the newline action option above. When this option is invoked, the row and column of the current cell are remembered. If a later newline action would take the current cell to the right of the remembered column, then the current cell is instead moved to the first column of the next row. If a newline action would take the current cell below the remembered row, then the current cell is instead moved to the top row of the next column.

The ``newline action'' and ``set newline action limits'' options can be combined to allow very quick entry of large amounts of data. If all the data to be entered is in a single row or column then setting the appropriate newline action will allow the numbers to be entered without any explicit commands to position the current cell.

If the data entry involves several entries in each row for many rows, then setting the quick numeric entry option, setting the newline action to move right after each entry and setting the newline action limits on the last column on which data should be entered will allow the data to entered quickly. If necessary, columns which do not need data to be entered can be hidden. Similar arrangements can be made for entering several rows of data in each column.

CR Terminate
    By default, when entering data into a cell, you can terminate data entry by using the Return key, or by using one of the 4 arrow keys. (See the section below on ENTERING DATA) This menu item toggles between the default method of data entry and CR-terminate data entry. In CR-terminated mode, data entry can only be terminated by the return key. This let's you use the Left/Right arrow keys to edit the data as you enter it.

    BUG: The setting of this flag is NOT saved in the data file between runs of the program.

Pre-Scale
    Dollar prescale. If enabled, all numeric constants (not expressions) which you enter are multiplied by 0.01 so you don't have to keep typing the decimal point if you enter lots of dollar figures.

Macro
    Invoke the Macro Sub-Menu.

  Misc Sub-Menu
!:Shell Cmd E:Ext fn's I:Iterations R:Recalc Order T:Table Sty X:Encrypt

Shell Command
    ss prompts for a shell command to run. End the command line with the <RETURN> key. If the environment variable SHELL is defined, that shell is run. If not, /bin/sh is used. Giving a null command line starts the shell in interactive mode. A second ``!'' repeats the previous shell command.

Ext Fn's
    External function execution. When disabled, external functions (see @ext() below) are not called. This saves a lot of time at each screen update. If disabled, and external functions are used anywhere, a warning is printed each time the screen is updated, and the result of @ext() is the value from the previous call, if any, or a null string. (DEFAULT: external function execution disabled)

Iterations
    Set the maximum number of recalculations before the screen is displayed again. Iterations is set to 10 by default.

Recalc Order
    Specify the order of cell evaluation when updating. This options toggles between column-wise and row-wise (the default) spreadsheet recalculation.

Table Style
    Invoke the Table Style Sub-Menu.

Encrypt
    Turn encryption of files on/off.

    NOTE: Encryption may not be available at your sight. See the ``-x'' item under OPTIONS above for further details.

  Macro Sub-Menu
R:Run D:Define

Run (Run macros) Since ss files are saved as ASCII files, it is possible to use them as primitive macro definition files. The ``Run'' command makes this easier. It's like the ``File/Merge'' command, but prints a saved path name as the start of the filename to merge in. The string to use is set with the ``Define'' command. To write macros, you must be familiar with the file format written by the ``File/Save'' commands. This facility is still primitive and could be much improved.

    Disclaimer: This code was lifted virtually unchanged from `sc'. I don't use it, haven't explored it, and therefore don't understand it. (Art Mulder)

Define
    Define a path for the ``Run'' command to use.

  Name Sub-Menu
D:Define Name E:Erase Name S:Show Names

This menu is invoked from the Edit menu.

Define Name
    Define a Name for a range of cells. If no range is currently defined, then define a name for the current cell.

    Names defined in this fashion are used by the program in future prompts, may be entered in response to prompts requesting a cell or range name, and are saved when the spreadsheet is saved. Names defined must be more than two alpha characters long to differentiate them from a column names, and must not have embedded special characters. Names may include the character ``_'' or numerals as long as they occur after the first three alpha characters.

Erase Name
    Erase the name assigned to a range of cells. If no range is currently defined, then prompt for a cell name to erase.

Show Names
    List all Names that have been assigned to cells, or ranges of cells. Pipe the output to 'sort' and then to a pager. Therefore the list of names is sorted, and it will not run off the top of your display. If the environment variable PAGER is set, its value is used as your pager, otherwise a (sytem dependent) default pager is used.

  Table Style Sub-Menu
N:None T:Tbl X:TeX L:LaTeX S:sLaTeX F:Frame

This menu is invoked from the Misc menu.

The Table Style menu controls which delimeters are used to separate the data when a text-only listing of the current spreadsheet is out via the Table Save option on the File menu. The possible choices are: None (also shown as style 0) to give plain colon delimited fields; tbl to give colon delimited fields, with tbl(1) control lines; TeX, LaTeX, sLaTeX, to give appropriate delimeters for those environments (SLaTeX = Scandinavian LaTeX) consisting of simple tabbed alignment with ampersands as delimiters; and Frame to produce a file suitable for reading into FrameMaker.

COMMANDS

A number of commands are accessible directly from the keyboard, via Control-keys, or Function-keys. These are primarily cursor movement commands (ie: up-arrow key, etc), but there are also a small number of control-keys which access other functions.

NOTE: In the following ``^'' indicates the use of the Control key. Hence, ^A means ``Hold down the Control key, while typing the `A' key''. Also, < > are used to identify ``named'' keys. So, <Delete> stands for the Delete Key.

There are also a few commands that are invoked by two keystrokes in succession. For example, `` ^X v '' means ``Type Control-X, then v'' (Case is unimportant, V or v is fine). Also, ``<Esc> v'' means ``Type <Esc>, then v''. In some cases, there exists more than one command sequence for the same thing. (Like ^B and <Left Arrow>). Both commands are then listed together, separated by a comma.

  Cursor Movement
These key sequences all move the cell cursor. When possible, I strove to use the same control-key sequences as the emacs text editor - no point in reinventing the wheel!

Moving Short Distances:

    ^B, <Left Arrow>
        Move left one cell.

    ^F, <Right Arrow>
        Move right one cell.

    ^P, <Up Arrow>
        Move up one cell.

    ^N, <Down Arrow>
        Move down one cell.

Moving Longer Distances:

    <Esc> <, <Home>
        Jump to cell A0.

    <Esc> >, <End>
        Jump to the last row of the current column.

    ^T  Jump to row 0 of the current column.

    ^A  Jump to the first cell in the current row (Column A).

    ^E  Jump to the last valid cell in the current row.

    <Esc> v, <PgUp>
        Jump a (half) page up.

    ^V, <PgDn>
        Jump a (half) page down.

    ^X <, <Shift><Left Arrow>
        Jump a (half) page left.

    ^X >, <Shift><Right Arrow>
        Jump a (half) page right.

Special Movement:

    <Esc> b
        Move the cursor backward to the previous valid cell.

    <Esc> f
        Move the cell cursor forward to the next valid cell. These two commands do not ``wrap around'' when the end of the spreadsheet is encountered.

    ^J  Jump the cursor to the end of a (user-specified) range. The user is prompted for a direction (Any of the Up,Down,Left,Right commands above), and the cell cursor is then jumped to the last valid cell in that direction.

        The user can enter a <Space> or <Return> to abort this procedure.

  Menu Short-Cuts
These commands all duplicate functions that are also available through menu's. They exist here because I felt that they would be used often enough to warrant a quicker access to their functionality.

Cell Menu Short-Cuts:

    ^G  Goto a Cell. See ``Goto'' on the Cell Menu.

    ^W  Mark a Cell for later copying. See ``Mark''.

    ^Y  Copy a previously marked cell to the current cell. See ``Copy''.

    ^X V
        Edit the Value of the Current Cell. See ``edit Value''.

    ^X L
        Edit the Label of the Current Cell. See ``edit Label''.

Edit Menu Short-Cuts:

    <Del>, <BackSpace>, ^D
        Erase the contents (Label and Value) of the current cell. This is similar to choosing the ``Erase'' item on the Edit Menu with no range defined, and therefore the ``Yank'' and ``Merge'' commands on the Row & Column menus will undo this deletion. See the relevant sections of this man page for more details.

Misc Menu Short-Cuts:

    ^L  Redraw the screen. (This isn't a menu shortcut, but it does belong with the next two commands).

    ^R  Redraw the Screen and Highlight all Values. See ``Show Values''

    ^K  Redraw the Screen and Highlight all Expressions. See ``Show Expr''

  Other Commands
These commands do not fit into either of the the two previous categories, so they are dumped here into that wonderful category known as ``Miscellaneous''.

<Tab>
    Toggle Range display/definition mode. See the section below on RANGES

<Return>
    (or ^M) The cell-cursor is moved in one of a number of directions. See ``/ Misc - Options - Return''.

^Z  Stop. On systems where this is possible, the program is stopped, and control is given to the shell.

ENTERING DATA (Emacs Command/Entry Editing)
ss frequently prompts the user to enter a line of data on the top line of the display. When entering such data, a number of Emacs-compatible commands are supported for the editing of the data as it is entered.

There are two kinds of these data input modes. In the general case, (Cursor Terminated), the user is simply entering a number, function, or label into the spreadsheet (See ``How Input Is Processed'' above). In that general case, input is terminated with a <Return> or with an arrow key (or ^N, ^P, ^F, ^B). When input is ended with an arrow key, the cell cursor is then moved in that direction. (This sounds confusing, but really it isn't.)

In the other case, (<CR> Terminated), the user is either editing the contents of a cell (through one of the cell editing commands discussed above), or is entering input in response to a question from the program. (For example: Enter the name of a filename to load). In this case, only a <CR> is accepted as terminating input.

  Input Editing Commands:

^A  Move the cursor to the beginning of the line

^B, <Left Arrow>
    Move the cursor left. This command obviously does not apply to the ``Cursor Terminated'' mode.

^G  Abort input. If you are editing a cell, this command will abort the operation and leave the cells contents unchanged.

^D  Delete the character ``under'' cursor.

^E  Move to the end of the line.

^F, <Right Arrow>
    Move the cursor right. This command obviously does not apply to the ``Cursor Terminated'' mode.

^H, <Del>
    Delete the character to the left of cursor.

^K  Kill from the cursor to the end of the line.

^L  Redraw the line.

^M, <Return>
    Terminate input.

^O  Toggle Overwrite (versus insert) mode. In Overwrite, text to the right of the cursor is overwritten instead of ``pushed'' right.

^T  Transpose the character to the left of the cursor, with the character ``under'' the cursor.

^Y  At the current cursor location, Yank back text killed with ^K.

FORMATTING CELL CONTENTS

The following characters can be used in building a format string:

    #   Digit placeholder. If the number has fewer digits on either side of the decimal point than there are `#' characters in the format, the extra `#' characters are ignored. The displayed number is rounded to the number of digit placeholders as are found to the right of the decimal point. If there are more digits in the number than there are digit placeholders on the left side of the decimal point, then those digits are displayed.

    0   Digit placeholder. Same as for `#' except that the number is padded with zeroes on either side of the decimal point. The number of zeroes used in padding is determined by the number of digit placeholders after the `0' for digits on the left side of the decimal point and by the number of digit placeholders before the `0' for digits on the right side of the decimal point.

    .   Decimal point. Determines how many digits are placed on the right and left sides of the decimal point in the number. Note that numbers smaller than 1 will begin with a decimal point if the left side of the decimal point contains only a `#' digit placeholder. Use a `0' placeholder to get a leading zero in decimal formats.

    %   Percentage. For each `%' character in the format, the actual number gets multiplied by 100 (only for purposes of formatting - the original number is left unmodified) and the `%' character is placed in the same position as it is in the format.

    ,   Thousands separator (comma). The presence of a `,' in the format (multiple commas are treated as one) will cause the number to be formatted with a `,' separating each set of three digits in the integer part of the number with numbering beginning from the right end of the integer.

    \   Quote. This character causes the next character to be inserted into the formatted string directly with no special interpretation.

    E- E+ e- e+
        Scientific format. Causes the number to formatted in scientific notation. The case of the `E' or `e' given is preserved. If the format uses a `+', then the sign is always given for the exponent value. If the format uses a `-', then the sign is only given when the exponent value is negative. Note that if there is no digit placeholder following the `+' or `-', then that part of the formatted number is left out. In general, there should be one or more digit placeholders after the `+' or `-'.

    ;   Format selector. Use this character to separate the format into two distinct formats. The format to the left of the `;' character will be used if the number given is zero or positive. The format to the right of the `;' character is used if the number given is negative.

    Some example formats:
    Integer | ``0'' or ``#''
    Fixed | ``0.00''
    Percentage | ``0%'' or ``0.00%''
    Scientific | ``0.00E+00''
    Currency | ``$#,0.00;($#,0.00)''

WORKING WITH RANGES

A Range is defined as being some rectangular block of cells. A range is identified by the cells in the top right and bottom left corners of the block. For example, the range C3:F5 refers to the rectangular block of cells:
C3 D3 | E3 F3
C4 D4 | E4 F4
C5 D5 | E5 F5

A number of commands operate upon ranges. Most of those commands will also function without a range, in that case there is some default effect. For example, the ``/-File-Save'' command will save the entire spreadsheet by default. If a range of cells is defined, then that command will instead just save the defined range of cells. In contrast, the ``/-Edit-Erase'' command will by default just erase the cell at the current cursor location. If a range is defined, it will erase the entire range of cells.

SS endeavours to follow the ``Select then execute'' philosophy, much like mouse-oriented systems do. For example, instead of choosing the erase command, and then entering a range of cells to be erase, you first select a range of cells, and then choose the erase command.

To start defining a range, use the <Tab> key. Then, use any of the cursor motion keys (arrow keys, PgDn, etc) to move your cursor. All cells making up the rectangular region between the current cell, and the cell where you first typed the <Tab> key, will be highlighted, indicating the range of cells you are defining.

Once you have highlighted the desired range of cells, simply use the menu commands, as always, to choose an operation to perform upon the range you have defined. See the above section on MENUS to find out which commands also apply to ranges.

If, for some reason, you decide that you don't want to do anything with the range you have defined, you can type the <Tab> key a second time to discontinue defining a range. The highlighted section will then be returned to normal video, and you will no longer have a range defined.

WORKING WITH SS

  Spreadsheet Update
Re-evaluation of spreadsheet expressions is done by row or by column depending on the selected calculation order. Evaluation is repeated up to iterations times for each update if necessary, so forward references usually work as expected. If stability has not been reached after all those repeated evaluating of the spreadsheet expressions, a warning is printed. This is usually due to a long series of forward references, or to unstable cyclic references (for example, set A0's expression to ``A0+1'').

See ``Recalc Order'' under the Misc Menu above for how to choose row or column evalution order, and ``Iterations'' for how to change the value of iterations.

  About Cells
Cells can contain both a numeric value and a string value. Either value can be the result of an expression, but not both at once, i.e. each cell can have only one expression associated with it. Entering a valid numeric expression alters the cell's previous numeric value, if any, and replaces the cell's previous string expression, if any, leaving only the previously computed constant label string. Likewise, entering a valid string expression alters the cell's the previous label string, if any, and replaces the cell's previous numeric expression, if any, leaving only the previously computed constant numeric value.

  Variable Names
Normally, a variable name is just the name of a cell, such as K20. The value is the numeric or string value of the cell, according to context.

When a cell's expression (formula) is copied to another location via copy or range-copy, variable references are by default offset by the amount the formula moved. This allows the new formula to work on new data. If cell references are not to change, you can either use the fixed operator (see example below), or one of the following variations on the cell name.

K20 References cell K20; the reference changes when the formula is copied.

$K$20
    Always refers to cell K20; the reference stays fixed when the formula is copied.

$K20
    Keeps the column fixed at column K; the row is free to vary.

K$20
    Keeps the row fixed at row 20; the column is free to vary.

These conventions also hold on defined ranges. Range references vary when formulas containing them are copied. If the range is defined with fixed variable references, the references do not change.

fixed
    To make a variable not change automatically when a cell moves, put the word fixed in front of the reference, for example: B1 * fixed C3.

  Numeric Expressions
Numeric expressions have a fairly conventional syntax. Terms may be constants, variable names, parenthesized expressions, and negated terms. Ranges may be operated upon with range functions such as sum (@sum()) and average (@avg()). Terms may be combined using binary operators.

-e  Negation.

e+e Addition.

e-e Subtraction.

e*e Multiplication.

e/e Division.

e1%e2
    e1 mod e2.

e^e Exponentiation.

e<e
e<=e
e=e
e!=e
e>=e
e>e Relationals: true (1) if and only if the indicated relation holds, else false (0). Note that ``<='', ``!='', and ``>='' are converted to their ``~()'' equivalents.

~e  Boolean operator NOT.

e&e Boolean operator AND.

e|e Boolean operator OR.

@if(e,e,e)
e?e:e
    Conditional: If the first expression is true then the value of the second is returned, otherwise the value of the third.
Operator precedence from highest to lowest is:
    -, ~ ^ *, / +, - <, <=, =, !=, >=, > & | ?:

  String Expressions
String expressions are made up of constant strings (characters surrounded by double quotation marks), variables (cell names, which refer to the cells's label strings or expressions), and string functions. Note that string expressions are only allowed when entering a cell's label string, not its numeric part. Also note that string expression results may be left or right flushed or centered, according to the type of the cell's string label.
#   Concatenate strings. For example, the string expression
        A0 # "zy dog"
    displays the string ``the lazy dog'' in the cell if the value of A0's string is ``the la''.

FUNCTIONS

  Cell Functions
@myrow, @mycol Are functions that return the row or column of the current cell respectively. ex: The cell directly above a cell in the D column could then be accessed by @nval("d",@myrow-1). NOTE: @myrow and @mycol can't be used in specifying ranges.

  Range Functions
These functions return numeric values.
@sum(r)
    Sum all valid (non-blank) entries in the region whose two corners are defined by the two variable names (e.g. c5:e14) or the range name specified.
@prod(r)
    Multiply together all valid (non-blank) entries in the specified region.
@avg(r)
    Average all valid (non-blank) entries in the specified region.
@count(r)
    Count all valid (non-blank) entries in the specified region.
@max(r)
    Return the maximum value in the specified region. See also the multi argument version of @max below.
@min(r)
    Return the minimum value in the specified region. See also the multi argument version of @min below.
@stddev(r)
    Return the sample standard deviation of the cells in the specified region.
@lookup(e,r)
@lookup(se,r)
    Evaluates the expression e (or se) and then searches through the range r for a matching value. The range should be either a single row or a single column. The expression can be either a string expression or a numeric expression. If it is a numeric expression, the range is searched for the the last value less than or equal to e. If the expression is a string expression, the string portions of the cells in the range are searched for an exact string match. The value returned is the numeric value from the next row and the same column as the match, if the range was a single row, or the value from the next column and the same row as the match if the range was a single column.

@hlookup(e,r,n)
@hlookup(se,r,n)
    Evaluates the expression e (or se) and then searches through the first row in the range r for a matching value. The expression can be either a string expression or a numeric expression. If it is a numeric expression, the row is searched for the the last value less than or equal to e. If the expression is a string expression, the string portions of the cells in the row are searched for an exact string match. The value returned is the numeric value from the same column n rows below the match.

@vlookup(e,r,n)
@vlookup(se,r,n)
    Evaluates the expression e (or se) and then searches through the first column in the range r for a matching value. The expression can be either a string expression or a numeric expression. If it is a numeric expression, the column is searched for the the last value less than or equal to e. If the expression is a string expression, the string portions of the cells in the column are searched for an exact string match. The value returned is the numeric value from the same row n columns to the right of the match.

@index(e,r)
    Use the value of the expression e to index into the range r. The numeric value at that position is returned. The value 1 selects the first item in the range, 2 selects the second item, etc. The range r should be either a single row or a single column.

@stindex(e,r)
    Use the value of e to index into the range r. The string value at that position is returned. The value 1 selects the first item in the range, 2 selects the second item, etc. The range r should be either a single row or a single column.

  Numeric Functions
All of these functions operate on floating point numbers (doubles) and return numeric values. Most of them are standard system functions more fully described in math(3). The trig functions operate with angles in radians.

@sqrt(e)
    Return the square root of e.

@exp(e)
    Return the exponential function of e.

@ln(e)
    Return the natural logarithm of e.

@log(e)
    Return the base 10 logarithm of e.

@floor(e)
    Return the largest integer not greater than e.

@ceil(e)
    Return the smallest integer not less than e.

@rnd(e)
    Round e to the nearest integer. default: round-to-even (banker's round), *.5 will round to the closest even number;

@round(e,n)
    Round e to n decimal places. n may be positive to round off the right side of the decimal, and negative to round off the left side. See @rnd(e) above for rounding types.

@abs(e)
@fabs(e)
    Return the absolute value of e.
@pow(e1,e2)
    Return e1 raised to the power of e2.
@hypot(e1,e2)
    Return sqrt(e1*e1+e2*e2), taking precautions against unwarranted overflows.
pi  @pi
    A constant quite close to pi.
@dtr(e)
    Convert e in degrees to radians.
@rtd(e)
    Convert e in radians to degrees.
@sin(e)
@cos(e)
@tan(e)
    Return trigonometric functions of radian arguments. The magnitude of the arguments are not checked to assure meaningful results.

@asin(e)
    Return the arc sine of e in the range -pi/2 to pi/2.

@acos(e)
    Return the arc cosine of e in the range 0 to pi.

@atan(e)
    Return the arc tangent of e in the range -pi/2 to pi/2.

@atan2(e1,e2)
    Returns the arc tangent of e1/e2 in the range -pi to pi.

@max(e1,e2,...)
    Return the maximum of the values of the expressions. Two or more expressions may be specified. See also the range version of @max above.

@min(e1,e2,...)
    Return the minimum of the values of the expressions. Two or more expressions may be specified. See also the range version of @min above.

@ston(se)
    Convert string expression se to a numeric value.

@eqs(se1,se2)
    Return 1 if string expression se1 has the same value as string expression se2, 0 otherwise.

@nval(se,e)
    Return the numeric value of a cell selected by name. String expression se must evaluate to a column name (``A''-``ZZ'') and e must evaluate to a valid row number (The number of rows is system dependant). If se or e is out of bounds, or the cell has no numeric value, the result is 0. You can use this for simple table lookups. Be sure the table doesn't move unexpectedly! See also @sval() below.

  String Functions
@substr(se,e1,e2)
    Extract and return from string expression se the substring indexed by character number e1 through character number e2 (defaults to the size of se if beyond the end of it). If e1 is less than 1 or greater than e2, the result is the null string. For example,

        @substr ("Nice jacket", 4, 7)

    returns the string ``e jac''.

@fmt(se,e)
    Convert a number to a string. The argument se must be a valid printf(3) format string. e is converted according to the standard rules. For example, the expression

        @fmt ("**%6.3f**", 10.5)

    yields the string ``**10.500**''. e is a double, so applicable formats are e, E, f, g, and G. Try ``%g'' as a starting point.

@sval(se,e)
    Return the string value of a cell selected by name. String expression se must evaluate to a column name (``A''-``ZZ'') and e must evaluate to a valid row number (The number of rows is system dependant). If se or e is out of bounds, or the cell has no string value, the result is the null string. You can use this for simple table lookups. Be sure the table doesn't move unexpectedly!

@upper(e)
    and @lower(e) will change the string expression to upper or lower case.

@capital(e)
    will convert the first letter of words in a string into upper case and other letters to lower case (the latter if all letters of the string are upper case).

@ext(se,e)
    Call an external function (program or script). The purpose is to allow arbitrary functions on values, e.g. table lookups and interpolations. String expression se is a command or command line to call with popen(3). The value of e is converted to a string and appended to the command line as an argument. The result of @ext() is a string: the first line printed to standard output by the command. The command should emit exactly one output line. Additional output, or output to standard error, messes up the screen. @ext() returns a null string and prints an appropriate warning if external functions are disabled, se is null, or the attempt to run the command fails.

    External functions can be slow to run, and if enabled are called at each screen update, so they are disabled by default.

    A simple example:

        @ext ("echo", a1)

    You can use @ston() to convert the @ext() result back to a number. For example:

        @ston (@ext ("form.sc.ext", a9 + b9))

    Note that you can built a command line (including more argument values) from a string expression with concatenation. You can also "hide" the second argument by ending the command line (first argument) with `` #'' (shell comment).

@coltoa(e)
    Returns a string name for a column from the numeric argument. For example:

        @coltoa(@mycol-1)
        @nval(coltoa(@mycol-1), @myrow+1)

  Financial Functions
Financial functions compute the mortgage (or loan) payment, future value, and the present value functions. Each accepts three arguments, an amount, a rate of interest (per period), and the number of periods. These functions are the same as those commonly found in other spreadsheets and financial calculators

@pmt(e1,e2,e3)
    @pmt(60000,.01,360) computes the monthly payments for a $60000 mortgage at 12% annual interest (.01 per month) for 30 years (360 months).

@fv(e1,e2,e3)
    @fv(100,.005,36) computes the future value for of 36 monthly payments of $100 at 6% interest (.005 per month). It answers the question: "How much will I have in 36 months if I deposit $100 per month in a savings account paying 6% interest compounded monthly?"

@pv(e1,e2,e3)
    @pv(1000,.015,36) computes the present value of an a ordinary annuity of 36 monthly payments of $1000 at 18% annual interest. It answers the question: "How much can I borrow at 18% for 30 years if I pay $1000 per month?"

  Date and Time Functions
Time for ss follows the system standard: the number of seconds since 1970. All date and time functions except @date() return numbers, not strings.

@now
    Return the current time encoded as the number of seconds since the beginning of the epoch (December 31, 1969, midnight, GMT.)

@dts(e1,e2,e3)
    @dts(9,14,1988) converts the date September 14, 1988 to the number of seconds from the epoch to the first second of 9/14/88, local time. For example, @date(@dts(12,14,1976)) yields

    Tue Dec 14 00:00:00 1976

    The month should be range from 1 to 12, the day should range from 1 to the number of days in the specified month, and the year should range from 1970 to 1999. (Hey! That isnt't that far off! What then? ;-)

@tts(e1,e2,e3)
    @tts(8,20,45) converts the time 8:40:45 to the number of seconds since midnight, the night before. The hour should range from 0 to 23; the minutes and seconds should range from 0 to 59.

The following functions take the time in seconds (e.g. from @now) as an argument and return the specified value. The functions all convert from GMT to local time.

@date(e)
    Convert the time in seconds to a date string 24 characters long in the following form:

    Sun Sep 16 01:03:52 1973

    Note that you can extract parts of this fixed-format string with @substr().

@year(e)
    Return the year. Valid years begin with 1970. The last legal year is system dependent.

@month(e)
    Return the month, encoded as 1 (January) to 12 (December).

@day(e)
    Return the day of the month, encoded as 1 to 31.

@hour(e)
    Return the number of hours since midnight, encoded as 0 to 23.

@minute(e)
    Return the number of minutes since the last full hour, encoded as 0 to 59.

@second(e)
    Return the number of seconds since the last full minute, encoded as 0 to 59.

SEE ALSO
bc(1), dc(1), crypt(1), pss(1), sc(1)

BUGS
Top-to-bottom, left-to-right evaluation of expressions is silly. A proper following of the dependency graph with (perhaps) recourse to relaxation should be implemented.

Only one previous value is saved from any call of @ext(). If it is used more than once in a spreadsheet and external functions are enabled and later disabled, the last returned value pops up in several places.

On some systems, if the cell cursor is in column 0 with topline enabled (so the current cell is highlighted), or if any cell in column 0 is highlighted, the corresponding row number gets displayed and then blanked during a screen refresh. This looks like a bug in curses.

Many commands give no indication (a message or beep) if they have null effect. Some should give confirmation of their action, but they don't.

AUTHORS
This is a much modified version of a public domain spread sheet originally authored by James Gosling, and subsequently modified and posted to USENET by Mark Weiser under the name vc.

The program was subsequently renamed sc, and further modified by numerous contributors, Jeff Buhrt of Proslink, Inc. ({sequent, uunet}!sawmill!prslnk!buhrt) and Robert Bond of Sequent, prominent among them.

Finally, Art Mulder ( art@cs.ualberta.ca ) -in one of those classic ``it seemed like a good idea at the time'' moves - took sc version 6.19 and radically overhauled its user interface, to create ss.

Apologies are freely offered to all sc adherents offended by what has been done to ``their'' program.

COPYRIGHT
Copyright (c) 1992,1993 by Arthur E. Mulder.

All Rights Reserved

Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of any persons or organizations involved not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission.

ALL PERSONS AND ORGANIZATIONS INVOLVED IN THE CREATION OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ANY OF THEM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Translation: I'm not trying to restrict anyone's free use of ``ss'', I just don't want anyone turning around and (a) claiming that they wrote it or (b) selling it.