home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / languages / obrn-a_1.5_lib.lha / oberon-a / source2.lha / Source / Library / XYPlane.mod < prev   
Encoding:
Text File  |  1995-01-26  |  9.2 KB  |  367 lines

  1. (*************************************************************************
  2.  
  3.      $RCSfile: XYPlane.mod $
  4.   Description: Basic facilities for graphics programming.
  5.  
  6.    Created by: fjc (Frank Copeland)
  7.     $Revision: 1.3 $
  8.       $Author: fjc $
  9.         $Date: 1995/01/26 00:40:27 $
  10.  
  11.   Copyright © 1994-1995, Frank Copeland.
  12.   This file is part of the Oberon-A Library.
  13.   See Oberon-A.doc for conditions of use and distribution.
  14.  
  15. *************************************************************************)
  16.  
  17. <* STANDARD- *> <* MAIN- *>
  18.  
  19. MODULE XYplane;
  20.  
  21. IMPORT
  22.   SYS := SYSTEM, Kernel, e := Exec, es := ExecSupport, u := Utility,
  23.   gfx := Graphics, i := Intuition, gt := GadTools, str := Strings,
  24.   s := Sets;
  25.  
  26. CONST
  27.   draw *= 1;
  28.   erase *= 0;
  29.  
  30. VAR
  31.   X -, Y -, W -, H -: INTEGER;
  32.  
  33. CONST
  34.   pubScreenName = "";
  35.   drawPen = 1;
  36.   erasePen = 0;
  37.  
  38. VAR
  39.   scr : i.ScreenPtr;
  40.   scrDepth : INTEGER;
  41.   win : i.WindowPtr;
  42.   winLock : e.SignalSemaphore;
  43.   winTask : e.TaskPtr;
  44.   keyPressed : CHAR;
  45.  
  46. CONST
  47.  
  48.   (* Menu and menu item indices. *)
  49.  
  50.   menuXYplane = 0;
  51.     itemAbout = 0;
  52.     itemBar = 1;
  53.     itemClose = 2;
  54.  
  55.   numMenus = 4;
  56.  
  57. VAR
  58.   menus : ARRAY numMenus + 1 OF gt.NewMenu;
  59.   menuStrip : i.MenuPtr;
  60.   visInfo : gt.VisualInfo;
  61.  
  62.  
  63. PROCEDURE OpenScreen ();
  64.  
  65.   VAR
  66.     screenModeID : LONGINT;
  67.     pubScreen : i.ScreenPtr;
  68.     screenDrawInfo : i.DrawInfoPtr;
  69.  
  70. BEGIN (* OpenScreen *)
  71.   pubScreen := i.LockPubScreen (pubScreenName);
  72.   IF pubScreen # NIL THEN
  73.     (*
  74.     ** Get the DrawInfo structure from the locked screen
  75.     ** This returns pen, depth and font info.
  76.     *)
  77.     screenDrawInfo := i.GetScreenDrawInfo (pubScreen);
  78.     IF screenDrawInfo # NIL THEN
  79.       screenModeID := gfx.GetVPModeID (SYS.ADR (pubScreen.viewPort));
  80.       IF screenModeID # gfx.invalidID THEN
  81.         (*
  82.         ** screenModeID may now be used in a call to
  83.         ** OpenScreenTags () with the tag saDisplayID
  84.         *)
  85.         scrDepth := screenDrawInfo.depth;
  86.         scr := i.OpenScreenTagsA ( NIL,
  87.             i.saWidth,       pubScreen.width,
  88.             i.saHeight,      pubScreen.height,
  89.             i.saDepth,       screenDrawInfo.depth,
  90.             i.saOverscan,    i.oScanText,
  91.             i.saAutoScroll,  i.LTRUE,
  92.             i.saFullPalette, i.LTRUE,
  93.             i.saPens,        screenDrawInfo.pens,
  94.             i.saSysFont,     1,
  95.             i.saDisplayID,   screenModeID,
  96.             i.saTitle,       SYS.ADR ("XYplane inactive"),
  97.             u.end );
  98.         IF scr # NIL THEN
  99.           (*
  100.           ** Free the drawinfo an public screen as we don't
  101.           ** need them any more. We now have our own screen.
  102.           *)
  103.           i.FreeScreenDrawInfo (pubScreen, screenDrawInfo);
  104.           screenDrawInfo := NIL;
  105.           i.UnlockPubScreen (pubScreenName, pubScreen);
  106.           pubScreen := NIL;
  107.  
  108.           (*
  109.           ** Obtain a VisualInfo for creating menus, etc.
  110.           *)
  111.           visInfo := gt.GetVisualInfo (scr, u.end);
  112.           IF visInfo = NIL THEN i.OldCloseScreen (scr); scr := NIL END
  113.         END
  114.       END
  115.     END
  116.   END
  117. END OpenScreen;
  118.  
  119.  
  120. PROCEDURE CloseScreen ();
  121. BEGIN (* CloseScreen *)
  122.   IF visInfo # NIL THEN gt.FreeVisualInfo (visInfo); visInfo := NIL END;
  123.   IF scr # NIL THEN i.OldCloseScreen (scr); scr := NIL END;
  124. END CloseScreen;
  125.  
  126.  
  127. PROCEDURE OpenWindow ();
  128. BEGIN (* OpenWindow *)
  129.   win := i.OpenWindowTagsA ( NIL,
  130.       i.waCustomScreen, scr,
  131.       i.waTop,          scr.barHeight + 1,
  132.       i.waHeight,       scr.height - scr.barHeight - 1,
  133.       i.waActivate,     i.LTRUE,
  134.       i.waBorderless,   i.LTRUE,
  135.       i.waBackdrop,     i.LTRUE,
  136.       i.waScreenTitle,  SYS.ADR ("XYplane active"),
  137.       u.end );
  138. END OpenWindow;
  139.  
  140.  
  141. PROCEDURE CloseWindow ();
  142. BEGIN (* CloseWindow *)
  143.   IF win # NIL THEN i.CloseWindow (win); win := NIL END;
  144. END CloseWindow;
  145.  
  146.  
  147. PROCEDURE AddMenus ();
  148.  
  149. BEGIN (* AddMenus *)
  150.   (* Making the assumption that unitialised fields are zeroed... *)
  151.   menus[0].type := gt.title;
  152.   menus[0].label := SYS.ADR ("XYplane");
  153.  
  154.   menus[1].type := gt.item;
  155.   menus[1].label := SYS.ADR ("About...");
  156.  
  157.   menus[2].type := gt.item;
  158.   menus[2].label := gt.barLabel;
  159.  
  160.   menus[3].type := gt.item;
  161.   menus[3].label := SYS.ADR ("Close...");
  162.   menus[3].commKey := SYS.ADR ("Q");
  163. END AddMenus;
  164.  
  165.  
  166. PROCEDURE RemoveMenus ();
  167. BEGIN (* RemoveMenus *)
  168.   IF menuStrip # NIL THEN
  169.     i.ClearMenuStrip (win);
  170.     gt.FreeMenus (menuStrip); menuStrip := NIL
  171.   END;
  172. END RemoveMenus;
  173.  
  174.  
  175. PROCEDURE* HandleWindow ();
  176.  
  177.   VAR
  178.     msg : i.IntuiMessagePtr;
  179.     done : BOOLEAN;
  180.     menuNumber : INTEGER;
  181.     menuNum : INTEGER;
  182.     itemNum : INTEGER;
  183.     subNum : INTEGER;
  184.     item : i.MenuItemPtr;
  185.     signals : s.SET32;
  186.     sigBit : SHORTINT;
  187.  
  188.   PROCEDURE ShowAbout ();
  189.  
  190.     VAR es : i.EasyStruct; ignore : LONGINT;
  191.  
  192.   BEGIN (* ShowAbout *)
  193.     es.structSize := SIZE (i.EasyStruct);
  194.     es.flags := {};
  195.     es.title := SYS.ADR ("About XYplane");
  196.     es.textFormat :=
  197.       SYS.ADR ( "XYplane for Oberon-A\n"
  198.                 "Written by Frank Copeland\n"
  199.                 "XYplane 1.1 (16.10.94)" );
  200.     es.gadgetFormat := SYS.ADR ("Continue");
  201.     ignore := i.EasyRequest ( win, SYS.ADR (es), NIL, NIL )
  202.   END ShowAbout;
  203.  
  204.  
  205. BEGIN (* HandleWindow *)
  206.   e.ObtainSemaphore (winLock);
  207.     i.OldModifyIDCMP (win, {i.menuPick, i.vanillaKey});
  208.     sigBit := win.userPort.sigBit;
  209.   e.ReleaseSemaphore (winLock);
  210.  
  211.   done := FALSE;
  212.   WHILE ~done DO
  213.     (* We only have one signal bit, so we do not have to check which
  214.     ** bit broke the Wait().
  215.     *)
  216.     signals := e.Wait ({sigBit});
  217.     e.ObtainSemaphore (winLock);
  218.       LOOP
  219.         IF done THEN EXIT END;
  220.         msg := SYS.VAL (i.IntuiMessagePtr, e.GetMsg (win.userPort));
  221.         IF msg = NIL THEN EXIT END;
  222.         IF msg.class = {i.menuPick} THEN
  223.           menuNumber := msg.code;
  224.           WHILE (menuNumber # i.menuNull) & ~done DO
  225.             item := i.ItemAddress (menuStrip^, menuNumber);
  226.  
  227.             (* Process the item here *)
  228.             menuNum := i.MenuNum (menuNumber);
  229.             itemNum := i.ItemNum (menuNumber);
  230.             subNum := i.SubNum (menuNumber);
  231.  
  232.             CASE menuNum OF
  233.               menuXYplane :
  234.                 CASE itemNum OF
  235.                   itemAbout : ShowAbout() |
  236.                   itemClose : done := TRUE |
  237.                 END
  238.               |
  239.             END;
  240.  
  241.             menuNumber := item.nextSelect
  242.           END
  243.         ELSIF msg.class = {i.vanillaKey} THEN
  244.           keyPressed := CHR (msg.code)
  245.         END;
  246.         e.ReplyMsg (msg)
  247.       END;
  248.     e.ReleaseSemaphore (winLock);
  249.   END;
  250.  
  251.   (* Close the window and screen *)
  252.   e.ObtainSemaphore (winLock);
  253.     RemoveMenus();
  254.     CloseWindow();
  255.     CloseScreen();
  256.   e.ReleaseSemaphore (winLock);
  257.  
  258.   (* Put task in a safe state until removed by the main process. *)
  259.   signals := e.Wait ({});
  260. END HandleWindow;
  261.  
  262.  
  263. PROCEDURE Open *;
  264. BEGIN (* Open *)
  265.   IF scr = NIL THEN
  266.     OpenScreen(); ASSERT (scr # NIL, 98);
  267.     OpenWindow(); ASSERT (win # NIL, 98);
  268.     AddMenus(); ASSERT (menuStrip # NIL, 98);
  269.     X := 0; Y := 0;
  270.     W := win.width - win.borderLeft - win.borderRight;
  271.     H := win.height - win.borderTop - win.borderBottom;
  272.     keyPressed := 0X;
  273.     e.InitSemaphore (winLock);
  274.     IF winTask # NIL THEN es.DeleteTask (winTask) END;
  275.     winTask := es.CreateTask ("", 0, HandleWindow, 4000);
  276.     ASSERT (winTask # NIL, 98)
  277.   END
  278. END Open;
  279.  
  280.  
  281. PROCEDURE Clear *;
  282.  
  283. BEGIN (* Clear *)
  284.   e.ObtainSemaphore (winLock);
  285.     IF win # NIL THEN
  286.       gfx.SetRast (win.rPort, erasePen);
  287.       i.RefreshWindowFrame (win)
  288.     END;
  289.   e.ReleaseSemaphore (winLock);
  290. END Clear;
  291.  
  292.  
  293. PROCEDURE Dot * ( x, y, mode : INTEGER );
  294.  
  295.   VAR rp : gfx.RastPortPtr;
  296.  
  297. BEGIN (* Dot *)
  298.   ASSERT ((x >= 0) & (y >= 0) & ((mode = draw) OR (mode = erase)), 97);
  299.   e.ObtainSemaphore (winLock);
  300.     IF win # NIL THEN
  301.       (* Map Oberon co-ordinates to window co-ordinates *)
  302.       x := x + win.borderLeft;
  303.       y := win.height - win.borderBottom - y - 1;
  304.       (* Clip to window boundaries *)
  305.       IF (x < (win.width - win.borderRight)) & (y > win.borderTop) THEN
  306.         rp := win.rPort;
  307.         IF mode = draw THEN gfx.SetAPen (rp, drawPen)
  308.         ELSE gfx.SetAPen (rp, erasePen)
  309.         END;
  310.         gfx.SetDrMd (rp, gfx.jam1);
  311.         IF gfx.WritePixel (rp, x, y) THEN END;
  312.       END;
  313.     END;
  314.   e.ReleaseSemaphore (winLock);
  315. END Dot;
  316.  
  317.  
  318. PROCEDURE IsDot * ( x, y : INTEGER ) : BOOLEAN;
  319.  
  320.   VAR result : BOOLEAN;
  321.  
  322. BEGIN (* IsDot *)
  323.   ASSERT ((x >= 0) & (y >= 0), 97);
  324.   result := FALSE;
  325.   e.ObtainSemaphore (winLock);
  326.     IF win # NIL THEN
  327.       (* Map Oberon co-ordinates to window co-ordinates *)
  328.       x := x + win.borderLeft;
  329.       y := win.height - win.borderBottom - y - 1;
  330.       (* Clip to window boundaries *)
  331.       IF (x < (win.width - win.borderRight)) & (y > win.borderTop) THEN
  332.         result := gfx.ReadPixel (win.rPort, x, y) # erasePen
  333.       END
  334.     END;
  335.   e.ReleaseSemaphore (winLock);
  336.   RETURN result
  337. END IsDot;
  338.  
  339.  
  340. PROCEDURE Key * () : CHAR;
  341.  
  342.   VAR ch : CHAR;
  343.  
  344. BEGIN (* Key *)
  345.   IF scr = NIL THEN Open() END;
  346.   ch := keyPressed; keyPressed := 0X;
  347.   RETURN ch
  348. END Key;
  349.  
  350.  
  351. PROCEDURE* Close ( VAR rc : LONGINT );
  352. BEGIN (* Close *)
  353.   e.ObtainSemaphore (winLock);
  354.     IF winTask # NIL THEN es.DeleteTask (winTask); winTask := NIL END;
  355.     RemoveMenus();
  356.     CloseWindow();
  357.     CloseScreen();
  358.   e.ReleaseSemaphore (winLock);
  359. END Close;
  360.  
  361. <*$ClearVars+*>
  362. BEGIN
  363.   ASSERT (gt.base # NIL, 100);
  364.   e.InitSemaphore (winLock);
  365.   Kernel.SetCleanup (Close)
  366. END XYplane.
  367.