(***************************************************************************

     $RCSfile: EasyIntuition.mod $
  Description: A port of easyintuition.c from the RKM:Libraries, Ch 2.

               "easyintuition.c  Simple backward-compatible V37 Intuition
               example.

               This example uses extended structures with the pre-V37
               OpenScreen() and OpenWindow() functions to compatibly open an
               Intuition display.  Enhanced V37 options specified via tags
               are ignored on 1.3 systems."

   Created by: fjc (Frank Copeland)
    $Revision: 1.5 $
      $Author: fjc $
        $Date: 1995/01/25 23:52:19 $

***************************************************************************)

<* STANDARD- *>

MODULE EasyIntuition;

IMPORT
  SYS := SYSTEM, E := Exec, U := Utility, D := Dos, G := Graphics,
  I := Intuition;

VAR

(*
 *  We can specify that we want the V37-compatible 3D look when running
 *  under V37 by adding an saPens tag.
 *)

  pens : ARRAY 1 OF INTEGER; (* empty pen array to get default 3D look *)
  ourscreentags : ARRAY 2 OF U.TagItem;

(*
 *  ExtNewScreen is an extended NewScreen structure.
 *  nsExtended flags that there is a tag pointer to additional
 *  tag information at the end of this structure.  The tags will
 *  be parsed by Release 2 but ignored by earlier OS versions.
 *)

  fullHires : I.ExtNewScreen;

CONST

(* Position and sizes for our window *)

  winLeftEdge  =  20;
  winTopEdge   =  20;
  winWidth     = 400;
  winMinWidth  =  80;
  winHeight    = 150;
  winMinHeight =  20;

(* Under V37, we'll get a special screen title when our window is active *)

  activetitle = "Our Screen - EasyWindow is Active";

VAR

  ourwindowtags : ARRAY 2 OF U.TagItem;

(*
 *  ExtNewWindow is an extended NewWindow structure.
 *  I.nwExtended indicates that there is a tag pointer to additional tag
 *  information at the end of this structure.  The tags will be parsed
 *  by Released 2 but ignored by earlier OS versions.
 *)

  easyWindow : I.ExtNewWindow;

(*------------------------------------*)
(*
 *  Initialises global variables.  C does this at compile time.
 *)
PROCEDURE init ();

BEGIN (* init *)
  pens [0] := -1; (* ~0 *)
  ourscreentags [0].tag := I.saPens;
  ourscreentags [0].data := SYS.ADR (pens);
  ourscreentags [1].tag := U.done;
  fullHires.ns.leftEdge := 0; (* must be zero prior to Release 2 *)
  fullHires.ns.topEdge := 0;
  fullHires.ns.width := 640; (* high-resolution *)
  fullHires.ns.height := I.stdScreenHeight; (* non-interlace *)
  fullHires.ns.depth := 2; (* 4 colors will be available *)
  fullHires.ns.detailPen := 0; (* Default *)
  fullHires.ns.blockPen := 1; (* Default *)
  fullHires.ns.viewModes := {G.hires}; (* the high-resolution display mode *)
  fullHires.ns.type := I.customScreen + {I.nsExtended}; (* the screen type *)
  fullHires.ns.font := NIL; (* no special font *)
  fullHires.ns.defaultTitle := SYS.ADR ("Our Screen");
  fullHires.ns.gadgets := NIL; (* no custom screen gadgets (not supported) *)
  fullHires.ns.customBitMap := NIL;
  fullHires.extension := SYS.ADR (ourscreentags);
                                    (* tags for additional V37 features *)
  ourwindowtags [0].tag := I.waScreenTitle;
  ourwindowtags [0].data := SYS.ADR (activetitle);
  ourwindowtags [1].tag := U.done;
  easyWindow.nw.leftEdge := winLeftEdge;
  easyWindow.nw.topEdge := winTopEdge;
  easyWindow.nw.width := winWidth;
  easyWindow.nw.height := winHeight;
  easyWindow.nw.detailPen := -1; (* Means use the screen's Detail
  easyWindow.nw.blockPen := -1;     and Block Pens *)
  easyWindow.nw.idcmpFlags := {I.closeWindow};
  (* These flags specify system gadgets and other window attributes  *)
  (* including the Extended flag which flags this as an ExtNewWindow *)
  easyWindow.nw.flags :=
    I.smartRefresh +
    { I.windowClose, I.activate, I.windowDrag,
      I.windowDepth, I.windowSizing, I.noCareRefresh,
      I.nwExtended };
  easyWindow.nw.firstGadget := NIL;
  easyWindow.nw.checkMark := NIL;
  easyWindow.nw.title := SYS.ADR("EasyWindow");
  easyWindow.nw.screen := NIL; (* Attach a screen later *)
  easyWindow.nw.bitMap := NIL; (* Let Intuition set up bitmap *)
  easyWindow.nw.minWidth := winMinWidth;
  easyWindow.nw.minHeight := winMinHeight;
  easyWindow.nw.maxWidth := -1;
  easyWindow.nw.maxHeight := -1;
  easyWindow.nw.type := I.customScreen;
  easyWindow.extension := SYS.ADR(ourwindowtags);
END init;

(*------------------------------------*)
PROCEDURE cleanExit (scrn : I.ScreenPtr; wind : I.WindowPtr);

BEGIN (* cleanExit *)
  (* Close things in the reverse order of opening *)
  IF wind # NIL THEN I.CloseWindow (wind) END;
  IF scrn # NIL THEN IF I.CloseScreen (scrn) THEN END END;
END cleanExit;

(*------------------------------------*)
PROCEDURE handleIDCMP (win : I.WindowPtr) : BOOLEAN;

  VAR
    done    : BOOLEAN;
    message : I.IntuiMessagePtr;
    class   : SET;

BEGIN (* handleIDCMP *)
  done := FALSE;
  (* Examine pending messages *)
  LOOP
    message := SYS.VAL (I.IntuiMessagePtr, E.GetMsg (win.userPort));
    IF message = NIL THEN EXIT END;
    class := message.class; (* get all the data we need from message *)

    (* When we're through with a message, reply *)
    E.ReplyMsg (message);

    (* See what events occurred *)
    IF I.closeWindow IN class THEN done := TRUE END;
  END; (* LOOP *)
  RETURN done
END handleIDCMP;

(*------------------------------------*)
PROCEDURE main ();

  VAR
    signalmask, signals : SET;
    winsignal : SHORTINT;
    done      : BOOLEAN;
    screen1   : I.ScreenPtr;
    window1   : I.WindowPtr;

BEGIN (* main *)
  done := FALSE; screen1 := NIL; window1 := NIL;

  (* Open the screen *)
  screen1 := I.OpenScreen (fullHires);
  IF screen1 = NIL THEN cleanExit (screen1, window1); HALT (D.warn) END;

  (* Attach the window to the open screen ... *)
  easyWindow.nw.screen := screen1;

  (* ... and open the window *)
  window1 := I.OpenWindow (easyWindow);
  IF window1 = NIL THEN cleanExit (screen1, window1); HALT (D.warn) END;

  (* Set up the signals for the events we want to hear about ... *)
  winsignal := window1.userPort.sigBit;
  signalmask := {winsignal}; (* we are only waiting on IDCMP events. *)

  (* Here's the main input event loop where we wait for events.  *)
  (* We have asked Intuition to send us CLOSEWINDOW IDCMP events *)
  (* Exec will wake us if any event we are waiting for occurs.   *)
  WHILE ~done DO
    signals := E.Wait (signalmask);
    (* An event occurred - now act on the signal(s) we received. *)
    (* We were only waiting on one signal (winsignal) in our     *)
    (* signalmask, so we actually know we received winsignal.    *)
    IF winsignal IN signals THEN
      done := handleIDCMP (window1)
    END; (* IF *)
  END; (* WHILE *)
  cleanExit (screen1, window1); HALT (D.ok); (* Exit the program *)
END main;

BEGIN (* EasyIntuition *)
  init ();
  main ();
END EasyIntuition.
