-- JaMGraphicsTool.mesa
-- Last change by Doug Wyatt,  7-Nov-81 14:44:34

DIRECTORY
  JaMGraphics USING [],
  JaMTajo,
  CGScreen USING [Bits],
  Tool USING [AddThisSW, Create, MakeSWsProc, RegisterSWType, SWType],
  ToolWindow USING [CreateSubwindow, DisplayProcType, TransitionProcType],
  UserInput USING [GetMouseAndCursorPosition, KeyPNRType, SetKeyPNR],
  Window USING [BitmapPlace, DisplayData, Handle, InvalidateBox, Place, Validate];
  
JaMGraphicsTool: MONITOR
  IMPORTS CGScreen, Tool, ToolWindow, UserInput, Window, JaMTajo
  EXPORTS JaMGraphics =
  BEGIN

  -- Globals
  
  wh: Window.Handle; -- Tool's window
  swtype: Tool.SWType; -- unique type for subwindow
  sw: Window.Handle ← NIL; -- subwindow for graphics
  data: LONG POINTER ← NIL; -- pointer to Cedar screen
  raster: CARDINAL ← 0; -- screen words per line
  height: CARDINAL ← 0; -- screen height
  bugflag: BOOLEAN ← FALSE;
  bugplace: Window.Place ← [0,0];

  Bugged: CONDITION;

  -- Tool needed routines
  
  ClientTransition: ENTRY ToolWindow.TransitionProcType =
    -- This procedure is called whenever the system determines that this
    -- Tool's state is undergoing a user invoked transition.
    BEGIN
    IF new = inactive THEN sw ← NIL;
    END;
    
  Init: PROCEDURE =
    BEGIN
    swtype ← Tool.RegisterSWType[];
    [data,raster,height] ← CGScreen.Bits[];
    wh ← Tool.Create[initialBox: [[0,408],[400,400]],
      makeSWsProc: MakeSWs, initialState: default,
      clientTransition: ClientTransition, name: "JaM Graphics"L];
    END;
    
  MakeSWs: Tool.MakeSWsProc =
    BEGIN
    sw ← ToolWindow.CreateSubwindow[
      parent: window, display: MyDisplay, boxesCount: none];
    UserInput.SetKeyPNR[sw,redButton,MyButton];
    UserInput.SetKeyPNR[sw,blueButton,MyButton];
    sw.clearingNotRequired ← TRUE;
    Tool.AddThisSW[window,sw,swtype];
    JaMTajo.AcceptTypeInFrom[sw];
    END;
  
  MyDisplay: ToolWindow.DisplayProcType = {
    Window.DisplayData[
      window: window,
      box: [[0,0],[raster*16,height]],
      data: data,
      wpl: raster,
      bbop: replace];
    };
  
  SetBug: ENTRY PROC[place: Window.Place] = --INLINE-- {
    IF sw=NIL THEN RETURN;
    bugflag ← TRUE; bugplace ← place;
    NOTIFY Bugged };

  GetBug: ENTRY PROC[clr: BOOLEAN ← TRUE] RETURNS[Window.Place] = --INLINE-- {
    place: Window.Place;
    IF clr THEN bugflag ← FALSE;
    UNTIL sw=NIL OR bugflag DO WAIT Bugged ENDLOOP;
    IF sw=NIL THEN place ← UserInput.GetMouseAndCursorPosition[]
    ELSE { place ← bugplace; bugflag ← FALSE };
    RETURN[place] };

  GetPlace: ENTRY PROC RETURNS[Window.Place] = --INLINE-- {
    place: Window.Place ← UserInput.GetMouseAndCursorPosition[];
    IF sw#NIL THEN {
      w: Window.Place ← Window.BitmapPlace[sw];
      place.x ← place.x - w.x; place.y ← place.y - w.y };
    RETURN[place] };
  
  MyButton: UserInput.KeyPNRType = {
    doit: BOOLEAN ← TRUE;
    button: JaMTajo.Button;
    IF key=Red AND downUp=down THEN SetBug[place];
    SELECT key FROM
      Red => button ← IF downUp=down THEN rd ELSE ru;
      Blue => button ← IF downUp=down THEN bd ELSE bu;
      ENDCASE => doit ← FALSE;
    JaMTajo.DoButton[button,place.x,place.y];
    };
  
  Mouse: PUBLIC PROC[click: BOOLEAN] RETURNS[x,y: INTEGER] = {
    place: Window.Place;
    IF click THEN place ← GetBug[] ELSE place ← GetPlace[];
    RETURN[place.x, place.y];
    };
  
  Update: PUBLIC ENTRY PROC = {
    IF sw#NIL THEN {
      w: INTEGER ← raster*16;
      h: INTEGER ← height;
      Window.InvalidateBox[sw,[[0,0],[w,h]]];
      Window.Validate[sw] };
    };
  
  -- Mainline code
  
  Init[]; -- this gets string out of global frame
  
  END...