--
--      Shared screen
--      Copyright (C) 1997  P.H. Welch
--      Modified 2005 Jonathan Whiting, Fred Barnes
--
--	This library is free software; you can redistribute it and/or
--	modify it under the terms of the GNU Lesser General Public
--	License as published by the Free Software Foundation; either
--	version 2 of the License, or (at your option) any later version.
--
--	This library is distributed in the hope that it will be useful,
--	but WITHOUT ANY WARRANTY; without even the implied warranty of
--	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--	Lesser General Public License for more details.
--
--	You should have received a copy of the GNU Lesser General Public
--	License along with this library; if not, write to the Free Software
--	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
--

--** Shared screen library.
--
-- To use this library:
--
-- [@code
-- #INCLUDE "shared_screen.module"]
--
-- @module shared_screen

#INCLUDE "consts.inc"
#INCLUDE "shared_screen.inc"
#USE "course.lib"

--{{{  PROC fg.col (VAL COLOUR c, CHAN BYTE out!)
--* Set foreground colour.
-- Generate a VT220 control sequence to set the terminal colour.
-- @param c Colour to set; see [@ref COLOURS]
-- @param out Channel to write to
PROC fg.col (VAL COLOUR c, CHAN BYTE out!)
  --{{{  
  VAL COLOUR set.fg IS 30:
  IF
    c = default
      SEQ
        out ! ESCAPE
        out.string ("[0m", 0, out!)
        out ! FLUSH
    c > bold.white
      SKIP
    TRUE
      SEQ
        out ! ESCAPE
        out ! '['
        IF
          c > white
            SEQ
              out ! '1'
              out ! ';'
              out.byte (BYTE ((c - bold.black) + set.fg), 0, out!)
          TRUE
            SEQ
              out ! '0'
              out ! ';'
              out.byte (BYTE (c + set.fg), 0, out!)
        out ! 'm'
        out ! FLUSH
  --}}}
:
--}}}
--{{{  PROC screen.interpret (VAL []SCREEN.NODE node, CHAN BYTE out!)
--* Interpret an array of screen update commands.
-- @param node Commands to interpret; see [@ref SCREEN.NODE]
-- @param out Channel to write to
PROC screen.interpret (VAL []SCREEN.NODE node, CHAN BYTE out!)
  SEQ i = 0 FOR SIZE node
    VAL SCREEN.NODE node IS node[i]:
    CASE node[tag]
      --{{{  coordinates.tag
      coordinates.tag
        cursor.x.y (node[a], node[b], out!)
      --}}}
      --{{{  colour.tag
      colour.tag
        fg.col (COLOUR node[a], out!)
      --}}}
      --{{{  byte.tag
      byte.tag
        out.byte (node[a], 0, out!)
      --}}}
      --{{{  character.tag
      character.tag
        out ! node[a]
      --}}}
      --{{{  left.tag
      left.tag
        cursor.left (node[a], out!)
      --}}}
      --{{{  right.tag
      right.tag
        cursor.right (node[a], out!)
      --}}}
      --{{{  up.tag
      up.tag
        cursor.up (node[a], out!)
      --}}}
      --{{{  down.tag
      down.tag
        cursor.down (node[a], out!)
      --}}}
      --{{{  draw.left.tag
      draw.left.tag
        SEQ i = 0 FOR INT node[b]
          SEQ
            out ! node[a]
            cursor.left (2, out!)
      --}}}
      --{{{  draw.right.tag
      draw.right.tag
        SEQ i = 0 FOR INT node[b]
          out ! node[a]
      --}}}
      --{{{  draw.up.tag
      draw.up.tag
        SEQ i = 0 FOR INT node[b]
          SEQ
            out ! node[a]
            cursor.left (1, out!)
            cursor.up (1, out!)
      --}}}
      --{{{  draw.down.tag
      draw.down.tag
        SEQ i = 0 FOR INT node[b]
          SEQ
            out ! node[a]
            cursor.left (1, out!)
            cursor.down (1, out!)
      --}}}
      --{{{  erase.eol.tag
      erase.eol.tag
        erase.eol (out!)
      --}}}
      --{{{  erase.bol.tag
      erase.bol.tag
        erase.bol (out!)
      --}}}
      --{{{  erase.line.tag
      erase.line.tag
        erase.line (out!)
      --}}}
      --{{{  erase.eos.tag
      erase.eos.tag
        erase.eos (out!)
      --}}}
      --{{{  erase.bos.tag
      erase.bos.tag
        erase.bos (out!)
      --}}}
      --{{{  erase.screen.tag
      erase.screen.tag
        erase.screen (out!)
      --}}}
      --{{{  cursor.visible.tag
      cursor.visible.tag
        SEQ
          cursor.visible (out!)
          out ! FLUSH
      --}}}
      --{{{  cursor.invisible.tag
      cursor.invisible.tag
        SEQ
          cursor.invisible (out!)
          out ! FLUSH
      --}}}
      --{{{  flush.tag
      flush.tag
        out ! FLUSH
      --}}}
:
--}}}
--{{{  PROC screen.driver (CHAN SCREEN.CONTROL in?, CHAN BYTE out!)
--* Shared screen process.
-- Manage a VT220 terminal display.
-- @param in Command input channel (see [@ref SCREEN.CONTROL])
-- @param out Channel to write to
PROC screen.driver (CHAN SCREEN.CONTROL in?, CHAN BYTE out!)
  --{{{  
  BOOL running:
  SEQ
    running := TRUE
    WHILE running
      in ? CASE
        --{{{  atomic
        --{{{  coordinates
        COORDINATES p:
        coordinates; p
          cursor.x.y (p[X], p[Y], out!)
        --}}}
        --{{{  colour
        COLOUR c:
        colour; c
          fg.col (c, out!)
        --}}}
        --{{{  string
        BYTE size:
        [255]BYTE s:
        string; size::s
          out.string ([s FOR (INT size)], 0, out!)
        --}}}
        --{{{  byte
        BYTE b:
        byte; b
          out.byte (b, 0, out!)
        --}}}
        --{{{  character
        BYTE b:
        character; b
          out ! b
        --}}}
        --{{{  integer
        INT n:
        integer; n
          out.int (n, 0, out!)
        --}}}
        --{{{  left
        BYTE b:
        left; b
          cursor.left (b, out!)
        --}}}
        --{{{  right
        BYTE b:
        right; b
          cursor.right (b, out!)
        --}}}
        --{{{  up
        BYTE b:
        up; b
          cursor.up (b, out!)
        --}}}
        --{{{  down
        BYTE b:
        down; b
          cursor.down (b, out!)
        --}}}
        --{{{  draw.left
        BYTE b, n:
        draw.left; b; n
          SEQ i = 0 FOR INT n
            SEQ
              out ! b
              cursor.left (2, out!)
        --}}}
        --{{{  draw.right
        BYTE b, n:
        draw.right; b; n
          SEQ i = 0 FOR INT n
            out ! b
        --}}}
        --{{{  draw.up
        BYTE b, n:
        draw.up; b; n
          SEQ i = 0 FOR INT n
            SEQ
              out ! b
              cursor.left (1, out!)
              cursor.up (1, out!)
        --}}}
        --{{{  draw.down
        BYTE b, n:
        draw.down; b; n
          SEQ i = 0 FOR INT n
            SEQ
              out ! b
              cursor.left (1, out!)
              cursor.down (1, out!)
        --}}}
        --{{{  erase.eol
        erase.eol
          erase.eol (out!)
        --}}}
        --{{{  erase.bol
        erase.bol
          erase.bol (out!)
        --}}}
        --{{{  erase.line
        erase.line
          erase.line (out!)
        --}}}
        --{{{  erase.eos
        erase.eos
          erase.eos (out!)
        --}}}
        --{{{  erase.bos
        erase.bos
          erase.bos (out!)
        --}}}
        --{{{  flush
        flush
          out ! FLUSH
        --}}}
        --}}}
        --{{{  structured
        --{{{  pcs
        COORDINATES.COLOUR pc:
        BYTE size:
        [255]BYTE s:
        pcs; pc; size::s
          SEQ
            cursor.x.y (pc[X], pc[Y], out!)
            fg.col (pc[col], out!)
            out.string ([s FOR (INT size)], 0, out!)
            out ! FLUSH
        --}}}
        --{{{  pci
        COORDINATES.COLOUR pc:
        INT n:
        pci; pc; n
          SEQ
            cursor.x.y (pc[X], pc[Y], out!)
            fg.col (pc[col], out!)
            out.int (n, 0, out!)
            out ! FLUSH
        --}}}
        --{{{  pcsi
        COORDINATES.COLOUR pc:
        BYTE size:
        [255]BYTE s:
        INT n:
        pcsi; pc; size::s; n
          SEQ
            cursor.x.y (pc[X], pc[Y], out!)
            fg.col (pc[col], out!)
            out.string ([s FOR (INT size)], 0, out!)
            out.int (n, 0, out!)
            out ! FLUSH
        --}}}
        --{{{  pcis
        COORDINATES.COLOUR pc:
        BYTE size:
        [255]BYTE s:
        INT n:
        pcis; pc; n; size::s
          SEQ
            cursor.x.y (pc[X], pc[Y], out!)
            fg.col (pc[col], out!)
            out.int (n, 0, out!)
            out.string ([s FOR (INT size)], 0, out!)
            out ! FLUSH
        --}}}
        --{{{  pcb
        COORDINATES.COLOUR pc:
        BYTE b:
        pcb; pc; b
          SEQ
            cursor.x.y (pc[X], pc[Y], out!)
            fg.col (pc[col], out!)
            out.byte (b, 0, out!)
            out ! FLUSH
        --}}}
        --{{{  pcsb
        COORDINATES.COLOUR pc:
        BYTE size:
        [255]BYTE s:
        BYTE b:
        pcsb; pc; size::s; b
          SEQ
            cursor.x.y (pc[X], pc[Y], out!)
            fg.col (pc[col], out!)
            out.string ([s FOR (INT size)], 0, out!)
            out.byte (b, 0, out!)
            out ! FLUSH
        --}}}
        --{{{  pcbs
        COORDINATES.COLOUR pc:
        BYTE size:
        [255]BYTE s:
        BYTE b:
        pcbs; pc; b; size::s
          SEQ
            cursor.x.y (pc[X], pc[Y], out!)
            fg.col (pc[col], out!)
            out.byte (b, 0, out!)
            out.string ([s FOR (INT size)], 0, out!)
            out ! FLUSH
        --}}}
        --{{{  pc.draw.left
        COORDINATES.COLOUR pc:
        BYTE b, n:
        pc.draw.left; pc; b; n
          SEQ
            cursor.x.y (pc[X], pc[Y], out!)
            fg.col (pc[col], out!)
            SEQ i = 0 FOR INT n
              SEQ
                out ! b
                cursor.left (2, out!)
            out ! FLUSH
        --}}}
        --{{{  pc.draw.right
        COORDINATES.COLOUR pc:
        BYTE b, n:
        pc.draw.right; pc; b; n
          SEQ
            cursor.x.y (pc[X], pc[Y], out!)
            fg.col (pc[col], out!)
            SEQ i = 0 FOR INT n
              out ! b
            out ! FLUSH
        --}}}
        --{{{  pc.draw.up
        COORDINATES.COLOUR pc:
        BYTE b, n:
        pc.draw.up; pc; b; n
          SEQ
            cursor.x.y (pc[X], pc[Y], out!)
            fg.col (pc[col], out!)
            SEQ i = 0 FOR INT n
              SEQ
                out ! b
                cursor.left (1, out!)
                cursor.up (1, out!)
            out ! FLUSH
        --}}}
        --{{{  pc.draw.down
        COORDINATES.COLOUR pc:
        BYTE b, n:
        pc.draw.down; pc; b; n
          SEQ
            cursor.x.y (pc[X], pc[Y], out!)
            fg.col (pc[col], out!)
            SEQ i = 0 FOR INT n
              SEQ
                out ! b
                cursor.left (1, out!)
                cursor.down (1, out!)
            out ! FLUSH
        --}}}
        --{{{  c.erase.eol
        COORDINATES p:
        c.erase.eol; p
          SEQ
            cursor.x.y (p[X], p[Y], out!)
            erase.eol (out!)
            out ! FLUSH
        --}}}
        --{{{  c.erase.bol
        COORDINATES p:
        c.erase.bol; p
          SEQ
            cursor.x.y (p[X], p[Y], out!)
            erase.bol (out!)
            out ! FLUSH
        --}}}
        --{{{  c.erase.line
        COORDINATES p:
        c.erase.line; p
          SEQ
            cursor.x.y (p[X], p[Y], out!)
            erase.line (out!)
            out ! FLUSH
        --}}}
        --{{{  c.erase.eos
        COORDINATES p:
        c.erase.eos; p
          SEQ
            cursor.x.y (p[X], p[Y], out!)
            erase.eos (out!)
            out ! FLUSH
        --}}}
        --{{{  c.erase.bos
        COORDINATES p:
        c.erase.bos; p
          SEQ
            cursor.x.y (p[X], p[Y], out!)
            erase.bos (out!)
            out ! FLUSH
        --}}}
        --{{{  erase.screen
        erase.screen
          SEQ
            erase.screen (out!)
            out ! FLUSH
        --}}}
        --{{{  cursor.visible
        cursor.visible
          SEQ
            cursor.visible (out!)
            out ! FLUSH
        --}}}
        --{{{  cursor.invisible
        cursor.invisible
          SEQ
            cursor.invisible (out!)
            out ! FLUSH
        --}}}
        --{{{  interpret
        [255]SCREEN.NODE node:
        BYTE size:
        interpret; size::node
          SEQ
            screen.interpret ([node FOR INT size], out!)
            out ! FLUSH
        --}}}
        --{{{  poison
        poison
          SEQ
            out ! FLUSH
            running := FALSE
        --}}}
        --}}}
  --}}}
:
--}}}
