(*
        Chaos: a program that allows you to play with
	"strange attractors". See "Scientific American" 
	July 1987 issue.
        
        Created: 8/10/87 by Richie Bielak
        
        Copyright (c) 1987 by Richie Bielak
        
        This program maybe freely distributed, but please leave
        my name in. Thanks.....Richie

*)
MODULE Chaos;

FROM SYSTEM     IMPORT ADR, BYTE, ADDRESS;
FROM Intuition  IMPORT
     Window, WindowFlags, NewWindow, MenuPick, IDCMPFlagsSet, 
     WindowFlagsSet, WindowPtr, ScreenPtr, MenuPtr, MenuItemFlagsSet, 
     ItemText, ItemEnabled, IntuiMessagePtr, CustomScreen, ScreenFlagsSet, 
     OpenWindow, CloseWindow, NewScreen, OpenScreen, CloseScreen, ShowTitle,
     SetMenuStrip, MENUNUM, ITEMNUM, MenuNull, SetWindowTitles;
FROM Rasters    IMPORT Jam2, Jam1, DrawModeSet, SetRast;
FROM Ports      IMPORT ReplyMsg, WaitPort, GetMsg, MessagePtr;
FROM Views      IMPORT ViewModes, ViewModesSet, SetRGB4;
FROM Drawing    IMPORT SetAPen, RectFill;
FROM AmigaDOS   IMPORT Close;
FROM System     IMPORT WBenchMsg, StdOutput;
FROM SimpleWindows IMPORT CreateWindow;
FROM GetRes     IMPORT ChooseResolution;
FROM EasyMenus  IMPORT DetachMenuStrip, DisposeEasyMenuStrip;
FROM ChaosMenu  IMPORT ChaosMenu, ActionItems, ScreenItems, PreSetsItems,
                MenuStripPtr, AltMenuStripPtr;
FROM ChaosDraw  IMPORT DrawPicture; 
FROM ChaosPanel IMPORT ControlPanel, SetUpPanelGadgets, CleanUpPanelGadgets,
                       ControlValues;
FROM ChaosInfo  IMPORT AboutChaos;
FROM ChaosSave  IMPORT SavePicture;


CONST
  ChaosTitle     = "HENON MAPPING  © 1987 Richie Bielak";
  ComputingTitle = "Drawing in progress ...";
  SavingTitle    = "Saving picture...";  

VAR
  DisplayWidth, DisplayHeight : CARDINAL;
  DisplayType : ViewModesSet;
  wp : WindowPtr;
  sp : ScreenPtr;
  DispTitle : BOOLEAN;

(*++++++++++++++++++++++++++++++++++++++ *)
PROCEDURE InitScreen (name : ADDRESS) : ScreenPtr;
  VAR s : NewScreen;
  BEGIN
    WITH s DO
      LeftEdge := 0; TopEdge := 0; 
      Width := DisplayWidth; Height := DisplayHeight;
      Depth := 4; DetailPen := BYTE (0); BlockPen := BYTE (1);
      ViewModes := DisplayType;
      Type := CustomScreen; Font := NIL;
      DefaultTitle := name;
      Gadgets := NIL; CustomBitMap := NIL
    END;
    (* Now open the screen *)
    RETURN OpenScreen (s)
  END InitScreen;

(*++++++++++++++++++++++++++++++++++++++ *)
(* Initialize and open a window.         *)
PROCEDURE InitWindow (sp : ScreenPtr) : WindowPtr;
  BEGIN
     RETURN CreateWindow (0, 0, DisplayWidth, DisplayHeight,
                          IDCMPFlagsSet {MenuPick},
   			  WindowFlagsSet {Activate, Borderless, BackDrop},
			  NIL, sp, NIL);
  END InitWindow;

(*++++++++++++++++++++++++++++++++++++++ *)
PROCEDURE SetColors (sp : ScreenPtr);
  BEGIN
    WITH sp^ DO
      SetRGB4(ViewPort, 0, 0, 0, 0); SetRGB4(ViewPort, 1, 15, 15, 15);
      SetRGB4(ViewPort, 2, 12, 12, 12); SetRGB4(ViewPort, 3, 9, 9, 9);
      SetRGB4(ViewPort, 4, 10, 0, 10);  SetRGB4(ViewPort, 5, 8, 10, 15);
      SetRGB4(ViewPort, 6, 15, 15, 2); SetRGB4(ViewPort, 7, 11, 15, 0);
      SetRGB4(ViewPort, 8, 5, 13, 0);  SetRGB4(ViewPort, 9, 0, 0, 15);
      SetRGB4(ViewPort, 10, 3, 6, 15); SetRGB4(ViewPort, 11, 7, 7, 15);
      SetRGB4(ViewPort, 12, 12, 0, 14);SetRGB4(ViewPort, 13, 15, 2, 14);
      SetRGB4(ViewPort, 14, 15, 15, 0);SetRGB4(ViewPort, 15, 5, 12, 12);
    END
  END SetColors;

(* +++++++++++++++++++++++++++++++++++++++++ *)
PROCEDURE ProcessActionsMenu (code : CARDINAL; VAR quit : BOOLEAN);
  BEGIN
    CASE ActionItems(ITEMNUM(code)) OF
      Begin:
        (* Attach alternate menu and switch screen title *)
        SetMenuStrip (wp^, AltMenuStripPtr^);
        SetWindowTitles(wp^, NIL, ADR(ComputingTitle));
        DrawPicture(wp, DisplayWidth, DisplayHeight);
        (* Put old title back *)
        SetWindowTitles(wp^, NIL, ADR(ChaosTitle));
        DetachMenuStrip (wp);
           |
      Panel: ControlPanel (sp)
           |
      About: AboutChaos (sp)
           |
      SaveIFF:
        SetWindowTitles(wp^, NIL, ADR(SavingTitle));
        SavePicture (DisplayWidth, DisplayHeight, sp);
        SetWindowTitles(wp^, NIL, ADR(ChaosTitle));
           |
      Quit: quit := TRUE;
    END
  END ProcessActionsMenu;

(* +++++++++++++++++++++++++++++++++++++++++ *)
PROCEDURE ProcessScreensMenu (code : CARDINAL);
  BEGIN
    CASE ScreenItems (ITEMNUM(code)) OF
      ToggleTitle:
         DispTitle := NOT DispTitle;
         ShowTitle (sp^, DispTitle);   
	 |
      Clear:
         SetRast (wp^.RPort^, 0);
    END;
  END ProcessScreensMenu;


(* +++++++++++++++++++++++++++++++++++++++++ *)
PROCEDURE ProcessPreSetsMenu (code : CARDINAL);
  BEGIN
    WITH ControlValues DO
      IterPerOrbit := 1000; MaxOrbits := 130; MaxColors := 15;
      xInc := 0.02; yInc := 0.02;          
      IF DisplayHeight > 200 THEN 
        ZoomFactor := 2.0;
      ELSE
        ZoomFactor := 1.0;
      END;
      CASE PreSetsItems(ITEMNUM(code)) OF
        Pic1: a := 1.59; |
	Pic2: a := 1.3;  |
	Pic3: a := 0.5;  |
	Pic4: a := 2.23; 
      END;
    END;
  END ProcessPreSetsMenu;

(* +++++++++++++++++++++++++++++++++++++++++ *)
PROCEDURE ProcessMenu (code : CARDINAL; VAR quit : BOOLEAN);
  BEGIN
    (* Remove the menu strip while processing things *) 
    DetachMenuStrip (wp);
    CASE ChaosMenu (MENUNUM(code)) OF
      ActionMenu: ProcessActionsMenu (code, quit);  |
      ScreenMenu: ProcessScreensMenu (code);        |
      PreSetMenu: ProcessPreSetsMenu (code)
    END;
    (* Re-attach the menu strip *)
    SetMenuStrip (wp^, MenuStripPtr^);
  END ProcessMenu;

(* +++++++++++++++++++++++++++++++++++++++++ *)
PROCEDURE ProcessMessages ();
  VAR
    quit : BOOLEAN;
    msgptr : IntuiMessagePtr;
    class  : IDCMPFlagsSet; code : CARDINAL;
  BEGIN
    quit := FALSE;
    REPEAT
      msgptr := WaitPort (wp^.UserPort^);
      LOOP
        msgptr := GetMsg (wp^.UserPort^);
        IF msgptr = NIL THEN EXIT; END;
        code := msgptr^.Code; class := msgptr^.Class;
        ReplyMsg (MessagePtr(msgptr));
        IF (class = IDCMPFlagsSet{MenuPick}) AND (code <> MenuNull) THEN
          ProcessMenu(code, quit)
        END;
      END; (* LOOP *)
    UNTIL quit;
  END ProcessMessages;

BEGIN
  (* Get rid of the extra window, if we started from WB *)
  IF WBenchMsg <> NIL THEN
    Close (StdOutput); StdOutput := NIL;
  END;  
  DispTitle := TRUE;
  ChooseResolution (DisplayWidth, DisplayHeight, DisplayType);
  sp := InitScreen (ADR(ChaosTitle));
  wp := InitWindow (sp);
  SetColors (sp);
  SetMenuStrip (wp^, MenuStripPtr^);
  SetUpPanelGadgets ();

  ProcessMessages ();

  DetachMenuStrip (wp);
  DisposeEasyMenuStrip (MenuStripPtr);
  DisposeEasyMenuStrip (AltMenuStripPtr);
  CleanUpPanelGadgets ();
  CloseWindow (wp^); CloseScreen (sp^);
END Chaos.
