# The grid

The grid is a matrix of characters that represents what is seen on a screen. It
has a fixed number of columns (COLS) and lines (LINES) and maintains a current
position (pos) as a single number encoded as "y*COLS+x".

The grid is implemented as a IO stream [doc/io/stream].  Its "pos" field is the
"cursor" position on the screen and the IO screen represents the terminal
screen: whenever a byte is written to it through the IO methods, the character
is written at cursor position and that cursor is advanced by one.

If a NL character ($0a) is written to it, the grid skips to the next line. If a
BS character ($08) is written to it, the cursor goes back one character.

In newline conditions (NL character or wrapping around the end of line), we
clear the next line and move the cursor there. If we're at the end of the
screen, we scroll if the underlying driver allows it. Otherwise, we wrap around
to the top.

The grid unit defines a "grid" value [doc/lib/bm], representing the active grid.
Setting it to a structure created through "newgrid" changes the active grid.

## Spit mode

Sometimes, we want to write things to screen that are at a position other than
the cursor and we don't want to update the cursor while writing there. Moreover,
we don't want the special handling of the regular mode (newline handling). One
such example is the "dbgnum1!" word.

In these cases, you'll want to enable the "spit" mode with "spiton", do your
thing, then go back to regular mode with "spitoff".

## API

Fields:

COLS
  Width, in characters, of the grid.

LINES
  Height, in characters, of the grid.

pos
  Current position of the cursor

spitpos
  Position of the "spit" mode. When -1, spit mode is inactive.

highlight
  Boolean flag indicating whether written cells should be "highlighted".
  Changing this flag doesn't affect existing contents on the screen, only newly
  written content.

Methods:

cell! ( c pos grid -- )
  Set content of the cell at "pos" to character "c". Should honor the
  "highlight" flag.

cursor! ( pos grid -- )
  Move cursor to "pos".

newln ( oldln grid -- newln )
  Prepare new line under line number "newln" and return the line number of that
  prepared line as "newln". Normally, "newln" is "oldln+1", but if scrolling is
  involved, then "newln" will be "oldln".

Words:

highlight! ( f grid -- )
  Set "highlight" field to "f".

pcell! ( c grid -- )
  Set content of the cell at current pos to character "c".

pos! ( pos grid -- )
  Set current pos to "pos" and update cursor position.

clrline ( ln grid -- )
  Set all cells in line number "ln" to spaces.

linefeed ( grid -- )
  Clear a new line below the current one, scrolling if needed, then set pos to
  the beginning of that line

spiton ( pos grid -- )
  Enable "spit mode" starting at position "pos". This doesn't affect regular
  position.

spitoff ( grid -- )
  Disable "spit mode".

dbgnum1! ( n grid -- )
  Spit "n", formatted with ".x", at the top right corner of the screen. Useful
  for debugging purposes. To debug live numbers, you can combine this with
  sys/loop.

dbgnum2! ( n grid -- )
  Same as :dbgnum1!, but one slot to the left.

grid# ( -- )
  Check that a grid is setup and errors out if it's not.

gridtest ( -- )
  Fill the grid with characters between $20 and $60 by calling :cell!
  repeatedly, alternating the "highlight" flag on each line.
