(*******************************************************************)
(** Release history:                                              **)
(**    17th January 1985   version 1.0.0 First port to new world  **)
(*******************************************************************)
IMPLEMENTATION MODULE Graphics;
(*
    Title    :  Graphics
    LastEdit :  Thu Jan 10 17:48:42 1985
    Author   :  Graham Toal
    Acorn Computers VLSI Design Aids Group
*)
IMPORT GenDict;
IMPORT BBC, HP;
IMPORT Defaults;
IMPORT Dict;
IMPORT Strings;
FROM Dict IMPORT DICT, KeyAttr;
FROM GraphicsIP IMPORT gstreamIP, colourIP, textIP, markerIP, cursorIP;
FROM Polysys IMPORT POLYGON;
FROM Streams IMPORT Stream;
TYPE
  gstream = gstreamIP;
  colour = colourIP;
  text = textIP;
  marker = markerIP;
  cursor = cursorIP;
VAR DeviceAliases: DICT;
(*------------------------------------------------------------------------*)
PROCEDURE GraphicsInit();
  PROCEDURE Alias(Name, Monicker: ARRAY OF CHAR);
  (*---------------------------------------------------------------------*)
  (*  Enter all valid names for graphics devices in a system-wide table. *)
  (*  The proper name of the device is returned on request.               *)
  (*---------------------------------------------------------------------*)
  BEGIN
    Dict.Enter(DeviceAliases, Monicker, KeyAttr{}, Strings.CopyCS(Name))
  END Alias;
BEGIN  (* GraphicsInit *)
  DeviceAliases := Dict.NewDict("graphics device aliases");
  Dict.Enter(Defaults.Contents, "graphics device aliases", KeyAttr{},
   DeviceAliases);
  (* Form of a name must be <generic module> <integer sub-devuce>  *)
  Alias("bbc 1",   "bbc"   );   (* Standard colour mode, stippled *)
  Alias("bbc 0",   "b/w"   );   (* Hi-res black & white mode      *)
  Alias("acrtc 0", "tudor" );   (* New hi-res colour graphics     *)
  Alias("hp 7220", "hp7220");   (* Various similar plotters       *)
  Alias("hp 7221", "hp"    );
  Alias("hp 7221", "hp7221");
  Alias("hp 7580", "hp7580");
  Alias("hp 7580", "bighp" );
  Alias("hp 7585", "hp7585");
END GraphicsInit;
(*------------------------------------------------------------------------*)
(*  Configure: This reads only integers and strings: it does no data      *)
(*  validation itself.  Each device driver is called to update its        *)
(*  internal structures from the updated DICT tables.                     *)
(*  For example: when defining a stipple pattern, such as "gold",         *)
(*  the entry bbc.stipple.gold := "red, green, green, red" is set.        *)
(*  At the 'ReConfigure' step, this is replaced by an token for the       *)
(*  stipple mixture itself.  One consequence of this approach is          *)
(*  that whenever a table is updated, ALL entries in that table must      *)
(*  be updated - previous entries will be lost.                           *)
(*------------------------------------------------------------------------*)
PROCEDURE Configure(InputStream: Stream);
BEGIN
  GenDict.ReadDict(InputStream, Defaults.Contents);
  BBC.ReConfigure();
  HP.ReConfigure();
END Configure;
(*--------------------------------------------------------------------------*)
(* These commands take a text description and return a token for future use *)
(*--------------------------------------------------------------------------*)
PROCEDURE Colour (Stream: GSTREAM; Text: ARRAY OF CHAR): COLOUR;
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  RETURN(Implementation^.Procedure^.Colour(Stream, Text))
END Colour;
(*------------------------------------------------------------------------*)
PROCEDURE TextStyle(Stream: GSTREAM; Text: ARRAY OF CHAR): TEXT;
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  RETURN(Implementation^.Procedure^.TextStyle(Stream, Text))
END TextStyle;
(*------------------------------------------------------------------------*)
PROCEDURE Marker (Stream: GSTREAM; Text: ARRAY OF CHAR): MARKER;
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  RETURN(Implementation^.Procedure^.Marker(Stream, Text))
END Marker;
(*------------------------------------------------------------------------*)
PROCEDURE Cursor (Stream: GSTREAM; Text: ARRAY OF CHAR): CURSOR;
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  RETURN(Implementation^.Procedure^.Cursor(Stream, Text))
END Cursor;
(*------------------------------------------------------------------------*)
(*      Access procedures to set attributes in stream attribute block     *)
(*------------------------------------------------------------------------*)
PROCEDURE SetLineColour(Stream: GSTREAM; Co: COLOUR);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.SetLineColour(Stream, Co)
END SetLineColour;
(*------------------------------------------------------------------------*)
PROCEDURE SetAreaColour(Stream: GSTREAM; Co: COLOUR);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.SetAreaColour(Stream, Co)
END SetAreaColour;
(*------------------------------------------------------------------------*)
PROCEDURE SetTextStyle(Stream: GSTREAM; Te: TEXT);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.SetTextStyle(Stream, Te)
END SetTextStyle;
(*------------------------------------------------------------------------*)
PROCEDURE SetCursor(Stream: GSTREAM; Cu: CURSOR);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.SetCursor(Stream, Cu)
END SetCursor;
(*------------------------------------------------------------------------*)
(* These commands have a direct action on the device.  The 'Command'      *)
(* interface is provided as a general escape mechanism for very device-   *)
(* specific commands                                                      *)
(*------------------------------------------------------------------------*)
PROCEDURE Surface(Stream: GSTREAM; Xl,Yb,Xr,Yt: INTEGER);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.Surface(Stream, Xl, Yb, Xr, Yt)
END Surface;
(*------------------------------------------------------------------------*)
PROCEDURE Command(Stream: GSTREAM; Comm: ARRAY OF CHAR): INTEGER;
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  RETURN Implementation^.Procedure^.Command(Stream, Comm)
END Command;
(*------------------------------------------------------------------------*)
(* The current line colour is an attribute held in the GSTREAM.           *)
(*------------------------------------------------------------------------*)
PROCEDURE MoveTo(Stream: GSTREAM;X,Y: INTEGER);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.MoveTo(Stream, X, Y)
END MoveTo;
(*------------------------------------------------------------------------*)
PROCEDURE LineTo(Stream: GSTREAM;X,Y: INTEGER);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.LineTo(Stream, X, Y)
END LineTo;
(*------------------------------------------------------------------------*)
(* Markers are drawn with their centre on the point given. The marker is  *)
(* geometrically defined elsewhere, and a handle to it is got from the    *)
(* 'Marker' procedure; e.g. Marker(Arrow, "->")                          *)
(*------------------------------------------------------------------------*)
PROCEDURE MarkerAt(Stream: GSTREAM; X,Y: INTEGER; Ma: MARKER);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.MarkerAt(Stream, X, Y, Ma)
END MarkerAt;
(*------------------------------------------------------------------------*)
(* This text command draws text from the point given. see also 'TextBox'  *)
(*------------------------------------------------------------------------*)
PROCEDURE TextAt(Stream: GSTREAM; X,Y: INTEGER; Text: ARRAY OF CHAR);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.TextAt(Stream, X, Y, Text)
END TextAt;
(*------------------------------------------------------------------------*)
(* These are area-action commands: TextBox puts the text in the box as    *)
(* best as it can                                                         *)
(*------------------------------------------------------------------------*)
PROCEDURE Box(Stream: GSTREAM; Xl,Yb,Xr,Yt: INTEGER);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.Box(Stream, Xl, Yb, Xr, Yt)
END Box;
(*------------------------------------------------------------------------*)
PROCEDURE TextBox(Stream: GSTREAM; Xl,Yb,Xr,Yt: INTEGER; Text: ARRAY OF CHAR);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.TextBox(Stream, Xl, Yb, Xr, Yt, Text)
END TextBox;
(*-------------------------------------------------------------------------*)
(* The four input co-ords allow a vast variety of initial cursor display   *)
(* on raster devices.  Possibilities include dragged boxes, stretched      *)
(* boxes, 45 degree snap lines etc.  The 'text' parameter returned will be *)
(* a device independant mapping of the returned value from a pick.         *)
(* There is a possibility of returning entire command strings in this way  *)
(* using a menu mechanism yet to be determined.                            *)
(*-------------------------------------------------------------------------*)
PROCEDURE ReadCursor(Stream: GSTREAM;Xl,Yb,Xr,Yt: INTEGER;VAR X,Y: INTEGER;
                     VAR Text: ARRAY OF CHAR);
VAR Implementation: gstreamIP;
BEGIN
   Implementation := gstreamIP(Stream^.Implementation);
   Implementation^.Procedure^.ReadCursor(Stream, Xl, Yb, Xr, Yt, X, Y, Text)
END ReadCursor;
(*------------------------------------------------------------------------*)
PROCEDURE DrawPolygon(Stream: GSTREAM; Polygon: POLYGON);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.DrawPolygon(Stream, Polygon)
END DrawPolygon;
(*------------------------------------------------------------------------*)
(* Stream attribute-block pointers.  These can also be had from the       *)
(* device-specific modules, such as HP. This module offers a generic      *)
(* entry to the system for ease of use.  An HP output stream would be     *)
(* opened by HP := FindOutput("hp 7221");                                *)
(*------------------------------------------------------------------------*)
PROCEDURE FindInput(Qual: ARRAY OF CHAR): GSTREAM;
BEGIN
  (* NOT YET SUPPORTED *)
END FindInput;
(*------------------------------------------------------------------------*)
PROCEDURE FindOutput(Qual: ARRAY OF CHAR): GSTREAM;
BEGIN
  (* NOT YET SUPPORTED *)
END FindOutput;
(*------------------------------------------------------------------------*)
PROCEDURE FindInOut(Qual: ARRAY OF CHAR): GSTREAM;
BEGIN
  (* NOT YET SUPPORTED *)
END FindInOut;
(*------------------------------------------------------------------------*)
PROCEDURE Delete(Stream: GSTREAM);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.Delete(Stream)
END Delete;
(*------------------------------------------------------------------------*)
PROCEDURE Update(Stream: GSTREAM);
VAR Implementation: gstreamIP;
BEGIN
  Implementation := gstreamIP(Stream^.Implementation);
  Implementation^.Procedure^.Update(Stream)
END Update;
(*------------------------------------------------------------------------*)
END Graphics.
