home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Pascal / Applications / SplatMaster 2.0d / SplatMaster2d.p < prev    next >
Encoding:
Text File  |  1995-12-15  |  93.2 KB  |  3,557 lines  |  [TEXT/PJMM]

  1. program SplatMaster2;
  2.  
  3.     uses
  4.         Quickdraw, Picker, Palettes, sane;
  5.  
  6.     const
  7.         drawBtnName = 'Draw Frame';
  8.         clearBtnName = 'Clear Splats';
  9.         fillBtnName = 'Draw Filled';
  10.         OK_ALRT_ID = 1005;
  11.         YN_ALRT_ID = 1006;
  12.         YNC_ALRT_ID = 1007;
  13.  
  14.         MacroDLOG_ID = 400;
  15.  
  16.         rad1_Start_ET = 16;
  17.         rad1_End_ET = 17;
  18.         rad2_Start_ET = 18;
  19.         rad2_End_ET = 19;
  20.         theta_ET = 20;
  21.         divs_ET = 21;
  22.         iterations_ET = 23;
  23.  
  24.         k_MoveToSentinel = $5000;    { = 20480}
  25.         k_Sentinel = k_MoveToSentinel + $1000;  { = 20480 + 4096 = 24576}
  26.  
  27. {MacDraw PicComment values follow}
  28.         PicDwgBeg = 130;
  29.         PicDwgEnd = 131;
  30.         PicGrpBeg = 140;
  31.         PicGrpEnd = 141;
  32.         StringBegin = 152;
  33.         StringEnd = 153;
  34.  
  35. {constants for the NewSplat dialog}
  36.         NewBlnDLOG_ID = 401;
  37.         okay = 1;
  38.         cancel = 2;
  39.         innerRad_ET = 3;
  40.         outerRad_ET = 4;
  41.         divisions_ET = 5;
  42.         name_ET = 6;
  43.         autoDraw_Chk = 14;
  44.         groBox_Chk = 15;
  45.         statsBox_Chk = 16;
  46.         polyBox_Chk = 17;
  47.  
  48.         k_PrefsResID = 128;
  49.         k_PrefsResType = 'prf1';
  50.  
  51.         MainWindID = 1000;
  52.  
  53.         AppleMenuID = 1000;
  54.         MenuAbout = 1;
  55.         MenuHelp = 2;
  56.  
  57.         FileMenuID = 1001;
  58.         MenuNew = 1;
  59.         MenuQuit = 3;
  60.  
  61.         EditMenuID = 1002;
  62.         MenuUndo = 1;
  63.         MenuCut = 3;
  64.         MenuCopy = 4;
  65.         MenuPaste = 5;
  66.         MenuClear = 6;
  67.         MenuPrefs = 8;
  68.  
  69.         GoodiesMenuID = 1003;
  70.         MenuMultiSplat = 1;
  71.         MenuClearSplats = 2;
  72.         MenuHidePalette = 3;
  73.         DoIt4 = 4;
  74.  
  75.         k_SaveAlrtID = 1001;
  76.         k_okALRTID = 1005;
  77.         k_ynALRTID = 1006;                {    Yes No type alert                }
  78.         k_yncALRTID = 1007;            {    Yes, No, Cancel type alert    }
  79.  
  80.         k_crossCurs = 1;
  81.         k_arrowCurs = 2;
  82.         k_watchCurs = 3;
  83.  
  84. {keyboard equivalents}
  85.         k_UpArrow = 30;
  86.         k_DownArrow = 31;
  87.         k_LeftArrow = 28;
  88.         k_RightArrow = 29;
  89.         k_PgUp = 11;
  90.         k_PgDown = 12;
  91.         k_HelpKey = 5;
  92.         k_HomeKey = 1;
  93.         k_EndKey = 4;
  94.         k_Enter = 3;
  95.         k_CR = 13;
  96.         k_Comma = 44;
  97.         k_Period = 46;
  98.         k_Tab = 9;
  99.         k_BS = 8;
  100.         k_EscClr = 27;
  101.  
  102.  
  103. {•    Low-memory globals:•}
  104.         ROM85 = $28E;
  105.         MBarHeight = $BAA;
  106.  
  107. {our constants}
  108.         kNumCtls = 2;
  109.  
  110.         kArraySiz = 1001;
  111.         twoPi = 6.283185307;
  112.  
  113.     type
  114.         WordPtr = ^INTEGER;
  115.  
  116.         BigArray = array[0..0] of Point;
  117.         BigArrayPtr = ^BigArray;
  118.         BigArrayHdl = ^BigArrayPtr;
  119.  
  120.         PrefRec = record
  121.                 def_alwaysDraw: Boolean;        {default value}
  122.                 def_alwaysGrowBox: Boolean;
  123.                 def_alwaysStatBox: Boolean;
  124.                 def_alwaysPolyBox: Boolean;
  125.             end;
  126.         PrefPtr = ^PrefRec;
  127.         PrefHdl = ^PrefPtr;
  128.  
  129. {balloon info}
  130.         SplatRec = record
  131.                 name: Str63;
  132.                 blnMiddle: Point;
  133.                 innerRadius, outerRadius: integer;
  134.                 rad1Start, rad1End, rad2Start, rad2End: integer;
  135.                 theta, thetaEndDegrees: real;
  136.                 iterations, divisions: integer;
  137.                 myBigArray: BigArrayHdl;
  138.                 maxPtsAllowed, numPtsSoFar: integer;
  139.                 autoRedraw, autoFill: Boolean;
  140.                 statsBox: rect;
  141.                 numSplats: integer;
  142.                 statsFont: integer;
  143.             end;
  144.  
  145.     type
  146.         TopicSet = record
  147.                 textRsrc, stylRsrc: Integer;
  148.             end;
  149.         HelpListHdl = ^HelpListPtr;
  150.         HelpListPtr = ^HelpList;
  151.         HelpList = record
  152.                 numTopics: Integer;
  153.                 topicSets: array[0..0] of TopicSet;
  154.             end;
  155.  
  156.     var
  157.         HasColorQD: boolean;        {    can we use color?            }
  158.         HasCoProcessor: boolean;    {    are we fast?                    }
  159.  
  160.         DrawWindPtr: WindowPtr;
  161.         mainWindowStorage: WindowRecord;
  162.         mainWindPalette: PaletteHandle;
  163.         GrowIconRect: Rect;                    {    for pseudo grow-icon            }
  164.         clippingRect: Rect;
  165.  
  166.         toolWindPtr: WindowPtr;
  167.         toolWindowStorage: WindowRecord;
  168.  
  169.         paletteWindPtr: WindowPtr;
  170.         paletteWindowStorage: WindowRecord;
  171.  
  172.         hueWindPtr: WindowPtr;
  173.         hueWindowStorage: WindowRecord;
  174.  
  175.         myMenus: array[AppleMenuID..GoodiesMenuID] of MenuHandle; {all of the normal menus}
  176.  
  177.         gIBeam: CursHandle;
  178.         gWatch: CursHandle;
  179.         gCrossHairs: CursHandle;
  180.         cursorIs: integer;
  181.  
  182.         quitting, finished, errorFlag, refreshMenus, gWNEImplemented: Boolean;
  183.         currMenuHeight, savedMenuHeight: integer;
  184.  
  185.         MainEvent: EventRecord;
  186.  
  187.         poly: PolyHandle;
  188.         innerRadScrl, outerRadScrl, divsScrl: ControlHandle;
  189.         redScroll, greenScroll, blueScroll: ControlHandle;
  190.         drawBtnRect, clearBtnRect, fillBtnRect: Rect;
  191.         autoDrawChkBox: Rect;
  192.         autoFillChkBox: Rect;
  193.         showToolWind: Boolean;
  194.         showPaletteWind: Boolean;
  195.         graphPICHdl: PicHandle;
  196.  
  197.         curSplat: SplatRec;
  198.         prefs: PrefRec;
  199.         appResFileRef: integer;        {for prefs resource}
  200.         tempSplat: SplatRec;    {make this global, just to make life easier}
  201.  
  202.         myDialog: DialogPtr;
  203.         myHelpListH: HelpListHdl;
  204.         theList: ListHandle;
  205.         pagesize, numTopics: Integer;
  206.         textRes, numTopicsH: Handle;
  207.         sBar: ControlHandle;
  208.         theText: TEHandle;
  209.  
  210. {$S One}
  211.     procedure CreateList;
  212.         var
  213.             i, iType: Integer;
  214.             topicStr: Str255;
  215.             iRect, dataBounds: Rect;
  216.             cSize, theCell: Cell;
  217.             iHandle: Handle;
  218.     begin
  219.         GetDItem(myDialog, 3, iType, iHandle, iRect);
  220.         FrameRect(iRect);
  221.         InsetRect(iRect, 1, 1);
  222.         SetPt(cSize, iRect.right - iRect.left, 17);
  223.         SetRect(dataBounds, 0, 0, 1, numTopics);
  224.         theList := LNew(iRect, dataBounds, cSize, 0, myDialog, False, False, False, True);
  225.         for i := 1 to numTopics do                    {drawIt, hasGrow, hScroll, vScroll}
  226.             begin
  227.                 GetIndString(topicStr, 256, i);
  228.                 SetPt(theCell, 0, i - 1);
  229.                 LSetCell(Pointer(Ord(@topicStr) + 1), Length(topicStr), theCell, theList);
  230.             end;
  231.         theList^^.selFlags := lOnlyOne;
  232.         SetPt(theCell, 0, 0);
  233.         LSetSelect(true, theCell, theList);
  234.         LDoDraw(True, theList); {set drawing to True now that list is built}
  235.     end;
  236.  
  237.     procedure ScrAction (theCtl: ControlHandle; partCode: Integer);
  238.         var
  239.             delta, oldValue: Integer;
  240.     begin
  241.         case partCode of
  242.             inUpButton: 
  243.                 delta := -10;
  244.             inDownButton: 
  245.                 delta := 10;
  246.             inPageUp: 
  247.                 delta := -pagesize;
  248.             inPageDown: 
  249.                 delta := pagesize;
  250.             otherwise
  251.         end;
  252.         if partCode <> 0 then
  253.             begin
  254.                 oldValue := GetCtlValue(theCtl);
  255.                 SetCtlValue(theCtl, oldValue + delta);
  256.                 TEScroll(0, oldValue - GetCtlValue(theCtl), theText);
  257.             end;
  258.     end;
  259.  
  260.     procedure WindowScroll (thePt: Point; theWindow: WindowPtr);
  261.         var
  262.             theCtl: ControlHandle;
  263.             part, oldValue: Integer;
  264.     begin
  265.         GlobalToLocal(thePt);
  266.         case FindControl(thePt, theWindow, theCtl) of
  267.             inUpButton..inPageDown: 
  268.                 part := TrackControl(theCtl, thePt, @ScrAction);
  269.             inThumb: 
  270.                 begin
  271.                     with theText^^ do
  272.                         oldValue := viewRect.top - destRect.top;
  273.                     if TrackControl(theCtl, thePt, nil) <> 0 then
  274.                         TEScroll(0, oldValue - GetCtlValue(theCtl), theText);
  275.                 end;
  276.             otherwise
  277.         end;
  278.     end;
  279.  
  280.     procedure LoadText (item: Integer);
  281.         const
  282.             inactive = 255;
  283.         var
  284.             max, textNum, stylNum: Integer;
  285.             textRes, stylRes: Handle;
  286.     begin
  287.         TEDeactivate(theText);
  288.         TESetSelect(0, 32767, theText);
  289.         TEDelete(theText);
  290.         theText^^.destRect := theText^^.viewRect;
  291.         textNum := myHelpListH^^.topicSets[item].textRsrc;
  292.         stylNum := myHelpListH^^.topicSets[item].stylRsrc;
  293.         if (textNum <> 0) & (stylNum <> 0) then
  294.             begin
  295.                 textRes := GetResource('TEXT', textNum);
  296.                 stylRes := GetResource('styl', stylNum);
  297.                 HLock(textRes);
  298.                 HLock(stylRes);
  299.                 TEStylInsert(textRes^, SizeResource(textRes), StScrpHandle(stylRes), theText);
  300.                 HUnlock(stylRes);
  301.                 HUnlock(textRes);
  302.             end;
  303.         max := TEGetHeight(theText^^.nLines, 0, theText) - pagesize;
  304.         if max > 0 then
  305.             HiliteControl(sBar, activeFlag)
  306.         else
  307.             HiliteControl(sBar, inactive);
  308.         SetCtlValue(sBar, 0);
  309.         SetCtlMax(sBar, max);
  310.         TEActivate(theText);
  311.     end;
  312.  
  313.     function MyFilter (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: Integer): Boolean;
  314.         var
  315.             iType, part: Integer;
  316.             iBox: Rect;
  317.             iHdl: Handle;
  318.             thePt: Point;
  319.             theCtl: ControlHandle;
  320.             ignore: Boolean;
  321.             newCell: Cell;
  322.     begin
  323.         MyFilter := False;
  324.         case theEvent.what of
  325.             keyDown, autoKey:  {close if enter or return is keyed}
  326.                 if BitAnd(theEvent.message, charCodeMask) in [3, 13] then
  327.                     begin
  328.                         MyFilter := True;
  329.                         GetDItem(theDialog, 1, iType, iHdl, iBox);
  330.                         InvertRoundRect(iBox, 10, 10);
  331.                         itemHit := 1;
  332.                     end;
  333.             mouseDown: 
  334.                 begin
  335.                     thePt := theEvent.where;
  336.                     GlobalToLocal(thePt);
  337.                     part := FindControl(thePt, myDialog, theCtl);
  338.                     if theCtl = sBar then
  339.                         WindowScroll(theEvent.where, myDialog)
  340.                     else if theCtl = theList^^.vScroll then
  341.                         ignore := LClick(thePt, theEvent.modifiers, theList)
  342.                     else if PtInRect(thePt, theList^^.rView) then
  343.                         begin
  344.                             ignore := LClick(thePt, theEvent.modifiers, theList);
  345.                             SetPt(newCell, 0, 0);
  346.                             ignore := LGetSelect(True, newCell, theList);
  347.                             LoadText(newCell.v);
  348.                         end;
  349.                 end;
  350.             updateEvt: 
  351.                 begin
  352.                     TEUpdate(theText^^.viewRect, theText);
  353.                     LUpdate(myDialog^.visRgn, theList);
  354.                 end;
  355.             otherwise
  356.         end;
  357.     end;
  358.  
  359.     procedure Help (strRsrcNum, hlpRsrcNum: Integer);
  360.         type
  361.             IntHdl = ^IntPtr;
  362.             IntPtr = ^Integer;
  363.         var
  364.             savePort: GrafPtr;
  365.             iBox, tBox: Rect;
  366.             iType, itemHit: Integer;
  367.             iHdl: Handle;
  368.     begin
  369.         GetPort(savePort);
  370.         myDialog := GetNewDialog(1001, nil, Pointer(-1));
  371.         SetPort(myDialog);
  372.         ShowWindow(myDialog);
  373.         TextFont(Geneva);
  374.         TextSize(12);
  375.         numTopics := IntHdl(GetResource('STR#', strRsrcNum))^^;
  376.         myHelpListH := HelpListHdl(GetResource('HLP#', hlpRsrcNum));
  377.         HLock(Handle(myHelpListH));
  378.         CreateList;
  379.         GetDItem(myDialog, 2, iType, iHdl, tBox);
  380.         FrameRect(tBox);
  381.         InsetRect(tBox, 4, 2);
  382.         pagesize := tBox.bottom - tBox.top;
  383.         theText := TEStylNew(tBox, tBox);
  384.         HLock(Handle(theText));
  385.         GetDItem(myDialog, 6, iType, iHdl, iBox);
  386.         sBar := ControlHandle(iHdl);
  387.         GetDItem(myDialog, 1, iType, iHdl, iBox);
  388.         InsetRect(iBox, -4, -4);
  389.         PenSize(3, 3);
  390.         FrameRoundRect(iBox, 16, 16);
  391.         PenSize(1, 1);
  392.         LoadText(0);
  393.         repeat
  394.             ModalDialog(@MyFilter, itemHit);
  395.         until itemHit = 1;
  396.         HUnlock(Handle(theText));
  397.         LDispose(theList);
  398.         DisposDialog(myDialog);
  399.         SetPort(savePort);
  400.     end;
  401.  
  402. {-------------------Draw Fake Grow Icon-------------------}
  403. {The following procedure will put a graphic growbox in the lower right corner}
  404.     procedure FakeGrowIcon (WPtr: WindowPtr; visible: boolean);
  405.         var
  406.             bot, rght: integer;
  407.             R: rect;
  408.             pState: PenState;
  409.     begin
  410.         bot := WPtr^.portRect.bottom;
  411.         rght := WPtr^.PortRect.right;
  412.         SetRect(growIconRect, rght - 15, bot - 15, rght + 1, bot + 1);
  413.         if visible then
  414.             begin
  415.                 GetPenState(pState);
  416.                 EraseRect(growIconRect);
  417.                 FrameRect(growIconRect);
  418.                 SetRect(R, rght - 10, bot - 10, rght - 1, bot - 1);
  419.                 FrameRect(R);
  420.                 SetRect(R, rght - 12, bot - 12, rght - 5, bot - 5);
  421.                 EraseRect(R);
  422.                 FrameRect(R);
  423.                 SetPenState(pState);
  424.             end;{if visible}
  425.     end;
  426.  
  427. {===========================================================================}
  428.     procedure SetUpPalette;
  429.         const
  430.             numColors = 256;    {256 - 2; 2 spots reserved for black & white}
  431.             colorsAvail = 254;
  432.         var
  433.             i: integer;
  434.             num: real;
  435.             anRGB: RGBColor;
  436.     begin
  437.         mainWindPalette := NewPalette(256, nil, pmCourteous, $5000);
  438. {mainWindPalette := GetPalette(mainWindowPtr);}
  439.  
  440.         anRGB.red := 2 * maxInt;
  441.         anRGB.blue := 2 * maxInt;
  442.         anRGB.green := 2 * maxInt;
  443.         SetEntryColor(mainWindPalette, 0, anRGB);    {first Entry is white}
  444.         anRGB.red := 0;
  445.         anRGB.blue := 0;
  446.         anRGB.green := 0;
  447.         SetEntryColor(mainWindPalette, 255, anRGB);    {last entry is black}
  448.  
  449.         for i := 1 to numColors - 1 do            {defaults to grays}
  450.             begin
  451.                 num := 1 - i / (colorsAvail);
  452.                 anRGB.red := 2 * (round(num * maxint));
  453.                 anRGB.blue := 2 * (round(num * maxint));
  454.                 anRGB.green := 2 * (round(num * maxint));
  455.                 SetEntryColor(mainWindPalette, i + 1, anRGB);
  456.             end;
  457.  
  458.         for i := 1 to numColors do
  459.             ProtectEntry(i, TRUE);
  460.     end;
  461.  
  462. {===========================================================================}
  463.     procedure PutUpDrawingWIND;
  464.         var
  465.             Screen: Rect;
  466.             offSet: point;
  467.     begin
  468.         if hasColorQD then
  469.             begin
  470.                 DrawWindPtr := GetNewCWindow(1000, @mainWindowStorage, pointer(-1));
  471.                 SetUpPalette;
  472.                 SetPalette(DrawWindPtr, mainWindPalette, TRUE);
  473.                 ActivatePalette(DrawWindPtr);
  474.             end
  475.         else
  476.             DrawWindPtr := GetNewWindow(1000, @mainWindowStorage, WindowPtr(-1));
  477.  
  478.         SetPort(DrawWindPtr);
  479.  
  480.         offSet.h := (ScreenBits.bounds.right - DrawWindPtr^.portRect.right) div 2 + 20;
  481.         offSet.v := 26 + (ScreenBits.bounds.bottom - DrawWindPtr^.portRect.bottom) div 3;
  482. {not calculating currMenuHeight yet}
  483. {offSet.v := currMenuHeight + (ScreenBits.bounds.bottom - DrawWindPtr^.portRect.bottom) div 3;}
  484.         MoveWindow(DrawWindPtr, offSet.h, offSet.v, TRUE);
  485.  
  486.         clippingRect := DrawWindPtr^.portRect;
  487.         InsetRect(clippingRect, 1, 1);
  488.         ClipRect(clippingRect);
  489.  
  490.         SetWTitle(DrawWindPtr, 'SplatMaster');
  491.         ShowWindow(DrawWindPtr);
  492.         FakeGrowIcon(DrawWindPtr, prefs.def_alwaysGrowBox);
  493.     end;
  494.  
  495.  
  496. {===========================================================================}
  497.     procedure CloseDrawingWIND;
  498.     begin
  499.         CloseWindow(DrawWindPtr);
  500.     end;
  501.  
  502.  
  503. {===========================================================================}
  504.     procedure CenterWindow (theWindow: WindowPtr);
  505.  
  506.         const
  507.             MBarHeight = $BAA;
  508.         type
  509.             WordPtr = ^INTEGER;
  510.         var
  511.             theX, theY: INTEGER;
  512.             scrnNoMB: Rect;        (* Rectangle of the screen without Menu Bar. *)
  513.     begin
  514.         with WindowPeek(theWindow)^.port do
  515.             begin
  516.                 with screenBits do
  517.                     begin
  518.                         theX := ((bounds.right - bounds.left) - (portRect.right - portRect.left)) div 2;
  519.                         theY := ((bounds.bottom - bounds.top) - (portRect.bottom - portRect.top)) div 3;
  520.                     end
  521.             end;
  522.         theY := theY + WordPtr(MBarHeight)^;
  523.         MoveWindow(theWindow, theX, theY, FALSE);
  524.     end;
  525.  
  526.  
  527. {===========================================================================}
  528.     procedure DoDrag (theWindow: WindowPtr);
  529.     begin
  530. {this allows the user to drag a window around in the rectangle defined by}
  531. {ScreenBits.bounds.}
  532.         DragWindow(theWindow, MainEvent.where, ScreenBits.bounds);
  533.     end;
  534.  
  535. {===========================================================================}
  536.     procedure DoGrow (theWindow: WindowPtr);
  537.         var
  538.             Wptr, oldPort: Windowptr;
  539.             sizeRect: rect;
  540.             newSize: longint;
  541.             newWidth, newHeight: integer;
  542.             r: rect;
  543.             bot, rght: integer;
  544.  
  545.     begin
  546.         GetPort(oldPort);
  547.         SetPort(theWindow);
  548.         if theWindow <> FrontWindow then
  549.             SelectWindow(theWindow);
  550. {the minimum size that this particular window can be resized is}
  551. {100 pixels wide,  100 pixels tall.  The maximum size is}
  552. {screenBits.right,screenBits.bottom - 37 tall.}
  553.         SetRect(sizeRect, 100, 100, screenBits.bounds.right, screenBits.bounds.bottom - 37);
  554.         newSize := GrowWindow(theWindow, MainEvent.where, sizeRect);
  555.         if newSize <> 0 then
  556.             begin
  557.                 bot := WPtr^.portRect.bottom;
  558.                 rght := WPtr^.PortRect.right;
  559.                 EraseRect(theWindow^.portRect);
  560.                 newWidth := LoWord(newSize);
  561.                 newHeight := HiWord(newSize);
  562.                 SizeWindow(theWindow, newWidth, newHeight, TRUE);
  563.                 ClipRect(theWindow^.portRect);
  564.                 InvalRect(theWindow^.portRect);
  565.                 FakeGrowIcon(theWindow, prefs.def_alwaysGrowBox);
  566.                 clippingRect := DrawWindPtr^.portRect;
  567.                 InsetRect(clippingRect, 1, 1);
  568.                 ClipRect(clippingRect);
  569.             end;
  570.         SetPort(oldPort);
  571.     end;{DoGrow}
  572.  
  573. {===========================================================================}
  574. {• procedure HandleWClose; {(whichWindow : WindowPtr; where : point);•]}
  575. {• begin•}
  576. {•  Quitting := TRUE;•}
  577. {•  if whichWindow <> FrontWindow then•}
  578. {•   SelectWindow(whichWindow)•}
  579. {•  else•}
  580. {•   begin•}
  581. {•    if TrackGoAway(whichWindow, where) then•}
  582. {•     begin•}
  583. {•                    {•]}
  584. {•{                    if anything in the window needs to be saved to•]}
  585. {•{                    disk, now is the time to do it!!!!!•]}
  586. {•{                    •]}
  587. {•  HideWindow(whichWindow);•}
  588. {•  disposeWindow(whichWindow);•}
  589. {• end;•}
  590. {• end;•}
  591. {• end;{HandleWClose•]}
  592.  
  593. {=======================================================================================    }
  594.     procedure DoMessage (mes0: str255; mes1: str255; mes2: str255; mes3: str255);
  595.         const
  596.             MessageDialog = 258;
  597.         var
  598.             dialogP: DialogPtr;
  599.             item: integer;
  600.             oldPort: grafPtr;
  601.     begin
  602.         GetPort(oldPort);
  603.         ParamText(mes0, mes1, mes2, mes3);
  604.         dialogP := GetNewDialog(MessageDialog, nil, pointer(-1));
  605.         if dialogP = nil then
  606.             begin
  607.                 SysBeep(5);
  608.             end
  609.         else
  610.             begin
  611.                 CenterWindow(dialogP);
  612.                 ShowWindow(dialogP);
  613.                 InitCursor;
  614.                 ModalDialog(nil, item);
  615.                 DisposDialog(dialogP);
  616.             end;
  617.         SetPort(oldPort);
  618.     end; {DoMessage}
  619.  
  620.  
  621. {======================================================================================= }
  622.     procedure DoOneLiner (mes0: Str255);
  623.     begin
  624.         DoMessage(mes0, '', '', '');
  625.     end; {DoOneLiner}
  626.  
  627.  
  628. {======================================================================================= }
  629. {Make sure your message has already been prepared using ParamText}
  630.     procedure Do_OK_ALRT;
  631.         var
  632.             oldPort: GrafPtr;
  633.             dummy: integer;
  634.     begin
  635.         GetPort(oldPort);
  636.         dummy := StopAlert(OK_ALRT_ID, nil);
  637.         SetPort(oldPort);
  638.     end;        {Do_OK_ALRT}
  639.  
  640.  
  641. {======================================================================================= }
  642. {Make sure your message has already been prepared using ParamText}
  643.     function Do_YN_ALRT: Boolean;
  644.         var
  645.             oldPort: GrafPtr;
  646.     begin
  647.         GetPort(oldPort);
  648.         if (Alert(YN_ALRT_ID, nil) = 1) then
  649.             Do_YN_ALRT := TRUE
  650.         else
  651.             Do_YN_ALRT := FALSE;
  652.         SetPort(oldPort);
  653.     end;        {Do_YN_ALRT}
  654.  
  655.  
  656.  
  657. {======================================================================================= }
  658. {Make sure your message has already been prepared using ParamText}
  659.     function Do_YNC_Alrt: integer;
  660.         var
  661.             oldPort: GrafPtr;
  662.     begin
  663.         GetPort(oldPort);
  664.         Do_YNC_Alrt := Alert(YNC_ALRT_ID, nil);
  665.         SetPort(oldPort);
  666.     end;        {Do_YNC_Alrt}
  667.  
  668.  
  669. {======================================================================================= }
  670.     {This is a routine used to add strings to an existing list}
  671.     procedure Add_List_String (theString: Str255; theList: ListHandle);
  672.         var
  673.             theRow: integer;             {The Row that we are adding}
  674.             aStr: str255;
  675.             aPt: point;
  676.     begin
  677.         if (theList <> nil) then
  678.             begin
  679.                 aPt.h := 0;                                           {Point to the correct column}
  680.                 theRow := LAddRow(1, 200, theList);            {Add another row at the end of the list}
  681.                 aPt.v := theRow;                                    {Point to the row just added}
  682.                 aStr := theString;{Get the string to add}
  683.                 LSetCell(Pointer(ord(@aStr) + 1), length(aStr), aPt, theList);{Place string in row just created}
  684.                 LDraw(aPt, theList);                                {Draw the new string}
  685.             end;
  686.     end;
  687.  
  688.  
  689. {======================================================================================= }
  690. {--------------------Scan Event Queue for Cmd-Period---------------------}
  691.  
  692. {example of code that might call CheckForStop }
  693. {    itsAnEvent := EventAvail(keyDownMask, myEvent);}
  694. {    if itsAnEvent then}
  695. {    begin}
  696. {    if CheckForStop(myEvent) then}
  697. {    goto 99;}
  698. {    end;}
  699.  
  700.     function CheckForStop (theEvent: EventRecord): boolean;
  701.         type
  702.             Trick = packed record
  703.                     case boolean of
  704.                         true: (
  705.                                 long: Longint
  706.                         );
  707.                         false: (
  708.                                 chr3, chr2, chr1, chr0: char
  709.                         )
  710.                 end;
  711.         var
  712.             CharCode: char;
  713.             TrickVar: Trick;
  714.             stop: boolean;
  715.             periodKey: char;
  716.     begin
  717.         stop := FALSE;
  718.         periodKey := chr(46);
  719.         TrickVar.long := theEvent.message;
  720.         CharCode := TrickVar.chr0;
  721.         if BitAnd(theEvent.modifiers, CmdKey) = CmdKey then
  722.             if CharCode = periodKey then
  723.                 stop := TRUE;
  724.         CheckForStop := stop;
  725.     end;
  726.  
  727. {--------------------Check/Uncheck CheckBoxes in DLOGs---------------------}
  728.     procedure CheckABox (theDlog: dialogPtr; ItemNum: integer; HighLite: boolean);
  729.         var
  730.             itemtype: integer;                {the dialog items type}
  731.             itemhandle: handle;                {the dialog items handle}
  732.             itemrect: rect;                    {the dialog items rect}
  733.             itemcntlhand: controlhandle;    {we convert the items handle to a cntl handle}
  734.  
  735.     begin
  736.         GetDItem(theDlog, ItemNum, itemtype, itemhandle, itemrect); {get the handle}
  737.         itemcntlhand := controlhandle(itemhandle); {convert it to a cntl handle}
  738.         if HighLite then
  739.             begin
  740.                 SetCtlValue(itemcntlhand, 1); {hilite the control}
  741.             end
  742.         else
  743.             begin
  744.                 SetCtlValue(itemcntlhand, 0); {unlilite the control}
  745.             end;
  746.     end;
  747.  
  748. {-----------------Track User's Use of Scrollbar---------------}
  749.  
  750.     procedure TrackScroll (theControl: ControlHandle; partCode: Integer);
  751.         var
  752.             min, max, amount, startValue: Integer;
  753.             up: Boolean;
  754.     begin
  755.         up := partcode in [inUpButton, inPageUp];
  756.         min := GetCtlMin(theControl);
  757.         max := GetCtlMax(theControl);
  758.         startValue := GetCtlValue(theControl);
  759.         if ((up and (startValue > min)) or ((not up) and (startValue < max))) and (partCode <> 0) then
  760.             begin
  761.                 if up then
  762.                     amount := -1
  763.                 else
  764.                     amount := 1;
  765.                 if partCode in [inPageUp, inPagedown] then
  766.                     amount := round(amount * 5)
  767.                 else
  768.                     amount := round(amount * 1);
  769.                 SetCtlValue(theControl, amount + startValue);
  770.             end;
  771.     end; {of TrackScroll}
  772.  
  773. {--------------------HiLite/UnHilite Radio Buttons---------------------}
  774.     procedure PushRadioButton (theDlog: dialogPtr; item, first, last: integer);
  775.  
  776.         var
  777.             index: integer;        {index through the loop}
  778.             itemtype: integer;        {the dialog items type}
  779.             itemhandle: handle;        {the dialog items handle}
  780.             itemrect: rect;        {the dialog items rect}
  781.             itemcntlhand: controlhandle; {we convert the items handle to a cntl handle}
  782.  
  783.     begin
  784.         for index := first to last do {do it for all items in the group}
  785.             begin
  786.                 GetDItem(theDlog, index, itemtype, itemhandle, itemrect); {get the handle}
  787.                 itemcntlhand := controlhandle(itemhandle); {convert it to a cntl handle}
  788.                 if (index = item) then
  789.                     begin
  790.                         SetCtlValue(itemcntlhand, 1); {hilite the control}
  791.                     end
  792.                 else
  793.                     SetCtlValue(itemcntlhand, 0); {unlilite the control}
  794.             end;
  795.     end;
  796.  
  797. {--------------------Outline DLOGs Default Button---------------------}
  798.     procedure DrawDefaultBtn (theItem: integer; thisDlog: DialogPtr);
  799.         var
  800.             OptType: Integer;
  801.             OptBox: Rect;
  802.             ItemHdl: Handle;
  803.             oldDlog: DialogPtr;
  804.  
  805.     begin
  806.         GetPort(oldDlog);
  807.         SetPort(thisDlog);{ set window to current graf port }
  808. {Note: GetDItem gets info about dialogs}
  809.         GetDItem(thisDlog, theItem, OptType, ItemHdl, OptBox);  { get item location }
  810.         Pensize(3, 3);                                     { no wimpy outlines here }
  811.         InsetRect(OptBox, -4, -4);                 { set rectangle around button }
  812.         FrameRoundRect(OptBox, 16, 16);         { draw the sucker! }
  813.         PenSize(1, 1);                            { reset the PenSize}
  814.         SetPort(oldDlog);                            { RESET to the original port}
  815.     end; { of proc DrawDefaultBtn }
  816.  
  817.  
  818.     procedure HiLiteDLOGButton (theItem: integer; state: boolean; thisDlog: DialogPtr);
  819.         const
  820.             on = TRUE;
  821.             off = FALSE;
  822.         var
  823.             tipe: integer;
  824.             aHdl: Handle;
  825.             tempRect: rect;
  826.     begin
  827.         GetDItem(thisDlog, theItem, tipe, aHdl, tempRect);    {Get the item handle}
  828.  
  829.         if state = on then
  830.             HiliteControl(controlhandle(aHdl), 0)                {un-dim button}
  831.         else
  832.             HiliteControl(controlhandle(aHdl), 255);            {Dim the button}
  833.     end;{}
  834.  
  835. {--------------------Draw DLOG Title---------------------}
  836. {this procedure expects the DLOG to already have been set with SetPort}
  837.     procedure DLOGTitle (title, FcnName: str255);
  838.         const
  839.             defaultFont = Geneva;
  840.             niceFont = Helvetica;
  841.             fontSyz = 12;
  842.             fontOffset = 12;
  843.             extraFHeight = 2;
  844.             lineOffset = 5;
  845.         var
  846.             aStr: str255;
  847.             anInt: integer;
  848.             center: integer;
  849.             theFont: integer;
  850.             myFRec: FontInfo;
  851.             pState: PenState;    {a great University}
  852.     begin
  853.         GetPenState(pState);    {save current pen info}
  854.         PenNormal;
  855.  
  856.         if RealFont(niceFont, fontSyz) then    {decide which font to use}
  857.             theFont := niceFont
  858.         else
  859.             theFont := defaultFont;
  860.  
  861.         TextFont(theFont);
  862.         TextSize(fontSyz);
  863.         TextFace([Bold]);
  864.         GetFontInfo(myFRec);
  865.  
  866.         foreColor(blueColor);    {old-style color}
  867. {•  anInt := myFRec.ascent + myFRec.descent + extraFHeight;•}
  868.         anInt := myFRec.ascent + extraFHeight;
  869.         MoveTo(fontOffset, anInt);
  870.         WriteDraw(title);
  871.  
  872.         if FcnName <> '' then        {if we have a name to draw also…}
  873.             begin
  874.                 MoveTo(thePort^.portRect.right - fontOffset - StringWidth(FcnName), anInt);
  875.                 TextFace([Italic, Bold]);
  876.                 WriteDraw(FcnName);
  877.             end;
  878.  
  879.         foreColor(redColor);    {old-style color}
  880.         with thePort^.portRect do
  881.             begin
  882.                 MoveTo(lineOffset, anInt + 3);
  883.                 LineTo(right - lineOffset, anInt + 3);
  884.                 PenSize(1, 2);
  885.                 MoveTo(lineOffset, anInt + 5);
  886.                 LineTo(right - lineOffset, anInt + 5);
  887.             end;
  888.  
  889.         foreColor(blackColor);
  890.         TextFace([]);
  891.         TextSize(9);
  892.         SetPenState(pState);    {restore to saved pen info}
  893.     end;
  894.  
  895. {=======================================================================================    }
  896. {Get enclosing rectangle of a dialog item}
  897.     function GetDBox (theDlog: dialogPtr; theItem: integer): rect;
  898.         var
  899.             tipe: integer;
  900.             hdl: handle;
  901.             theRect: rect;
  902.     begin
  903.         GetDItem(theDlog, theItem, tipe, hdl, theRect);
  904.         GetDBox := theRect;
  905.     end;{GetDBox}
  906.  
  907. {=======================================================================================    }
  908. {get handle of item in dialog}
  909.     function GetDLOGIHandle (theDLOG: dialogPtr; theItem: integer): Handle;
  910.         var
  911.             tipe: integer;
  912.             aRect: rect;
  913.             aHdl: handle;
  914.     begin
  915.         GetDItem(theDLOG, theItem, tipe, aHdl, aRect);
  916.         GetDLOGIHandle := aHdl;
  917.     end;{GetHandle}
  918.  
  919.  
  920. {=======================================================================================    }
  921. {write a label, to the right or left of a rectangle}
  922.     procedure WriteLabel (theStr: Str255; theRect: rect; toTheRight: boolean);
  923.         const
  924.             vertOff = 4;
  925.             horizOff = 6;
  926.         var
  927.             aHandle: handle;
  928.             aPt: point;
  929.     begin
  930.         TextFont(0);
  931.         TextFace([]);
  932.         TextSize(12);
  933.         PenNormal;
  934.         with theRect do
  935.             if ToTheRight then
  936.                 begin
  937.                     SetPt(aPt, right + horizOff, bottom - vertOff);
  938.                     left := right + 1;
  939.                     right := right + (StringWidth(theStr) + horizOff + 6);
  940.                 end
  941.             else    {it's to the left}
  942.                 begin
  943.                     SetPt(aPt, left - (horizOff + StringWidth(theStr)), bottom - vertOff);
  944.                     right := left - 4;
  945.                     left := left - (StringWidth(theStr) + horizOff + 6);
  946.                 end;{if ToTheRight…}
  947.         EraseRect(theRect);
  948.         MoveTo(aPt.h, aPt.v);
  949.         WriteDraw(theStr);
  950.     end;{WriteLabel}
  951.  
  952.  
  953. {=======================================================================================}
  954.     procedure ZoomRect (zoomUp: boolean; smallRect, bigRect: rect);
  955.  
  956.         const
  957.             zoomSteps = 16;
  958.  
  959.         var
  960.             rect1, rect2, rect3, rect4: Rect;
  961.             i, j: INTEGER;
  962. {•   savePort, thisPort: GrafPtr;•}
  963.             fract, factor, one: Fixed;
  964.  
  965.         function ZoomBlend (smallCoord, bigCoord: INTEGER): INTEGER;
  966.             var
  967.                 smallFix, bigFix, tempFix: Fixed;
  968.         begin
  969.             smallFix := one * smallCoord;
  970.             bigFix := one * bigCoord;
  971.             tempFix := FixMul(fract, bigFix) + FixMul(one - fract, smallFix);
  972.             ZoomBlend := FixRound(tempFix);
  973.         end;
  974.  
  975.     begin
  976.         PenPat(gray);
  977.         PenMode(notPatXor);
  978.  
  979.         one := 65536;
  980.         if zoomUp then
  981.             begin
  982.                 rect1 := smallRect;
  983.                 factor := FixRatio(6, 5);
  984.                 fract := FixRatio(541, 10000);
  985.             end
  986.         else
  987.             begin
  988.                 rect1 := bigRect;
  989.                 factor := FixRatio(5, 6);
  990.                 fract := one;
  991.             end;
  992.  
  993.         rect2 := rect1;
  994.         rect3 := rect1;
  995.         FrameRect(rect1);
  996.  
  997.         for i := 1 to zoomSteps do
  998.             begin
  999.                 rect4.left := ZoomBlend(smallRect.left, bigRect.left);
  1000.                 rect4.right := ZoomBlend(smallRect.right, bigRect.right);
  1001.                 rect4.top := ZoomBlend(smallRect.top, bigRect.top);
  1002.                 rect4.bottom := ZoomBlend(smallRect.bottom, bigRect.bottom);
  1003.  
  1004.                 FrameRect(rect4);
  1005.                 FrameRect(rect1);
  1006.                 rect1 := rect2;
  1007.                 rect2 := rect3;
  1008.                 rect3 := rect4;
  1009.  
  1010.                 fract := FixMul(fract, factor);
  1011.             end;
  1012.         FrameRect(rect1);
  1013.         FrameRect(rect2);
  1014.         FrameRect(rect3);
  1015.         PenNormal;
  1016.     end;
  1017.  
  1018. {===========================================================}
  1019. {draws a 2-pixel shadow around a rectangle}
  1020.     procedure ShadowBox (theRect: Rect);
  1021.     begin
  1022.         PenSize(2, 2);
  1023.         with theRect do
  1024.             begin
  1025.                 MoveTo(left + 2, bottom);
  1026.                 LineTo(Right, bottom);
  1027.                 MoveTo(right, Top + 2);
  1028.                 LineTo(Right, Bottom);
  1029.             end;
  1030.         PenSize(1, 1);
  1031.         FrameRect(theRect);
  1032.     end;{ShadowBox}
  1033.  
  1034.  
  1035.  
  1036.  
  1037. {--------------------Simulate MouseDown in Button---------------------}
  1038.     procedure ClickButton (Dptr: DialogPtr; ItemNo: integer);
  1039.  
  1040. {    Inside Macintosh leaves out the fact that if you use a filter procedure        }
  1041. {in the ModalDialog call you need to simulate a clicking of the OK button when    }
  1042. {the return key is hit.  This one of two possible techniques where we directly    }
  1043. {highlight and unhighlight the button.  The other technique would be to add a     }
  1044. {mouse down event to the event queue in which the mouse coordinates are         }
  1045. {somewhere inside of the OK button.  JWIND}
  1046.  
  1047.         var
  1048.             IType: integer;
  1049.             ButtonHandle: Handle;
  1050.             Box: rect;
  1051.             L: LongInt;
  1052.  
  1053.     begin
  1054.         GetDItem(Dptr, ItemNo, IType, ButtonHandle, Box);
  1055.         HiliteControl(ControlHandle(ButtonHandle), 253);
  1056.         Delay(8, L);
  1057.         HiliteControl(ControlHandle(ButtonHandle), 0);
  1058.     end; { ClickButton }
  1059.  
  1060.  
  1061. {check to see if the string passed contains only numerals and a decimal}
  1062. {Returns a string explaining what was wring, if anything}
  1063.     function IsStringReal (theStr: str255; var ItsBadBecause: str255): boolean;
  1064.         label
  1065.             99;
  1066.         var
  1067.             i, decimalFound, negativesFound: integer;
  1068.             aChar: char;
  1069.             Okay: boolean;
  1070.     begin
  1071.         okay := TRUE;
  1072.         decimalFound := 0;
  1073.         negativesFound := 0;
  1074.         ItsBadBecause := '';
  1075.         for i := 1 to length(theStr) do
  1076.             begin
  1077.                 aChar := Copy(theStr, i, 1);
  1078.                 if aChar = '.' then
  1079.                     decimalFound := decimalFound + 1;
  1080.                 if decimalFound > 1 then
  1081.                     begin
  1082.                         ItsBadBecause := 'Too many decimals found';
  1083.                         okay := FALSE;
  1084.                         goto 99;
  1085.                     end;{if decimalFound > 1 then}
  1086.                 if aChar = '-' then
  1087.                     negativesFound := negativesFound + 1;
  1088.                 if negativesFound > 1 then
  1089.                     begin
  1090.                         ItsBadBecause := 'Too many "-"s found ';
  1091.                         okay := FALSE;
  1092.                         goto 99;
  1093.                     end;{if negativesFound > 1 then}
  1094.                 if not (aChar in ['0'..'9', '-', '.']) then
  1095.                     begin
  1096.                         ItsBadBecause := Concat('Non-numeric character found: ', aChar);
  1097.                         okay := FALSE;
  1098.                         goto 99;
  1099.                     end;{if not aChar in ['0'..'9', '-','.'] then}
  1100.             end;{for i := 1 to length(theStr)}
  1101. 99:
  1102.         IsStringReal := Okay;
  1103.     end;{IsStringReal}
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109. {----------------Convert a Numeric String to an Integer----------------}
  1110.     function String2Int (theStr: Str255): integer;
  1111.         var
  1112.             aLongInt: longint;
  1113.     begin
  1114.         StringToNum(theStr, aLongInt);
  1115.         if aLongInt > maxInt then
  1116.             begin
  1117.                 DoMessage('That number is too big.', 'It must be less than 32767', '', '');
  1118.                 aLongInt := 0;
  1119.             end;
  1120.         String2Int := aLongInt;
  1121.     end;{String2Int}
  1122.  
  1123. {----------------Convert a Numeric String to an Integer----------------}
  1124.     function Int2String (theInt: integer): str255;
  1125.         var
  1126.             aLongInt: longint;
  1127.             aStr: str255;
  1128.     begin
  1129.         aLongInt := theInt;
  1130.         NumToString(aLongInt, aStr);
  1131.         Int2String := aStr;
  1132.     end;{String2Int}
  1133.  
  1134.  {--------------------Convert a Real to a Str255---------------------}
  1135.     function Real2String (aReal: real): str255;
  1136.         var
  1137.             aDecForm: DecForm;
  1138.             aDecStr: DecStr;
  1139.             aStr: str255;
  1140.     begin
  1141.         aDecform.Style := FixedDecimal;
  1142.         aDecform.digits := 2;
  1143.         Num2Str(aDecForm, aReal, aDecStr);
  1144.         aStr := aDecStr;
  1145.         Real2String := aStr;
  1146.     end;{Real2Str}
  1147.  
  1148.  {--------------------Convert a Str255 to a Real---------------------}
  1149. {This is actually very simple…}
  1150.     function String2Real (aStr: str255): real;
  1151.     begin
  1152.         String2Real := Str2Num(aStr);
  1153.     end;{String2Real}
  1154.  
  1155. {=======================================================================================    }
  1156.     function AddNewPrefs (var aPrefHdl: PrefHdl): Boolean;
  1157.         var
  1158.             err: OSerr;
  1159.             aHandle: Handle;
  1160.     begin
  1161.         AddNewPrefs := FALSE;
  1162.         aPrefHdl := nil;
  1163.  
  1164.         aPrefHdl := PrefHdl(NewHandle(sizeof(PrefRec)));
  1165.  
  1166.         HNoPurge(Handle(aPrefHdl));
  1167.         MoveHHi(Handle(aPrefHdl));
  1168.         HLock(Handle(aPrefHdl));
  1169.         AddResource(Handle(aPrefHdl), k_PrefsResType, k_PrefsResID, 'Prefs');
  1170.         err := ResError;
  1171.  
  1172.         if (aPrefHdl = nil) or (err <> noErr) then    {AddNewPrefs failed!}
  1173.             begin
  1174.                 DisposeHandle(Handle(aPrefHdl));
  1175.                 exit(AddNewPrefs);
  1176.             end;
  1177.         WriteResource(Handle(aPrefHdl));
  1178.         err := ResError;
  1179.         if err <> noErr then
  1180.             exit(AddNewPrefs);
  1181.  
  1182.         Hunlock(Handle(aPrefHdl));
  1183.         AddNewPrefs := TRUE;
  1184.  
  1185.     end;{AddNewPrefs}
  1186.  
  1187. {=======================================================================================    }
  1188.     procedure RewritePrefs (prefs: PrefRec);
  1189.         var
  1190.             err: integer;
  1191.             aPrefHdl: PrefHdl;
  1192.     begin
  1193.         UseResFile(appResFileRef);    {just in case it got changed somehow…}
  1194.         aPrefHdl := PrefHdl(GetResource(k_PrefsResType, k_PrefsResID));
  1195.         err := ResError;
  1196.         if (aPrefHdl = nil) or (err <> noErr) then
  1197.             if not AddNewPrefs(aPrefHdl) then
  1198.                 exit(RewritePrefs);
  1199.  
  1200. {stuff our pref values into the resource's handle}
  1201.         aPrefHdl^^.def_alwaysDraw := prefs.def_alwaysDraw;
  1202.         aPrefHdl^^.def_alwaysGrowBox := prefs.def_alwaysGrowBox;
  1203.         aPrefHdl^^.def_alwaysStatBox := prefs.def_alwaysStatBox;
  1204.  
  1205.         ChangedResource(Handle(aPrefHdl));
  1206.         err := ResError;
  1207.         if err = noErr then
  1208.             WriteResource(Handle(aPrefHdl));
  1209.         err := ResError;
  1210.         if err <> noErr then
  1211.             SysBeep(1);
  1212.  
  1213.         DisposHandle(Handle(aPrefHdl));
  1214.     end;{RewritePrefs}
  1215.  
  1216.  
  1217. {=======================================================================================    }
  1218.     procedure InitPrefs (var thePrefs: PrefRec);
  1219.     begin
  1220.         thePrefs.def_alwaysDraw := TRUE;
  1221.         thePrefs.def_alwaysGrowBox := TRUE;
  1222.         thePrefs.def_alwaysStatBox := TRUE;
  1223.     end;
  1224.  
  1225.  
  1226. {=======================================================================================    }
  1227.     procedure SetUpPrefs (var prefs: PrefRec);
  1228.         var
  1229.             err: OSerr;
  1230.             aPrefHdl: PrefHdl;
  1231.     begin
  1232.         InitPrefs(prefs);        {make sure, no matter what, that we have valid values}
  1233.  
  1234.         UseResFile(appResFileRef);    {just in case it got changed somehow…}
  1235.         aPrefHdl := PrefHdl(GetResource(k_PrefsResType, k_PrefsResID));
  1236.         err := ResError;
  1237.         if (aPrefHdl = nil) or (err <> noErr) then    {failed to get resource}
  1238.             exit(SetUpPrefs);                                        {so exit and just use the defaults}
  1239.  
  1240. {here is where we suck the marrow out of our resource-based prefs}
  1241. {and store it in our humble, global prefs record}
  1242.         prefs.def_alwaysDraw := aPrefHdl^^.def_alwaysDraw;
  1243.         prefs.def_alwaysGrowBox := aPrefHdl^^.def_alwaysGrowBox;
  1244.         prefs.def_alwaysStatBox := aPrefHdl^^.def_alwaysStatBox;
  1245.  
  1246.         DisposHandle(Handle(aPrefHdl));
  1247.  
  1248.     end;    {SetUpPrefs}
  1249.  
  1250.  
  1251.  
  1252.  
  1253. {=======================================================================================    }
  1254.     procedure PrefsDLOG;
  1255.         const
  1256.             PrefsDLOGID = 402;
  1257.  
  1258.             Draw_Chk = 4;
  1259.             Grow_Chk = 5;
  1260.             Stats_Chk = 6;
  1261.             Poly_Chk = 7;
  1262.         var
  1263.             UserPrefsDLOGPtr: DialogPtr;
  1264.             OldPort: GrafPtr;
  1265.             itemHit: integer;
  1266.             finished: Boolean;
  1267.  
  1268.             AutoRedraw, GrowBox, StatBox, PolyBox: Boolean;
  1269.  
  1270.     begin
  1271.  
  1272.         GetPort(OldPort);
  1273.  
  1274.         UserPrefsDLOGPtr := GetNewDialog(PrefsDLOGID, nil, Pointer(-1));
  1275.         CenterWindow(UserPrefsDLOGPtr);
  1276.         SetPort(UserPrefsDLOGPtr);
  1277.         ShowWindow(UserPrefsDLOGPtr);
  1278.  
  1279.         DrawDefaultBtn(ok, UserPrefsDLOGPtr);    {Outline Default Button}
  1280.  
  1281.         with prefs do
  1282.             begin
  1283.                 AutoRedraw := def_alwaysDraw;
  1284.                 GrowBox := def_alwaysGrowBox;
  1285.                 StatBox := def_alwaysStatBox;
  1286.                 PolyBox := def_alwaysPolyBox;
  1287.             end;    {with}
  1288.  
  1289.         CheckABox(UserPrefsDLOGPtr, Draw_Chk, AutoRedraw);
  1290.         CheckABox(UserPrefsDLOGPtr, Grow_Chk, GrowBox);
  1291.         CheckABox(UserPrefsDLOGPtr, Stats_Chk, StatBox);
  1292.         CheckABox(UserPrefsDLOGPtr, Poly_Chk, PolyBox);
  1293.  
  1294.         finished := FALSE;
  1295.  
  1296.         repeat
  1297.             begin
  1298.                 ModalDialog(nil, itemHit);    {Wait until an item is hit}
  1299.                 case itemHit of
  1300.                     ok: 
  1301.                         begin
  1302.                             curSplat.autoRedraw := AutoRedraw;
  1303.                             if (AutoRedraw <> prefs.def_alwaysDraw) and (showToolWind) then
  1304.                                 begin
  1305.                                     SetPort(toolWindPtr);
  1306.                                     InvalRect(autoDrawChkBox);
  1307.                                     InvalRect(drawBtnRect);
  1308.                                     SetPort(UserPrefsDLOGPtr);
  1309.                                 end;
  1310.                             prefs.def_alwaysDraw := AutoRedraw;
  1311.  
  1312.                             curSplat.autoFill := PolyBox;
  1313.                             if (PolyBox <> prefs.def_alwaysPolyBox) and (showToolWind) then
  1314.                                 begin
  1315.                                     SetPort(toolWindPtr);
  1316.                                     InvalRect(autoFillChkBox);
  1317.                                     InvalRect(fillBtnRect);
  1318.                                     SetPort(UserPrefsDLOGPtr);
  1319.                                 end;
  1320.                             prefs.def_alwaysPolyBox := PolyBox;
  1321.  
  1322.                             if (prefs.def_alwaysGrowBox <> GrowBox) or (prefs.def_alwaysStatBox <> StatBox) then
  1323.                                 begin
  1324.                                     SetPort(DrawWindPtr);
  1325.                                     EraseRect(GrowIconRect);
  1326.                                     InvalRect(GrowIconRect);
  1327.                                     EraseRect(curSplat.statsBox);
  1328.                                     InvalRect(curSplat.statsBox);
  1329.                                     SetPort(UserPrefsDLOGPtr);
  1330.                                 end;
  1331.                             prefs.def_alwaysGrowBox := GrowBox;
  1332.                             prefs.def_alwaysStatBox := StatBox;
  1333.                             finished := TRUE;
  1334.                         end;
  1335.                     cancel: 
  1336.                         finished := TRUE;
  1337.                     Draw_Chk: 
  1338.                         begin
  1339.                             AutoRedraw := not AutoRedraw;
  1340.                             CheckABox(UserPrefsDLOGPtr, Draw_Chk, AutoRedraw);
  1341.                         end;
  1342.                     Grow_Chk: 
  1343.                         begin
  1344.                             GrowBox := not GrowBox;
  1345.                             CheckABox(UserPrefsDLOGPtr, Grow_Chk, GrowBox);
  1346.                         end;
  1347.                     Stats_Chk: 
  1348.                         begin
  1349.                             StatBox := not StatBox;
  1350.                             CheckABox(UserPrefsDLOGPtr, Stats_Chk, StatBox);
  1351.                         end;
  1352.                     Poly_Chk: 
  1353.                         begin
  1354.                             PolyBox := not PolyBox;
  1355.                             CheckABox(UserPrefsDLOGPtr, Poly_Chk, PolyBox);
  1356.                         end;
  1357.                     otherwise
  1358.                         ;
  1359.                 end;{case}
  1360.             end;{repeat}
  1361.         until finished;    {repeat…}
  1362.  
  1363.         DisposDialog(UserPrefsDLOGPtr);{Flush the dialog out of memory}
  1364.  
  1365.     end;{PrefsDLOG}
  1366.  
  1367. {===========================================================================}
  1368. {For debugging}
  1369. {$SETC debuggIt = FALSE}
  1370.  
  1371. {$IFC debuggIt}
  1372.     procedure SplatMsg (myStr: str255);
  1373.         var
  1374.             oldPort: GrafPtr;
  1375.             aRect: rect;
  1376.             anInt: integer;
  1377.     begin
  1378.         GetPort(oldPort);
  1379.         SetPort(DrawWindPtr);
  1380.         aRect := thePort^.portRect;
  1381.         aRect.left := aRect.right - 200;
  1382.         aRect.bottom := aRect.top + 22;
  1383.         ClipRect(aRect);
  1384.         EraseRect(aRect);
  1385.         TextFont(0);
  1386.         TextSize(12);
  1387.         anInt := StringWidth(myStr) div 2;
  1388.         MoveTo(aRect.left + ((aRect.right - aRect.left) div 2 - anInt), aRect.top + 14);
  1389.         DrawString(myStr);
  1390.         PenSize(1, 1);
  1391.         FrameRect(aRect);
  1392.         PenNormal;
  1393.         ClipRect(thePort^.portRect);
  1394.         SetPort(oldPort);
  1395.     end;    {SplatMsg}
  1396. {$ENDC debuggIT}
  1397.  
  1398.     procedure SetForeColor (red, green, blue: integer);
  1399.         var
  1400.             hue: RGBColor;
  1401.     begin
  1402.         hue.red := red;
  1403.         hue.green := green;
  1404.         hue.blue := blue;
  1405.         RGBForeColor(hue);
  1406.     end;
  1407.  
  1408. {===========================================================================}
  1409.     procedure SplatStatistics (var aSplatRec: SplatRec);
  1410.         const
  1411.             linesInParagraph = 3;
  1412.             indent = 4;
  1413.         var
  1414.             oldPort: GrafPtr;
  1415.             Paragraph: array[1..linesInParagraph] of str255;
  1416.             leading, lineNo, longestLine: integer;
  1417.             fInfo: fontInfo;
  1418.             aStr: str255;
  1419.             aRect: rect;
  1420.     begin
  1421.         if not prefs.def_alwaysStatBox then
  1422.             exit(SplatStatistics);
  1423.         GetPort(oldPort);
  1424.         SetPort(DrawWindPtr);
  1425.  
  1426.         TextFont(aSplatRec.statsFont);
  1427.         TextSize(9);
  1428.         TextFace([]);
  1429.         GetFontInfo(fInfo);
  1430.         leading := fInfo.ascent + fInfo.descent + fInfo.leading;
  1431.  
  1432.         Paragraph[1] := aSplatRec.name;
  1433.         aStr := Int2String(aSplatRec.numPtsSoFar);
  1434.         Paragraph[2] := concat('Num. pts. so far: ', aStr);
  1435.         if (aSplatRec.numSplats = 1) then
  1436.             Paragraph[3] := 'One splat Drawn'
  1437.         else
  1438.             begin
  1439.                 aStr := Int2String(aSplatRec.numSplats);
  1440.                 Paragraph[3] := concat(aStr, ' Splats Drawn');
  1441.             end;
  1442.  
  1443.         longestLine := StringWidth(Paragraph[1]);
  1444.         if StringWidth(Paragraph[2]) > longestLine then
  1445.             longestLine := StringWidth(Paragraph[2])
  1446.         else if StringWidth(Paragraph[3]) > longestLine then
  1447.             longestLine := StringWidth(Paragraph[3]);
  1448.  
  1449.  
  1450.         aRect := aSplatRec.statsBox;
  1451.         aRect.bottom := aRect.top + (linesInParagraph * leading + 9);
  1452.         aRect.right := aRect.left + 12 + indent + longestLine;
  1453.         aSplatRec.statsBox := aRect;
  1454.  
  1455.         picComment(picGrpBeg, 0, nil);    {text and rects}
  1456.         picComment(picGrpBeg, 0, nil);    {rects}
  1457. {PenPat(Black);}
  1458.         SetForeColor($eeee, $eeee, $eeee);
  1459.         PaintRect(aRect);
  1460. {Fillrect(aRect, white);}
  1461.         SetForeColor($2222, $2222, $2222);
  1462.         FrameRect(aRect);
  1463.         InsetRect(aRect, 1, 1);
  1464.         SetForeColor($5555, $5555, $5555);
  1465.         FrameRect(aRect);
  1466.         InsetRect(aRect, 1, 1);
  1467.         SetForeColor($8888, $8888, $8888);
  1468.         FrameRect(aRect);
  1469.         InsetRect(aRect, 1, 1);
  1470.         SetForeColor($bbbb, $bbbb, $bbbb);
  1471.         FrameRect(aRect);
  1472.         picComment(picGrpEnd, 0, nil);    {rects}
  1473.         ClipRect(aRect);
  1474.  
  1475.         picComment(picGrpBeg, 0, nil);    {text}
  1476.         for lineNo := 1 to linesInParagraph do
  1477.             begin
  1478.                 picComment(StringBegin, 0, nil);    {string begin}
  1479.                 MoveTo(aRect.left, aRect.top + leading);
  1480.                 Move(indent, (lineNo - 1) * leading);
  1481.                 SetForeColor($aaaa, 0, 0);
  1482.                 DrawString(Paragraph[lineNo]);
  1483.                 picComment(StringEnd, 0, nil);    {string end}
  1484.             end;
  1485.         picComment(picGrpEnd, 0, nil);    {text}
  1486.         picComment(picGrpEnd, 0, nil);    {text and rects}
  1487.  
  1488.         PenNormal;
  1489.         ClipRect(thePort^.portRect);
  1490.         SetPort(oldPort);
  1491.     end;
  1492.  
  1493. {===========================================================================}
  1494.     procedure ClearAllSplats (var aSplatRec: SplatRec);
  1495.         var
  1496.             oldPort: grafPtr;
  1497.     begin
  1498.         GetPort(oldPort);
  1499.         SetPort(DrawWindPtr);
  1500.         EraseRect(thePort^.portRect);
  1501.         aSplatRec.numPtsSoFar := 0;
  1502.         aSplatRec.numSplats := 0;
  1503.         SplatStatistics(aSplatRec);
  1504.         SetPort(oldPort);
  1505.     end;    {ClearAllSplats}
  1506.  
  1507. {===========================================================================}
  1508. {port should already be set to DrawWindPtr}
  1509.     procedure DragStatsRect (var aSplatRec: SplatRec);
  1510.         var
  1511.             oldPort: GrafPtr;
  1512.             theRegion: rgnHandle;
  1513.             slopRect, limitRect: rect;
  1514.             mousePoint: point;
  1515.             aLong: longint;
  1516.             hi, lo: longint;
  1517.             width, height: integer;
  1518.             tempRect: rect;
  1519.     begin
  1520.         if not prefs.def_alwaysStatBox then
  1521.             exit(DragStatsRect);
  1522.  
  1523.         if not Button then
  1524.             exit(DragStatsRect);
  1525.  
  1526.         GetPort(oldPort);
  1527.         SetPort(DrawWindPtr);
  1528.         GetMouse(mousePoint);
  1529.         EraseRect(aSplatRec.statsBox);
  1530.         slopRect := thePort^.portRect;
  1531.         InsetRect(SlopRect, 1, 1);
  1532.         limitRect.left := mousePoint.h - aSplatRec.statsBox.left;
  1533.         limitRect.top := mousePoint.v - aSplatRec.statsBox.top;
  1534.         limitRect.right := slopRect.right - (aSplatRec.statsBox.right - mousePoint.h);
  1535.         limitRect.bottom := slopRect.bottom - (aSplatRec.statsBox.bottom - mousePoint.v);
  1536.         width := aSplatRec.statsBox.right - aSplatRec.statsBox.left;
  1537.         height := aSplatRec.statsBox.bottom - aSplatRec.statsBox.top;
  1538. {PenPat(black);}
  1539.         SetForeColor(0, 0, 0);
  1540.         theRegion := NewRgn;
  1541.         OpenRgn;
  1542.         FrameRect(aSplatRec.statsBox);
  1543.         CloseRgn(theRegion);
  1544.  
  1545.         aLong := DragGrayRgn(theRegion, mousePoint, limitRect, slopRect, 0, nil);
  1546.  
  1547.         hi := HiWord(aLong);
  1548.         lo := LoWord(aLong);
  1549.         if (hi = -32768) and (lo = -32768) then
  1550.             SysBeep(1)
  1551.         else
  1552.             aSplatRec.statsBox := theRegion^^.RgnBBox;
  1553.         DisposeRgn(theRegion);
  1554.  
  1555.         InvalRect(thePort^.portRect);
  1556.  
  1557.         SetPort(oldPort);
  1558.     end;
  1559.  
  1560. {$S Two}
  1561. {===========================================================================}
  1562.     function MakeArray (var anArrayHdl: BigArrayHdl): Boolean;
  1563.         var
  1564.             err: OSErr;
  1565.     begin
  1566.         anArrayHdl := BigArrayHdl(NewHandle(kArraySiz * sizeof(Point)));
  1567.         err := MemError;
  1568.         if err <> noErr then
  1569.             begin
  1570.                 Do_OK_ALRT;
  1571.                 anArrayHdl := nil;
  1572.                 MakeArray := FALSE;
  1573.                 exit(MakeArray);
  1574.             end;
  1575.         MakeArray := TRUE;
  1576.     end;
  1577.  
  1578.  
  1579. {===========================================================================}
  1580.     procedure RefreshSplats (var aSplatRec: SplatRec);
  1581.         var
  1582.             oldPort: GrafPtr;
  1583.             arrayPtr: bigArrayPtr;
  1584.             counter, numPts: integer;
  1585.             aPt: Point;
  1586.     begin
  1587.         if aSplatRec.myBigArray = nil then
  1588.             exit(RefreshSplats);
  1589.         if aSplatRec.numPtsSoFar = 0 then
  1590.             exit(RefreshSplats);
  1591.         GetPort(oldPort);
  1592.         SetPort(DrawWindPtr);
  1593.         PenNormal;
  1594.  
  1595. {$IFC debuggIT}
  1596.         SplatMsg('RefreshSplats');
  1597. {$ENDC debuggIT}
  1598.  
  1599.         MoveHHi(Handle(aSplatRec.myBigArray));
  1600.         HLock(Handle(aSplatRec.myBigArray));
  1601.         arrayPtr := aSplatRec.myBigArray^;
  1602.  
  1603.         SetForeColor(Random, Random, Random);
  1604.         numPts := aSplatRec.numPtsSoFar - 1;    {subtract 1 'cuz numPtsSoFar actually points to 1 greater than last actual pt}
  1605.         for counter := 0 to numPts do
  1606.             begin
  1607.                 aPt := arrayPtr^[counter];
  1608.                 if aPt.h > k_MoveToSentinel then        {a negative .h means the point is to be moved-to}
  1609.                     MoveTo((aPt.h - k_Sentinel) + aSplatRec.blnMiddle.h, aPt.v + aSplatRec.blnMiddle.v)
  1610.                 else
  1611.                     LineTo(aPt.h + aSplatRec.blnMiddle.h, aPt.v + aSplatRec.blnMiddle.v);
  1612.             end;
  1613.  
  1614.         SplatStatistics(aSplatRec);
  1615.  
  1616.         HUnlock(Handle(aSplatRec.myBigArray));
  1617.         SetPort(oldPort);
  1618.     end;
  1619.  
  1620. {===========================================================================}
  1621. {this is very similar to RefreshSplats}
  1622.     procedure SplatPICT (aSplatRec: SplatRec; var aPicHdl: PicHandle);
  1623.         var
  1624.             oldPort: GrafPtr;
  1625.             arrayPtr: bigArrayPtr;
  1626.             counter, numPts: integer;
  1627.             aPt: Point;
  1628.     begin
  1629.         if aSplatRec.myBigArray = nil then
  1630.             exit(SplatPICT);
  1631.         if aSplatRec.numPtsSoFar = 0 then
  1632.             exit(SplatPICT);
  1633.         GetPort(oldPort);
  1634.         SetPort(DrawWindPtr);
  1635.         PenNormal;
  1636.  
  1637.         MoveHHi(Handle(aSplatRec.myBigArray));
  1638.         HLock(Handle(aSplatRec.myBigArray));
  1639.         arrayPtr := aSplatRec.myBigArray^;
  1640.  
  1641.         if aPicHdl <> nil then
  1642.             KillPicture(aPicHdl);
  1643.  
  1644.         aPicHdl := OpenPicture(thePort^.portRect);
  1645.         PicComment(picDwgBeg, 0, nil);
  1646.  
  1647.         PicComment(PicGrpBeg, 0, nil);
  1648.         aPt := arrayPtr^[0];        {first one is alsways a move-to}
  1649.         MoveTo((aPt.h - k_Sentinel) + aSplatRec.blnMiddle.h, aPt.v + aSplatRec.blnMiddle.v);
  1650.  
  1651.         numPts := aSplatRec.numPtsSoFar - 1;    {subtract 1 'cuz numPtsSoFar actually points to 1 greater than last actual pt}
  1652.         for counter := 1 to numPts do
  1653.             begin
  1654.                 aPt := arrayPtr^[counter];
  1655.                 if aPt.h > k_MoveToSentinel then        {a negative .h means the point is to be moved-to}
  1656.                     begin
  1657.                         PicComment(PicGrpEnd, 0, nil);        {end last splat, begin next}
  1658.                         PicComment(PicGrpBeg, 0, nil);
  1659.                         MoveTo((aPt.h - k_Sentinel) + aSplatRec.blnMiddle.h, aPt.v + aSplatRec.blnMiddle.v);
  1660.                     end
  1661.                 else
  1662.                     LineTo(aPt.h + aSplatRec.blnMiddle.h, aPt.v + aSplatRec.blnMiddle.v);
  1663.             end;
  1664.         PicComment(PicGrpEnd, 0, nil);
  1665.  
  1666.         SplatStatistics(aSplatRec);
  1667.  
  1668.         PicComment(PicDwgEnd, 0, nil);
  1669.         ClosePicture;
  1670.         HUnlock(Handle(aSplatRec.myBigArray));
  1671.         SetPort(oldPort);
  1672.     end;    {}
  1673.  
  1674. {===========================================================================}
  1675.     procedure DrawFilledSplat (var aSplatRec: SplatRec);
  1676.         var
  1677.             oldPort: GrafPtr;
  1678.             stepNum: integer;
  1679.             originalPt, nextPt: Point;
  1680.             thetaStep: real;
  1681.             aLong, longSize: longint;
  1682.             arrayPtr: bigArrayPtr;
  1683.             aSize: Size;
  1684.     begin
  1685.         GetPort(oldPort);
  1686.         SetPort(DrawWindPtr);
  1687.         PenNormal;
  1688.  
  1689.         if aSplatRec.myBigArray = nil then
  1690.             begin
  1691.                 SetPort(oldPort);
  1692.                 exit(DrawFilledSplat);
  1693.             end;
  1694.  
  1695.         if (aSplatRec.divisions + aSplatRec.numPtsSoFar + 1) > aSplatRec.maxPtsAllowed then
  1696.             begin
  1697.                 aSize := GetHandleSize(Handle(aSplatRec.myBigArray));
  1698.                 if aSize > 0 then
  1699.                     SetHandleSize(Handle(aSplatRec.myBigArray), aSize + 100 * sizeof(Point));    {add 100 places to array}
  1700.                 if (MemError <> noErr) or (aSize = 0) then
  1701.                     begin
  1702.                         SetPort(oldPort);
  1703.                         exit(DrawFilledSplat);
  1704.                     end;
  1705.             end;
  1706.  
  1707.         MoveHHi(Handle(aSplatRec.myBigArray));
  1708.         HLock(Handle(aSplatRec.myBigArray));
  1709.         arrayPtr := aSplatRec.myBigArray^;
  1710.  
  1711.         thetaStep := twoPi / aSplatRec.divisions;
  1712.  
  1713.         with aSplatRec do
  1714.             begin
  1715.                 SetPt(originalPt, round(innerRadius * cos(theta)), round(innerRadius * sin(theta)));
  1716.                 SetForeColor(Random, Random, Random);
  1717.                 poly := OpenPoly;
  1718.                 MoveTo(blnMiddle.h + originalPt.h, blnMiddle.v + originalPt.v);
  1719.                 arrayPtr^[numPtsSoFar].h := k_Sentinel + originalPt.h;
  1720.                 arrayPtr^[numPtsSoFar].v := originalPt.v;
  1721.                 numPtsSoFar := numPtsSoFar + 1;
  1722.             end;
  1723.  
  1724.         for stepNum := 1 to (aSplatRec.divisions - 1) do
  1725.             begin
  1726.                 aSplatRec.theta := aSplatRec.theta + thetaStep;
  1727.                 with aSplatRec do
  1728.                     if odd(stepNum) then
  1729.                         SetPt(nextPt, round(outerRadius * cos(theta)), round(outerRadius * sin(theta)))
  1730.                     else
  1731.                         SetPt(nextPt, round(innerRadius * cos(theta)), round(innerRadius * sin(theta)));
  1732.                 LineTo(aSplatRec.blnMiddle.h + nextPt.h, aSplatRec.blnMiddle.v + nextPt.v);
  1733.                 arrayPtr^[aSplatRec.numPtsSoFar].h := nextPt.h;
  1734.                 arrayPtr^[aSplatRec.numPtsSoFar].v := nextPt.v;
  1735.                 aSplatRec.numPtsSoFar := aSplatRec.numPtsSoFar + 1;
  1736.             end;
  1737. {SetForeColor(0, 0, 0);}
  1738.         LineTo(aSplatRec.blnMiddle.h + originalPt.h, aSplatRec.blnMiddle.v + originalPt.v);
  1739.         arrayPtr^[aSplatRec.numPtsSoFar].h := originalPt.h;
  1740.         arrayPtr^[aSplatRec.numPtsSoFar].v := originalPt.v;
  1741.         aSplatRec.numPtsSoFar := aSplatRec.numPtsSoFar + 1;
  1742.         aSplatRec.theta := 0.0;
  1743.  
  1744.         ClosePoly;
  1745.         PaintPoly(poly);
  1746.         SetForeColor(0, 0, 0);
  1747.         FramePoly(poly);
  1748.         KillPoly(poly);
  1749.         HUnlock(Handle(aSplatRec.myBigArray));
  1750.  
  1751.         aSplatRec.numSplats := aSplatRec.numSplats + 1;
  1752.  
  1753.         SetPort(oldPort);
  1754.     end;    {DrawFilledSplat}
  1755.  
  1756.  
  1757. {===========================================================================}
  1758.     procedure DrawSplat (var aSplatRec: SplatRec);
  1759.         var
  1760.             oldPort: GrafPtr;
  1761.             stepNum: integer;
  1762.             originalPt, nextPt: Point;
  1763.             thetaStep: real;
  1764.             aLong, longSize: longint;
  1765.             arrayPtr: bigArrayPtr;
  1766.             aSize: Size;
  1767.     begin
  1768.         GetPort(oldPort);
  1769.         SetPort(DrawWindPtr);
  1770. {$IFC debuggIT}
  1771.         SplatMsg('DrawSplat');
  1772. {$ENDC debuggIT}
  1773.         PenNormal;
  1774.  
  1775.         if aSplatRec.myBigArray = nil then
  1776.             begin
  1777.                 DoOneLiner('**Error: Point array not allocated.');
  1778.                 SetPort(oldPort);
  1779.                 exit(DrawSplat);
  1780.             end;
  1781.  
  1782.         if (aSplatRec.divisions + aSplatRec.numPtsSoFar + 1) > aSplatRec.maxPtsAllowed then
  1783.             begin
  1784. {$IFC debuggIT}
  1785.                 SplatMsg('Growing handle');
  1786. {$ENDC debuggIT}
  1787.                 aSize := GetHandleSize(Handle(aSplatRec.myBigArray));
  1788.                 if aSize > 0 then
  1789.                     SetHandleSize(Handle(aSplatRec.myBigArray), aSize + 100 * sizeof(Point));    {add 100 places to array}
  1790.                 if (MemError <> noErr) or (aSize = 0) then
  1791.                     begin
  1792.                         DoOneLiner('**Error: Could not enlarge point-array.  Try smaller number of divisions.');
  1793.                         SetPort(oldPort);
  1794.                         exit(DrawSplat);
  1795.                     end;
  1796.             end;
  1797.  
  1798.         MoveHHi(Handle(aSplatRec.myBigArray));
  1799.         HLock(Handle(aSplatRec.myBigArray));
  1800.         arrayPtr := aSplatRec.myBigArray^;
  1801.  
  1802.         thetaStep := twoPi / aSplatRec.divisions;
  1803.  
  1804.         with aSplatRec do
  1805.             begin
  1806.                 SetPt(originalPt, round(innerRadius * cos(theta)), round(innerRadius * sin(theta)));
  1807.                 SetForeColor(Random, Random, Random);
  1808.                 MoveTo(blnMiddle.h + originalPt.h, blnMiddle.v + originalPt.v);
  1809.                 arrayPtr^[numPtsSoFar].h := k_Sentinel + originalPt.h;
  1810.                 arrayPtr^[numPtsSoFar].v := originalPt.v;
  1811.                 numPtsSoFar := numPtsSoFar + 1;
  1812.             end;
  1813.  
  1814.         for stepNum := 1 to (aSplatRec.divisions - 1) do
  1815.             begin
  1816.                 aSplatRec.theta := aSplatRec.theta + thetaStep;
  1817.                 with aSplatRec do
  1818.                     if odd(stepNum) then
  1819.                         SetPt(nextPt, round(outerRadius * cos(theta)), round(outerRadius * sin(theta)))
  1820.                     else
  1821.                         SetPt(nextPt, round(innerRadius * cos(theta)), round(innerRadius * sin(theta)));
  1822.                 LineTo(aSplatRec.blnMiddle.h + nextPt.h, aSplatRec.blnMiddle.v + nextPt.v);
  1823.                 arrayPtr^[aSplatRec.numPtsSoFar].h := nextPt.h;
  1824.                 arrayPtr^[aSplatRec.numPtsSoFar].v := nextPt.v;
  1825.                 aSplatRec.numPtsSoFar := aSplatRec.numPtsSoFar + 1;
  1826.             end;
  1827. {SetForeColor(0, 0, 0);}
  1828.         LineTo(aSplatRec.blnMiddle.h + originalPt.h, aSplatRec.blnMiddle.v + originalPt.v);
  1829.         arrayPtr^[aSplatRec.numPtsSoFar].h := originalPt.h;
  1830.         arrayPtr^[aSplatRec.numPtsSoFar].v := originalPt.v;
  1831.         aSplatRec.numPtsSoFar := aSplatRec.numPtsSoFar + 1;
  1832.         aSplatRec.theta := 0.0;
  1833.         HUnlock(Handle(aSplatRec.myBigArray));
  1834.  
  1835.         aSplatRec.numSplats := aSplatRec.numSplats + 1;
  1836.  
  1837.         SetPort(oldPort);
  1838.     end;    {DrawSplat}
  1839.  
  1840.  
  1841. {===========================================================================}
  1842.     procedure InitSplat (var aSplatRec: SplatRec);
  1843.         var
  1844.             error: boolean;
  1845.     begin
  1846.         SetPort(DrawWindPtr);
  1847.         with thePort^.portRect do
  1848.             begin
  1849.                 aSplatRec.blnMiddle.h := (right - left) div 2;
  1850.                 aSplatRec.blnMiddle.v := (bottom - top) div 2;
  1851.             end;
  1852.         aSplatRec.name := 'Untitled';
  1853.         aSplatRec.innerRadius := 55;
  1854.         aSplatRec.outerRadius := aSplatRec.innerRadius + 12;
  1855.         aSplatRec.divisions := 30;
  1856.         aSplatRec.numSplats := 0;
  1857.         aSplatRec.rad1Start := 120;
  1858.         aSplatRec.rad1End := 55;
  1859.         aSplatRec.rad2Start := 40;
  1860.         aSplatRec.rad2End := 80;
  1861.         aSplatRec.thetaEndDegrees := 24.0;
  1862.         aSplatRec.theta := 0.0;
  1863.         aSplatRec.iterations := 12;
  1864.  
  1865.         SetRect(aSplatRec.statsBox, 1, 1, 120, 40);
  1866.         if RealFont(helvetica, 9) then    {decide which font to use}
  1867.             aSplatRec.statsFont := helvetica
  1868.         else if RealFont(times, 9) then
  1869.             aSplatRec.statsFont := times
  1870.         else
  1871.             aSplatRec.statsFont := 0;    {use System font}
  1872.  
  1873.         aSplatRec.maxPtsAllowed := kArraySiz;
  1874.         aSplatRec.numPtsSoFar := 0;
  1875.         error := MakeArray(aSplatRec.myBigArray);
  1876.  
  1877.     end;    {InitSplat}
  1878.  
  1879.  
  1880. {======================================================================================= }
  1881.     function NewBlnFltr (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: integer): boolean;
  1882.         label
  1883.             10;
  1884.         var
  1885.             theRect: Rect;
  1886.             aHandle: handle;
  1887.             tipe, i: integer;
  1888.             myPt: point;
  1889.             KeyCh: Char;
  1890.     begin
  1891.         NewBlnFltr := FALSE;
  1892.         ItemHit := 0;
  1893.  
  1894.         GetMouse(myPt);
  1895. {Let's see if we're over any of the ET rects}
  1896.         for i := 3 to name_ET do
  1897.             begin
  1898.                 GetDItem(theDialog, i, tipe, aHandle, theRect);         {get the handle}
  1899.                 if PtInRect(myPt, theRect) then
  1900.                     if tipe = EditText then
  1901.                         begin
  1902.                             SetCursor(gIbeam^^);
  1903.                             goto 10;
  1904.                         end;
  1905.             end;{for i}
  1906.         InitCursor;                                    {make cursor Arrow if not over any ET rect}
  1907. 10:
  1908.         case theEvent.what of
  1909.             keydown, autoKey: 
  1910.                 begin    { trap key down events }
  1911.                     KeyCh := Chr(BitAnd(theEvent.message, charCodeMask));
  1912.                     if BitAnd(theEvent.modIFiers, CmdKey) <> 0 then    {Cmd key is down}
  1913.                         begin
  1914.                             ItemHit := -1;    {so the 'v','c', or 'x' won't be 'typed' into text box}
  1915.                             if theEvent.what <> AutoKey then    {we don't want to auto-key cmd-key equivs}
  1916.                                 case KeyCh of
  1917.                                     'x', 'X': 
  1918.                                         DlgCut(theDialog);
  1919.                                     'c', 'C': 
  1920.                                         DlgCopy(theDialog);
  1921.                                     'v', 'V': 
  1922.                                         DlgPaste(theDialog);
  1923.                                     '.': 
  1924.                                         begin
  1925.                                             itemHit := 2;
  1926.                                             ClickButton(theDialog, Cancel);
  1927.                                         end;
  1928.                                     otherwise
  1929.                                         SysBeep(1);    {not a valid Cmd-Key}
  1930.                                 end;    {case KeyCh of}
  1931.                         end    {if Cmd-key is down}
  1932.                     else
  1933.                         begin
  1934.                             ItemHit := 0;
  1935.                             if KeyCh in [char(k_CR), char(k_Enter)] then
  1936.                                 ItemHit := Okay;                                { Button equivalents }
  1937.                         end;
  1938.                 end;{keydown, autokey}
  1939.             otherwise
  1940.                 ;
  1941.         end;{case theEvent.what of}
  1942.  
  1943.         if ItemHit <> 0 then
  1944.             NewBlnFltr := True;           { don't pass back to modal }
  1945.  
  1946.         if ItemHit = Okay then       { Simulate clicking of the OK button }
  1947.             ClickButton(theDialog, Okay);
  1948.  
  1949.     end;
  1950. {===========================================================================}
  1951.     procedure NewSplat (var aSplatRec: SplatRec);
  1952.         var
  1953.             OldPort: GrafPtr;
  1954.             NewBaloonDLOGPtr: dialogPtr;
  1955.             itemHit, Tipe, anInt: integer;
  1956.             hdl: Handle;
  1957.             theRect: rect;
  1958.             aStr: Str255;
  1959.             aReal: Real;
  1960.             finished: boolean;
  1961.  
  1962.     begin
  1963.         if aSplatRec.myBigArray <> nil then
  1964.             DisposeHandle(Handle(aSplatRec.myBigArray));
  1965.         InitSplat(aSplatRec);
  1966.         SetCursor(gwatch^^);
  1967.         GetPort(OldPort);
  1968.         NewBaloonDLOGPtr := GetNewDialog(NewBlnDLOG_ID, nil, Pointer(-1));
  1969.  
  1970.         CenterWindow(NewBaloonDLOGPtr);
  1971.         SetPort(NewBaloonDLOGPtr);
  1972.  
  1973.         GetDItem(NewBaloonDLOGPtr, innerRad_ET, tipe, hdl, theRect);         {get the handle}
  1974.         aStr := Int2String(aSplatRec.innerRadius);
  1975.         SetIText(hdl, aStr);
  1976.  
  1977.         GetDItem(NewBaloonDLOGPtr, outerRad_ET, tipe, hdl, theRect);         {get the handle}
  1978.         aStr := Int2String(aSplatRec.outerRadius);
  1979.         SetIText(hdl, aStr);
  1980.  
  1981.         GetDItem(NewBaloonDLOGPtr, divisions_ET, tipe, hdl, theRect);         {get the handle}
  1982.         aStr := Int2String(aSplatRec.divisions);
  1983.         SetIText(hdl, aStr);
  1984.  
  1985.         GetDItem(NewBaloonDLOGPtr, name_ET, tipe, hdl, theRect);         {get the handle}
  1986.         SetIText(hdl, aSplatRec.name);
  1987.  
  1988.         CheckABox(NewBaloonDLOGPtr, autoDraw_Chk, prefs.def_alwaysDraw);
  1989.         CheckABox(NewBaloonDLOGPtr, groBox_Chk, prefs.def_alwaysGrowBox);
  1990.         CheckABox(NewBaloonDLOGPtr, statsBox_Chk, prefs.def_alwaysStatBox);
  1991.  
  1992.         InitCursor;
  1993.         ShowWindow(NewBaloonDLOGPtr);
  1994.         DrawDefaultBtn(Okay, NewBaloonDLOGPtr);    {Outline Default Button}
  1995.         SelIText(NewBaloonDLOGPtr, name_ET, 0, 32767);    {pre-doubleclick the item}
  1996.  
  1997.         finished := FALSE;
  1998.  
  1999.         repeat
  2000.             begin
  2001.                 ModalDialog(@NewBlnFltr, itemHit);{Wait until an item is hit}
  2002.                 case itemHit of
  2003.                     Okay: 
  2004.                         begin
  2005.                             GetDItem(NewBaloonDLOGPtr, innerRad_ET, tipe, hdl, theRect);         {get the handle}
  2006.                             GetIText(hdl, aStr);
  2007.                             aSplatRec.innerRadius := String2Int(aStr);
  2008.                             GetDItem(NewBaloonDLOGPtr, outerRad_ET, tipe, hdl, theRect);         {get the handle}
  2009.                             GetIText(hdl, aStr);
  2010.                             aSplatRec.outerRadius := String2Int(aStr);
  2011.                             GetDItem(NewBaloonDLOGPtr, divisions_ET, tipe, hdl, theRect);         {get the handle}
  2012.                             GetIText(hdl, aStr);
  2013.                             aSplatRec.divisions := String2Int(aStr);
  2014.                             GetDItem(NewBaloonDLOGPtr, name_ET, tipe, hdl, theRect);         {get the handle}
  2015.                             GetIText(hdl, aStr);
  2016.                             aSplatRec.name := aStr;
  2017.                             finished := TRUE;
  2018.                         end;
  2019.                     Cancel: 
  2020.                         begin
  2021.                             finished := TRUE;
  2022.                         end;
  2023.                     autoDraw_Chk: 
  2024.                         begin
  2025.                             prefs.def_alwaysDraw := not prefs.def_alwaysDraw;
  2026.                             CheckABox(NewBaloonDLOGPtr, autoDraw_Chk, prefs.def_alwaysDraw);
  2027.                         end;
  2028.                     groBox_Chk: 
  2029.                         begin
  2030.                             prefs.def_alwaysGrowBox := not prefs.def_alwaysGrowBox;
  2031.                             CheckABox(NewBaloonDLOGPtr, groBox_Chk, prefs.def_alwaysGrowBox);
  2032.                         end;
  2033.                     statsBox_Chk: 
  2034.                         begin
  2035.                             prefs.def_alwaysStatBox := not prefs.def_alwaysStatBox;
  2036.                             CheckABox(NewBaloonDLOGPtr, statsBox_Chk, prefs.def_alwaysStatBox);
  2037.                         end;
  2038.                     otherwise
  2039.                         ;
  2040.                 end{case}
  2041.             end;{begin}
  2042.         until finished;
  2043.  
  2044.         DisposDialog(NewBaloonDLOGPtr);{Flush the dialog out of memory}
  2045.         setPort(oldPort);
  2046.  
  2047.     end;    {NewSplat}
  2048.  
  2049. {======================================================================================= }
  2050. {Converts any angle to its positive equivalent angle : 0<=angle<360;}
  2051. {this function takes an angle (can be negative or positive and may}
  2052. {be greater than 360) and returns a positive angle such that any}
  2053. {negative angles are reevaluated into positive ones (e.g.,-15 degrees}
  2054. {gets returned as +345 degrees and any angles over 360 are }
  2055. {factored down, (e.g., 395 degrees becomes 35 degrees).}
  2056.     function MakeAngles (theAngle: real): real;
  2057.         var
  2058.             angleOffset: real;
  2059.     begin
  2060.         if theAngle < 0 then
  2061.             angleOffset := (round(theAngle / 360.0) - 1) * 360
  2062.         else
  2063.             angleOffset := round(theAngle / 360.0) * 360;
  2064.         MakeAngles := (theAngle - angleOffset);
  2065.     end;
  2066.  
  2067.  
  2068. {======================================================================================= }
  2069.     procedure SetUpETs (MacroDLOGPtr: dialogPtr);
  2070.         var
  2071.             aStr: str255;
  2072.             tipe, anInt, index: integer;
  2073.             hdl: handle;
  2074.             theRect: rect;
  2075.     begin
  2076.  
  2077.         GetDItem(MacroDLOGPtr, rad1_Start_ET, tipe, hdl, theRect);         {get the handle}
  2078.         aStr := Int2String(tempSplat.rad1Start);
  2079.         SetIText(hdl, aStr);
  2080.  
  2081.         GetDItem(MacroDLOGPtr, rad1_End_ET, tipe, hdl, theRect);         {get the handle}
  2082.         aStr := Int2String(tempSplat.rad1End);
  2083.         SetIText(hdl, aStr);
  2084.  
  2085.         GetDItem(MacroDLOGPtr, rad2_Start_ET, tipe, hdl, theRect);         {get the handle}
  2086.         aStr := Int2String(tempSplat.rad2Start);
  2087.         SetIText(hdl, aStr);
  2088.  
  2089.         GetDItem(MacroDLOGPtr, rad2_End_ET, tipe, hdl, theRect);         {get the handle}
  2090.         aStr := Int2String(tempSplat.rad2End);
  2091.         SetIText(hdl, aStr);
  2092.  
  2093.         GetDItem(MacroDLOGPtr, theta_ET, tipe, hdl, theRect);         {get the handle}
  2094.         aStr := Real2String(tempSplat.thetaEndDegrees);
  2095.         SetIText(hdl, aStr);
  2096.  
  2097.         GetDItem(MacroDLOGPtr, iterations_ET, tipe, hdl, theRect);         {get the handle}
  2098.         aStr := Int2String(tempSplat.iterations);
  2099.         SetIText(hdl, aStr);
  2100.  
  2101.         GetDItem(MacroDLOGPtr, divs_ET, tipe, hdl, theRect);         {get the handle}
  2102.         aStr := Int2String(tempSplat.divisions);
  2103.         SetIText(hdl, aStr);
  2104.  
  2105.  
  2106.     end;{SetUpETs}
  2107.  
  2108. {======================================================================================= }
  2109. {Get text and numbers out of  the ETs, error check them, return TRUE if they were}
  2110. {okay, FALSE if there was an error}
  2111.     function GetETs (MacroDLOGPtr: dialogPtr): boolean;
  2112.         var
  2113.             aStr: str255;
  2114.             tipe, anInt, index: integer;
  2115.             hdl: handle;
  2116.             theRect: rect;
  2117.             okay: boolean;
  2118.             aReal: real;
  2119.         function GetStr (theItem: integer): str255;
  2120.             var
  2121.                 aStr2: str255;
  2122.                 anInt: integer;
  2123.         begin
  2124.             GetDItem(MacroDLOGPtr, theItem, tipe, hdl, theRect);         {get the handle}
  2125.             GetIText(hdl, aStr2);
  2126.             GetStr := (aStr2);
  2127.         end;
  2128.     begin
  2129.         GetETs := FALSE;
  2130.  
  2131.         aStr := GetStr(rad1_Start_ET);
  2132.         anInt := String2Int(aStr);
  2133.         tempSplat.rad1Start := abs(anInt);
  2134.  
  2135.         aStr := GetStr(rad1_End_ET);
  2136.         anInt := String2Int(aStr);
  2137.         tempSplat.rad1End := abs(anInt);
  2138.  
  2139.         aStr := GetStr(rad2_Start_ET);
  2140.         anInt := String2Int(aStr);
  2141.         tempSplat.rad2Start := abs(anInt);
  2142.  
  2143.         aStr := GetStr(rad2_End_ET);
  2144.         anInt := String2Int(aStr);
  2145.         tempSplat.rad2End := abs(anInt);
  2146.  
  2147.         aStr := GetStr(theta_ET);
  2148.         aReal := String2Real(aStr);
  2149.         tempSplat.thetaEndDegrees := MakeAngles(aReal);
  2150.  
  2151.         aStr := GetStr(iterations_ET);
  2152.         anInt := String2Int(aStr);
  2153.         tempSplat.iterations := abs(anInt);
  2154.  
  2155.         aStr := GetStr(divs_ET);
  2156.         anInt := String2Int(aStr);
  2157.         tempSplat.divisions := abs(anInt);
  2158.  
  2159.  
  2160.         GetETs := TRUE;
  2161.     end;{GetETs}
  2162.  
  2163.  
  2164. {======================================================================================= }
  2165.     function MacroFilter (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: integer): boolean;
  2166.         label
  2167.             10;
  2168.         var
  2169.             tempRect: Rect;
  2170.             aHandle: handle;
  2171.             tipe, i: integer;
  2172.             myPt: point;
  2173.             KeyCh: Char;
  2174.     begin
  2175.         MacroFilter := FALSE;
  2176.         ItemHit := 0;
  2177.  
  2178.         GetMouse(myPt);
  2179. {Let's see if we're over any of the ET rects}
  2180.         for i := rad1_Start_ET to iterations_ET do
  2181.             begin
  2182.                 GetDItem(theDialog, i, tipe, aHandle, tempRect);         {get the handle}
  2183.                 if PtInRect(myPt, tempRect) and (tipe = EditText) then
  2184.                     begin
  2185.                         SetCursor(gIbeam^^);
  2186.                         goto 10;
  2187.                     end;{if PtInRect}
  2188.             end;{for i}
  2189.         InitCursor;                                    {make cursor Arrow if not over any ET rect}
  2190. 10:
  2191.         case theEvent.what of
  2192.             keydown, autoKey: 
  2193.                 begin    { trap key down events }
  2194.                     KeyCh := Chr(BitAnd(theEvent.message, charCodeMask));
  2195.                     if BitAnd(theEvent.modIFiers, CmdKey) <> 0 then    {Cmd key is down}
  2196.                         begin
  2197.                             ItemHit := -1;    {so the 'v','c', or 'x' won't be 'typed' into text box}
  2198.                             if theEvent.what <> AutoKey then    {we don't want to auto-key cmd-key equivs}
  2199.                                 case KeyCh of
  2200.                                     'x', 'X': 
  2201.                                         DlgCut(theDialog);
  2202.                                     'c', 'C': 
  2203.                                         DlgCopy(theDialog);
  2204.                                     'v', 'V': 
  2205.                                         DlgPaste(theDialog);
  2206.                                     '.': 
  2207.                                         begin
  2208.                                             itemHit := 2;
  2209.                                             ClickButton(theDialog, Cancel);
  2210.                                         end;
  2211.                                     otherwise
  2212.                                         SysBeep(1);    {not a valid Cmd-Key}
  2213.                                 end;    {case KeyCh of}
  2214.                         end    {if Cmd-key is down}
  2215.                     else
  2216.                         begin
  2217.                             ItemHit := 0;
  2218.                             if KeyCh in [char(k_CR), char(k_Enter)] then
  2219.                                 ItemHit := Okay;                                { Button equivalents }
  2220.                         end;
  2221.                 end;{keydown, autokey}
  2222.             otherwise
  2223.                 ;
  2224.         end;{case theEvent.what of}
  2225.  
  2226.         if ItemHit <> 0 then
  2227.             MacroFilter := True;           { don't pass back to modal }
  2228.  
  2229.         if ItemHit = Okay then       { Simulate clicking of the OK button }
  2230.             ClickButton(theDialog, Okay);
  2231.  
  2232.     end;
  2233.  
  2234. {======================================================================================= }
  2235.     function MakeMacro (var aSplat: SplatRec): boolean;
  2236.         var
  2237.             OldPort: GrafPtr;
  2238.             MacroDLOGPtr: dialogPtr;
  2239.             itemHit, Tipe, anInt: integer;
  2240.             aHdl: Handle;
  2241.             aRect: rect;
  2242.             aStr: Str255;
  2243.             aReal: Real;
  2244.             finished: boolean;
  2245.  
  2246.     begin
  2247.         SetCursor(gwatch^^);
  2248.         GetPort(OldPort);
  2249.         tempSplat := aSplat;
  2250.  
  2251.         MacroDLOGPtr := GetNewDialog(MacroDLOG_ID, nil, Pointer(-1));
  2252.  
  2253.         CenterWindow(MacroDLOGPtr);
  2254.         SetPort(MacroDLOGPtr);
  2255.         SetUpETs(MacroDLOGPtr);
  2256.  
  2257.         InitCursor;
  2258.         ShowWindow(MacroDLOGPtr);
  2259.         DrawDefaultBtn(Okay, MacroDLOGPtr);    {Outline Default Button}
  2260.         SelIText(MacroDLOGPtr, rad1_Start_ET, 0, 32767);    {pre-doubleclick the item}
  2261.  
  2262.         finished := FALSE;
  2263.  
  2264.         repeat
  2265.             begin
  2266.                 ModalDialog(@MacroFilter, itemHit);{Wait until an item is hit}
  2267.                 case itemHit of
  2268.                     Okay: 
  2269.                         begin
  2270.                             finished := GetETs(MacroDLOGPtr);{GetETs; if the ETs were okay then we 're done}
  2271.                             if finished then
  2272.                                 begin
  2273.                                     aSplat := tempSplat;
  2274.                                 end;
  2275.                             MakeMacro := TRUE;
  2276.                         end;
  2277.                     Cancel: 
  2278.                         begin
  2279.                             finished := TRUE;
  2280.                             MakeMacro := FALSE;
  2281.                         end;
  2282.                     otherwise
  2283.                         ;
  2284.                 end{case}
  2285.             end;{begin}
  2286.         until finished;
  2287.  
  2288.  
  2289.         DisposDialog(MacroDLOGPtr);{Flush the dialog out of memory}
  2290.         setPort(oldPort);
  2291.     end;    {MakeMacro}
  2292.  
  2293.  
  2294. {======================================================================================= }
  2295.     procedure DoMultiSplat (var aSplat: SplatRec);
  2296.         var
  2297.             curStep: integer;
  2298.             rad1Diff, rad2Diff, curTheta, thetaStep: real;
  2299.     begin
  2300.         tempSplat := aSplat;
  2301.         curTheta := 0.0;
  2302.         if tempSplat.thetaEndDegrees <> 0.0 then
  2303.             thetaStep := (twoPi * (tempSplat.thetaEndDegrees / 360.0)) / tempSplat.divisions
  2304.         else
  2305.             thetaStep := 0.0;
  2306.  
  2307.         with tempSplat do
  2308.             begin
  2309.                 rad1Diff := (rad1End - rad1Start) / iterations;
  2310.                 rad2Diff := (rad2End - rad2Start) / iterations;
  2311.             end;
  2312.  
  2313.         for curStep := 1 to tempSplat.iterations do
  2314.             begin
  2315.                 tempSplat.innerRadius := round(tempSplat.innerRadius + rad1Diff);
  2316.                 tempSplat.outerRadius := round(tempSplat.outerRadius + rad2Diff);
  2317.                 DrawSplat(tempSplat);
  2318.                 curTheta := curTheta + thetaStep;
  2319.                 tempSplat.theta := curTheta;
  2320.             end;
  2321.         aSplat.numPtsSoFar := tempSplat.numPtsSoFar;
  2322. {aSplat.numSplats := aSplat.numSplats + tempSplat.iterations;}
  2323.  
  2324.     end;
  2325.  
  2326. {===========================================================================}
  2327.     procedure DrawChkBox (chkBoxRect: rect; onOff: Boolean; which: integer);
  2328.         var
  2329.             aRect: rect;
  2330.     begin
  2331.         aRect := chkBoxRect;
  2332. {    InsetRect(aRect, 2, 2);}
  2333.  
  2334.         EraseRect(aRect);
  2335.         FrameRect(aRect);
  2336.         if onOff then    {if it's 'on', hilite it}
  2337.             begin
  2338.                 MoveTo(aRect.left, aRect.top);
  2339.                 LineTo(aRect.right - 1, aRect.bottom - 1);
  2340.                 MoveTo(aRect.right - 1, aRect.top);
  2341.                 LineTo(aRect.left, aRect.bottom - 1);
  2342.             end;
  2343.  
  2344.         MoveTo(chkBoxRect.right + 2, chkBoxRect.bottom);
  2345.         if (which = 1) then
  2346.             DrawString('Auto Draw')
  2347.         else if (which = 2) then
  2348.             DrawString('Auto Fill')
  2349.     end;    {DrawChkBox}
  2350.  
  2351.  
  2352. {===========================================================================}
  2353.     procedure HandleChkBox (chkBoxRect: rect; var onOff: Boolean; which: integer);
  2354.         var
  2355.             mouse: point;
  2356.             theRect: rect;
  2357.             mouseInBtn: boolean;
  2358.     begin
  2359.         mouseInBtn := FALSE;
  2360.  
  2361.         theRect := chkBoxRect;
  2362.         GetMouse(mouse);
  2363.  
  2364.         if not PtInRect(mouse, theRect) then
  2365.             exit(HandleChkBox);
  2366.  
  2367.         while StillDown do
  2368.             begin
  2369.                 GetMouse(mouse);
  2370.                 if PtInRect(mouse, theRect) then
  2371.                     begin
  2372.                         if (not mouseInBtn) then
  2373.                             begin
  2374.                                 mouseInBtn := TRUE;
  2375.                                 onOff := not onOff;
  2376.                                 if (which = 1) then
  2377.                                     DrawChkBox(theRect, onOff, 1)
  2378.                                 else
  2379.                                     DrawChkBox(theRect, onOff, 2)
  2380.                             end
  2381.                     end
  2382.                 else
  2383.                     begin
  2384.                         if (mouseInBtn) then
  2385.                             begin
  2386.                                 mouseInBtn := FALSE;
  2387.                                 onOff := not onOff;
  2388.                                 if (which = 1) then
  2389.                                     DrawChkBox(theRect, onOff, 1)
  2390.                                 else
  2391.                                     DrawChkBox(theRect, onOff, 2)
  2392.                             end;
  2393.                     end;
  2394.  
  2395.             end;{while}
  2396.  
  2397.     end;    {HandleChkBox}
  2398.  
  2399.  
  2400. {===========================================================================}
  2401.     procedure VerticalLabel (aRect: Rect; aStr: str255);
  2402.         const
  2403.             center = 5;    {center of label is 'center' pixels from left of rect}
  2404.         var
  2405.             numChars, leading, stringCenter, x, curVert: integer;
  2406.             fInfo: fontInfo;
  2407.     begin
  2408.         TextFont(helvetica);
  2409.         TextSize(9);
  2410.         TextFace([]);
  2411.         GetFontInfo(fInfo);
  2412.         leading := fInfo.ascent + fInfo.descent + fInfo.leading;
  2413.         stringCenter := aRect.left - center;
  2414.  
  2415.         foreColor(redColor);    {oldStyle color}
  2416.         curVert := aRect.top + leading;    {primed for first character}
  2417.         numChars := Length(aStr);
  2418.         for x := 1 to numChars do
  2419.             begin
  2420.                 MoveTo(stringCenter - (CharWidth(aStr[x]) div 2), curVert);
  2421.                 DrawChar(char(aStr[x]));
  2422.                 curVert := curVert + leading;
  2423.             end;
  2424.         foreColor(blackColor);    {oldStyle color}
  2425.     end;    {VerticalLabel}
  2426.  
  2427.  
  2428. {===========================================================================}
  2429.     function TrackButtonRect (therect: rect): boolean;
  2430. {This function will hilite and unhilite the rectangle you pass it as the user moves}
  2431. {the mouse in and out of the rectangle, and returns TRUE if the user released the}
  2432. {mouse button while the mouse was inside the rectangle, and FALSE if he/she did}
  2433. {not.  This simulates the effect you get when you click on a standard button, and}
  2434. {is useful to simulate "icon buttons".  Make sure your GrafPtr is set first!}
  2435.         var
  2436.             mouseloc: point;
  2437.             wasin, check: boolean;
  2438.  
  2439.     begin
  2440.         TrackButtonRect := false;
  2441.         invertroundrect(therect, 8, 8);
  2442.         wasin := true;
  2443.         repeat
  2444.             getmouse(mouseLoc);
  2445.             check := ptinrect(mouseloc, therect);
  2446.             if check <> wasin then
  2447.                 begin
  2448.                     wasin := check;
  2449.                     invertroundrect(therect, 8, 8);
  2450.                 end;
  2451.         until not stilldown;
  2452.         if wasin = true then
  2453.             begin
  2454.                 invertroundrect(therect, 8, 8);
  2455.                 TrackButtonRect := true;
  2456.             end;
  2457.     end;    {TrackButtonRect}
  2458.  
  2459. {===========================================================================}
  2460.     procedure ShowScrlValue (theControl: ControlHandle);
  2461.         var
  2462.             aRect: Rect;
  2463.             aStr: Str255;
  2464.             anInt: integer;
  2465.     begin
  2466.         aRect := theControl^^.contrlRect;
  2467.         aRect.top := aRect.bottom + 2;
  2468.         aRect.bottom := aRect.top + 11;
  2469.         aRect.left := aRect.left - 4;
  2470.         aRect.right := aRect.right + 4;
  2471.  
  2472.         EraseRect(aRect);
  2473.         anInt := GetCtlValue(theControl);
  2474.         aStr := Int2String(anInt);
  2475.         anInt := StringWidth(aStr) div 2;
  2476.         MoveTo(aRect.left + ((aRect.right - aRect.left) div 2 - anInt), aRect.top + 11);
  2477.         DrawString(aStr);
  2478.  
  2479.     end;    {ShowScrlValue}
  2480.  
  2481.  
  2482. {===========================================================================}
  2483.     procedure TrackRadScroll (theControl: ControlHandle; partCode: Integer);
  2484.         var
  2485.             min, max, amount, startValue: Integer;
  2486.             up: Boolean;
  2487.     begin
  2488.         up := partcode in [inUpButton, inPageUp];
  2489.         min := GetCtlMin(theControl);
  2490.         max := GetCtlMax(theControl);
  2491.         startValue := GetCtlValue(theControl);
  2492.         if ((up and (startValue > min)) or ((not up) and (startValue < max))) and (partCode <> 0) then
  2493.             begin
  2494.                 if up then
  2495.                     amount := -1
  2496.                 else
  2497.                     amount := 1;
  2498.                 if partCode in [inPageUp, inPagedown] then
  2499.                     amount := round(amount * 5)
  2500.                 else
  2501.                     amount := round(amount * 1);
  2502.                 SetCtlValue(theControl, amount + startValue);
  2503.             end;
  2504.         ShowScrlValue(theControl);
  2505.     end; {of TrackRadScroll}
  2506.  
  2507.  
  2508. {===========================================================================}
  2509.     procedure HandleToolContent (where: Point);
  2510.         var
  2511.             whichControl, OptType, anInt: integer;
  2512.             aControl: ControlHandle;
  2513.             dummy: Boolean;
  2514.     begin
  2515.         SetPort(toolWindPtr);
  2516.         GlobalToLocal(where);
  2517.         if PtInRect(where, drawBtnRect) and (not curSplat.autoRedraw) then
  2518.             begin
  2519.                 if TrackButtonRect(drawBtnRect) then
  2520.                     if (not curSplat.autoFill) then
  2521.                         DrawSplat(curSplat)
  2522.                     else
  2523.                         DrawFilledSplat(curSplat);
  2524.                 SplatStatistics(curSplat);
  2525.             end
  2526.         else if PtInRect(where, fillBtnRect) and (not curSplat.autoFill) then
  2527.             begin
  2528.                 if TrackButtonRect(fillBtnRect) then
  2529.                     begin
  2530.                         DrawFilledSplat(curSplat);
  2531.                         SplatStatistics(curSplat);
  2532.                     end
  2533.             end
  2534.         else if PtInRect(where, clearBtnRect) then
  2535.             if TrackButtonRect(clearBtnRect) then
  2536.                 begin
  2537.                     ClearAllSplats(curSplat)
  2538.                 end
  2539.             else
  2540.         else if PtInRect(where, autoDrawChkBox) then
  2541.             begin
  2542.                 HandleChkBox(autoDrawChkBox, curSplat.autoRedraw, 1);
  2543.                 InvalRect(drawBtnRect);
  2544.             end
  2545.         else if PtInRect(where, autoFillChkBox) then
  2546.             begin
  2547.                 HandleChkBox(autoFillChkBox, curSplat.autoFill, 2);
  2548.                 InvalRect(fillBtnRect);
  2549.             end
  2550.         else
  2551.             begin
  2552.                 whichControl := FindControl(where, toolWindPtr, aControl);
  2553.                 if whichControl <> 0 then
  2554.                     begin
  2555.  
  2556.                         case whichControl of
  2557.                             inUpButton, inDownButton, inPageUP, inPageDown: 
  2558.                                 begin
  2559.                                     OptType := TrackControl(aControl, where, @TrackRadScroll);
  2560.                                 end;
  2561.                             inThumb: 
  2562.                                 begin
  2563.                                     OptType := TrackControl(aControl, where, nil);
  2564.                                     ShowScrlValue(aControl);
  2565.                                 end;
  2566.                         end;{case whichControl of}
  2567.  
  2568.                         anInt := GetCtlValue(aControl);
  2569.                         if (aControl = innerRadScrl) and (anInt <> curSplat.innerRadius) then
  2570.                             begin
  2571.                                 curSplat.innerRadius := anInt;
  2572.                                 if curSplat.autoFill then
  2573.                                     DrawFilledSplat(curSplat)
  2574.                                 else if curSplat.autoRedraw then
  2575.                                     DrawSplat(curSplat);
  2576.                             end
  2577.                         else if (aControl = outerRadScrl) and (anInt <> curSplat.outerRadius) then
  2578.                             begin
  2579.                                 curSplat.outerRadius := anInt;
  2580.                                 if curSplat.autoFill then
  2581.                                     DrawFilledSplat(curSplat)
  2582.                                 else if curSplat.autoRedraw then
  2583.                                     DrawSplat(curSplat);
  2584.                             end
  2585.                         else if (aControl = divsScrl) and (anInt <> curSplat.divisions) then
  2586.                             begin
  2587.                                 if odd(anInt) then        {odd numbers in this value make the splat look dopey}
  2588.                                     anInt := anInt + 1;
  2589.                                 SetCtlValue(divsScrl, anInt);
  2590.                                 ShowScrlValue(divsScrl);
  2591.                                 curSplat.divisions := anInt;
  2592.  
  2593.                                 if curSplat.autoFill then
  2594.                                     DrawFilledSplat(curSplat)
  2595.                                 else if curSplat.autoRedraw then
  2596.                                     DrawSplat(curSplat);
  2597.                             end;
  2598.  
  2599.  
  2600.                     end;    {if whichControl <> 0}
  2601.             end;{ else}
  2602.  
  2603.     end;    {HandleToolContent}
  2604.  
  2605. {===========================================================================}
  2606.     procedure ShowHideTools;
  2607.         var
  2608.             aStr: Str255;
  2609.     begin
  2610.         if showToolWind then
  2611.             begin
  2612.                 ShowWindow(toolWindPtr);
  2613.                 SelectWindow(toolWindPtr);
  2614.                 SetPort(toolWindPtr);
  2615.             end
  2616.         else
  2617.             begin
  2618.                 HideWindow(toolWindPtr);
  2619.                 SelectWindow(drawWindPtr);
  2620.                 SetPort(drawWindPtr);
  2621.             end;
  2622.         if showToolWind then
  2623.             aStr := 'Hide Tools'
  2624.         else
  2625.             aStr := 'Show Tools';
  2626.         MoveHHi(Handle(myMenus[GoodiesMenuID]));
  2627.         HLock(Handle(myMenus[GoodiesMenuID]));
  2628.         SetItem(myMenus[GoodiesMenuID], MenuHidePalette, aStr);    {SetItem can move memory, as can CheckItem}
  2629.         HUnlock(Handle(myMenus[GoodiesMenuID]));                            {note that Enable & DisableItem do not more memory}
  2630.  
  2631.         refreshMenus := TRUE;
  2632.     end;    {ShowHideTools}
  2633.  
  2634.  
  2635. {===========================================================================}
  2636.     procedure RefreshToolWind;
  2637.         var
  2638.             aRect: Rect;
  2639.             anInt: integer;
  2640.     begin
  2641.  
  2642.         if (outerRadScrl <> nil) then
  2643.             SetCtlValue(outerRadScrl, curSplat.outerRadius);
  2644.         if (innerRadScrl <> nil) then
  2645.             SetCtlValue(innerRadScrl, curSplat.innerRadius);
  2646.         if (divsScrl <> nil) then
  2647.             SetCtlValue(divsScrl, curSplat.divisions);
  2648.  
  2649.         MoveTo(4, 13);
  2650.         foreColor(blueColor);
  2651.         LineTo(thePort^.portRect.right - 4, 13);
  2652.  
  2653.         MoveTo(4, 12);
  2654.         ForeColor(redColor);
  2655.         DrawString('SingleSplat Tools');
  2656.  
  2657.         DrawControls(toolWindPtr);
  2658.         ShowScrlValue(innerRadScrl);
  2659.         aRect := innerRadScrl^^.contrlRect;
  2660.         VerticalLabel(aRect, 'Radius 1');
  2661.  
  2662.         ShowScrlValue(outerRadScrl);
  2663.         aRect := outerRadScrl^^.contrlRect;
  2664.         VerticalLabel(aRect, 'Radius 2');
  2665.  
  2666.         ShowScrlValue(divsScrl);
  2667.         aRect := divsScrl^^.contrlRect;
  2668.         VerticalLabel(aRect, 'Divisions');
  2669.  
  2670.         anInt := StringWidth(drawBtnName) div 2;
  2671.         ClipRect(drawBtnRect);
  2672.         MoveTo(drawBtnRect.left + ((drawBtnRect.right - drawBtnRect.left) div 2 - anInt), drawBtnRect.top + 11);
  2673.         DrawString(drawBtnName);
  2674.         PenSize(1, 1);
  2675.         FrameRoundRect(drawBtnRect, 8, 8);
  2676.         if curSplat.autoRedraw then
  2677.             begin
  2678.                 PenPat(gray);
  2679.                 PenMode(patBic);
  2680.                 PaintRoundRect(drawBtnRect, 8, 8);
  2681.                 PenNormal;
  2682.             end;
  2683.  
  2684.         anInt := StringWidth(clearBtnName) div 2;
  2685.         ClipRect(clearBtnRect);
  2686.         MoveTo(clearBtnRect.left + ((clearBtnRect.right - clearBtnRect.left) div 2 - anInt), clearBtnRect.top + 11);
  2687.         DrawString(clearBtnName);
  2688.         PenSize(1, 1);
  2689.         FrameRoundRect(clearBtnRect, 8, 8);
  2690.  
  2691.         anInt := StringWidth(fillBtnName) div 2;
  2692.         ClipRect(fillBtnRect);
  2693.         MoveTo(fillBtnRect.left + ((fillBtnRect.right - fillBtnRect.left) div 2 - anInt), fillBtnRect.top + 11);
  2694.         DrawString(fillBtnName);
  2695.         PenSize(1, 1);
  2696.         FrameRoundRect(fillBtnRect, 8, 8);
  2697.  
  2698.         if curSplat.autoFill then
  2699.             begin
  2700.                 PenPat(gray);
  2701.                 PenMode(patBic);
  2702.                 PaintRoundRect(fillBtnRect, 8, 8);
  2703.                 PenNormal;
  2704.             end;
  2705.  
  2706.         PenNormal;
  2707.         ClipRect(thePort^.portRect);
  2708.  
  2709.         DrawChkBox(autoDrawChkBox, curSplat.autoRedraw, 1);
  2710.         DrawChkBox(autoFillChkBox, curSplat.autoFill, 2);
  2711.  
  2712.     end;    {RefreshToolWind}
  2713.  
  2714. {===========================================================================}
  2715.     procedure PutUpPaletteWIND;
  2716.         const
  2717.             scrollOffset = 12;
  2718.         var
  2719.             offSet: point;
  2720.             x: integer;
  2721.     begin
  2722.         if hasColorQD then
  2723.             begin
  2724.                 paletteWindPtr := GetNewCWindow(1002, @paletteWindowStorage, pointer(-1));
  2725.             end
  2726.         else
  2727.             paletteWindPtr := GetNewWindow(1002, @paletteWindowStorage, WindowPtr(-1));
  2728.  
  2729.         showPaletteWind := TRUE;
  2730.  
  2731.         SetPort(paletteWindPtr);
  2732. {offSet.h := DrawWindPtr^.portRect.left;}
  2733. {offSet.v := DrawWindPtr^.portRect.top;}
  2734. {LocalToGlobal(offSet);}
  2735.  
  2736. {SetPort(paletteWindPtr);}
  2737.  
  2738. {MoveWindow(paletteWindPtr, offSet.h - thePort^.portRect.right - 8, offSet.v - 8, TRUE);}
  2739.  
  2740. {clippingRect := paletteWindPtr^.portRect;}
  2741. {InsetRect(clippingRect, 1, 1);}
  2742. {ClipRect(clippingRect);}
  2743.  
  2744.         ShowWindow(paletteWindPtr);
  2745.     end;
  2746.  
  2747. {===========================================================================}
  2748.     procedure PutUpToolWIND;
  2749.         const
  2750.             scrollOffset = 12;
  2751.         var
  2752.             offSet: point;
  2753.             x: integer;
  2754.     begin
  2755.         if hasColorQD then
  2756.             begin
  2757.                 toolWindPtr := GetNewCWindow(1001, @toolWindowStorage, pointer(-1));
  2758.             end
  2759.         else
  2760.             toolWindPtr := GetNewWindow(1001, @toolWindowStorage, WindowPtr(-1));
  2761.  
  2762.         showToolWind := TRUE;
  2763.  
  2764.         SetPort(DrawWindPtr);
  2765.         offSet.h := DrawWindPtr^.portRect.left;
  2766.         offSet.v := DrawWindPtr^.portRect.top;
  2767.         LocalToGlobal(offSet);
  2768.  
  2769.         SetPort(toolWindPtr);
  2770.  
  2771.         MoveWindow(toolWindPtr, offSet.h - thePort^.portRect.right - 5, offSet.v, TRUE);
  2772.         SizeWindow(toolWindPtr, toolWindPtr^.portRect.right, toolWindPtr^.portRect.bottom + 40, TRUE);
  2773.  
  2774.         clippingRect := toolWindPtr^.portRect;
  2775.         InsetRect(clippingRect, 1, 1);
  2776.         ClipRect(clippingRect);
  2777.  
  2778.         TextFont(helvetica);
  2779.         TextSize(9);
  2780.  
  2781.  
  2782.         innerRadScrl := GetNewControl(400, toolWindPtr);
  2783.         SizeControl(innerRadScrl, 16, 200);
  2784.         MoveControl(innerRadScrl, scrollOffset, 20);
  2785.         SetCtlValue(innerRadScrl, curSplat.innerRadius);
  2786.  
  2787.         x := innerRadScrl^^.contrlRect.right;
  2788.         outerRadScrl := GetNewControl(400, toolWindPtr);
  2789.         SizeControl(outerRadScrl, 16, 200);
  2790.         MoveControl(outerRadScrl, x + scrollOffset, 20);
  2791.         SetCtlValue(outerRadScrl, curSplat.outerRadius);
  2792.  
  2793.         x := outerRadScrl^^.contrlRect.right;
  2794.         divsScrl := GetNewControl(401, toolWindPtr);
  2795.         SizeControl(divsScrl, 16, 200);
  2796.         MoveControl(divsScrl, x + scrollOffset, 20);
  2797.         SetCtlValue(divsScrl, curSplat.divisions);
  2798.  
  2799. {Let's put together our button's rectangle}
  2800.         drawBtnRect.left := 16;
  2801.         drawBtnRect.top := outerRadScrl^^.contrlRect.bottom + 18;
  2802.         drawBtnRect.right := drawBtnRect.left + StringWidth(drawBtnName) + 16;
  2803.         drawBtnRect.bottom := drawBtnRect.top + 16;
  2804.  
  2805.         autoDrawChkBox.left := drawBtnRect.left;
  2806.         autoDrawChkBox.top := drawBtnRect.bottom + 4;
  2807.         autoDrawChkBox.right := autoDrawChkBox.left + 8;
  2808.         autoDrawChkBox.bottom := autoDrawChkBox.top + 8;
  2809.  
  2810.         clearBtnRect := drawBtnRect;
  2811.         OffSetRect(clearBtnRect, 0, drawBtnRect.bottom - drawBtnRect.top + 16);
  2812.  
  2813.         autoFillChkBox.left := clearBtnRect.left;
  2814.         autoFillChkBox.top := clearBtnRect.bottom + 4;
  2815.         autoFillChkBox.right := autoFillChkBox.left + 8;
  2816.         autoFillChkBox.bottom := autoFillChkBox.top + 8;
  2817.  
  2818.         fillBtnRect := clearBtnRect;
  2819.         OffSetRect(fillBtnRect, 0, clearBtnRect.bottom - clearBtnRect.top + 16);
  2820.  
  2821.         ShowControl(innerRadScrl);    {allow controls to be seen in public}
  2822.         ShowControl(outerRadScrl);
  2823.         ShowControl(divsScrl);
  2824.  
  2825.         ShowWindow(toolWindPtr);
  2826.     end;
  2827.  
  2828. {=======================================================================================    }
  2829.     procedure Panic;
  2830.     begin
  2831.         ExitToShell;
  2832.     end;
  2833.  
  2834. {=======================================================================================    }
  2835.     procedure InitMac;
  2836.  
  2837.     begin
  2838.         MaxApplZone;
  2839.         InitGraf(@thePort);
  2840.         InitFonts;
  2841.         InitWindows;
  2842.         InitCursor;
  2843.         InitMenus;
  2844.         TEInit;
  2845.         InitDialogs(@Panic);
  2846.     end;
  2847. {=======================================================================================    }
  2848.     procedure SysCheck;
  2849. {: boolean;}
  2850.         label
  2851.             99;
  2852.         const
  2853.             versRequested = 1;
  2854.             envBadVers = -5501;
  2855.             envVersTooBig = -5502;
  2856.             WNE_TRAP_NUM = $60;
  2857.             UNIMPL_TRAP_NUM = $9F;
  2858.         var
  2859.             str1, str2: str255;
  2860.             freeSpace: size;
  2861.             myHeapSpace: longint;
  2862.             err: OSErr;
  2863.             theWorld: sysEnvRec;
  2864.             GotColorQD, GotCoProcessor, runability: boolean;
  2865.     begin
  2866. {SysCheck:= FALSE;}
  2867.         HasColorQD := FALSE;
  2868.         HasCoProcessor := FALSE;
  2869.         runability := FALSE;
  2870.  
  2871.         err := SysEnvirons(versRequested, theWorld);
  2872.  
  2873.         if err <> noErr then        {error on SysEnvirons call? If so,    }
  2874.             goto 99;
  2875.  
  2876. {-1 = Macintosh with 64K Rom, -2 = Macintosh XL. We can't run on those.}
  2877.         if (theWorld.machineType = -1) or (theWorld.machineType = -2) then
  2878.             goto 99;
  2879.  
  2880.         if theWorld.hasFPU then
  2881.             HasCoProcessor := TRUE;
  2882.  
  2883.         if theWorld.HasColorQD then
  2884.             HasColorQD := TRUE;
  2885.  
  2886.         runability := TRUE;
  2887.         gWNEImplemented := (NGetTrapAddress(WNE_TRAP_NUM, ToolTrap) <> NGetTrapAddress(UNIMPL_TRAP_NUM, ToolTrap));
  2888.  
  2889. 99:
  2890.         if not runability then
  2891.             DoMessage('**Sorry, this program', 'is unable to run', 'on this machine.', '')
  2892.         else
  2893.             ;
  2894. {SysCheck := TRUE;}
  2895.  
  2896.     end;{SysCheck}
  2897.  
  2898.  
  2899. {=======================================================================================    }
  2900.     function GetMBarHeight: INTEGER;
  2901.     inline
  2902.         $3EB8, $0BAA; {smMoveWord2Stack, smMBarHeight; (from ScriptManager.p interface}
  2903.  
  2904. {=======================================================================================    }
  2905.     procedure InitGlobs;
  2906.         var
  2907.             aLong: longint;
  2908.             anInt: integer;
  2909.     begin
  2910.  
  2911.         GetDateTime(aLong);                {make sure the numbers are randomized}
  2912.         randSeed := aLong;                {seed the system's random generator}
  2913.  
  2914.         appResFileRef := CurResFile;
  2915.  
  2916.         savedMenuHeight := GetMBarHeight;
  2917.         currMenuHeight := savedMenuHeight;
  2918.  
  2919.         gIBeam := GetCursor(iBeamCursor);
  2920.         gWatch := GetCursor(watchCursor);
  2921.         gCrossHairs := GetCursor(crossCursor);
  2922.  
  2923.         refreshMenus := TRUE;
  2924.         errorFlag := FALSE;
  2925.         quitting := FALSE;
  2926.         finished := FALSE;
  2927.  
  2928.         graphPICHdl := nil;
  2929.  
  2930.         cursorIs := k_arrowCurs;
  2931.  
  2932.     end;{InitGlobs}
  2933.  
  2934. {=======================================================================================    }
  2935.     procedure MakeMenus;
  2936.         var
  2937.             index: Integer;
  2938.     begin
  2939.  
  2940.         for index := AppleMenuID to GoodiesMenuID do
  2941.             begin
  2942.                 myMenus[index] := GetMenu(index);
  2943.                 InsertMenu(myMenus[index], 0);
  2944.             end;
  2945.         AddResMenu(myMenus[AppleMenuID], 'DRVR');
  2946.  
  2947.  
  2948.         DisableItem(myMenus[EditMenuID], MenuUndo);
  2949.         EnableItem(myMenus[EditMenuID], MenuCut);
  2950.         EnableItem(myMenus[EditMenuID], MenuCopy);
  2951.         DisableItem(myMenus[EditMenuID], MenuPaste);
  2952.         DisableItem(myMenus[EditMenuID], MenuClear);
  2953.  
  2954.         refreshMenus := TRUE;
  2955.     end;{MakeMenus}
  2956.  
  2957. {=======================================================================================    }
  2958.     function IsOptionKeyDown: boolean;
  2959.         var
  2960.             keys: keyMap;
  2961.     begin
  2962.         GetKeys(keys);
  2963.         if BitTst(@keys, 61) then
  2964.             IsOptionKeyDown := TRUE
  2965.         else
  2966.             IsOptionKeyDown := FALSE;
  2967.     end;{IsOptionKeyDown}
  2968.  
  2969.  
  2970. {=======================================================================================    }
  2971.     function IsCommandKeyDown: boolean;
  2972.         var
  2973.             keys: keyMap;
  2974.     begin
  2975.         GetKeys(keys);
  2976.         if BitTst(@keys, 48) then
  2977.             IsCommandKeyDown := TRUE
  2978.         else
  2979.             IsCommandKeyDown := FALSE;
  2980.     end;{IsCommandKeyDown}
  2981.  
  2982.  
  2983. {=======================================================================================    }
  2984.     procedure HandleDiskEvt;
  2985.         const
  2986.             top = 80;
  2987.             left = 120;
  2988.         var
  2989.             highWord: integer;
  2990.             aPt: point;
  2991.             result: integer;
  2992.     begin
  2993.         highWord := HiWord(MainEvent.message);
  2994.         if highWord <> 0 then    {the disk did not mount successfully}
  2995.             begin
  2996.                 SetPt(aPt, top, left);
  2997.                 DILoad;    {load the disk-initialization package}
  2998.                 result := DIBadMount(aPt, MainEvent.message);
  2999.                 DIUnLoad;    {Unload the disk-initialization package}
  3000.             end;
  3001.     end;{HandleDiskEvt}
  3002.  
  3003. {===========================================================================}
  3004.     procedure AnUpDate;
  3005.         var
  3006.             ActivePort, whichWindow: WindowPtr;
  3007.             x, width: integer;
  3008.     begin
  3009. {    save the current port in 'activeport', set the port to the}
  3010. {    window needing updating, redraw the contents of the window,}
  3011. {    restore the port to the original 'activeport'}
  3012.         GetPort(ActivePort);
  3013.         whichWindow := WindowPtr(MainEvent.message);
  3014.  
  3015.         SetCursor(gWatch^^);
  3016.  
  3017.         if whichWindow = toolWindPtr then        {drawing window}
  3018.             begin
  3019.                 BeginUpdate(toolWindPtr);
  3020.                 SelectWindow(toolWindPtr);
  3021.                 SetPort(toolWindPtr);
  3022.                 RefreshToolWind;
  3023.                 ENDUpdate(toolWindPtr);
  3024.             end;
  3025.         if whichWindow = DrawWindPtr then        {drawing window}
  3026.             begin
  3027.                 SetPort(DrawWindPtr);
  3028.                 InvalRect(thePort^.portRect);
  3029.                 BeginUpdate(DrawWindPtr);
  3030.                 if (curSplat.myBigArray = nil) or (curSplat.numPtsSoFar = 0) then
  3031.                     begin
  3032.                         if curSplat.autoRedraw then
  3033.                             begin
  3034.                                 DrawSplat(curSplat);
  3035.                                 SplatStatistics(curSplat);
  3036.                             end
  3037.                     end
  3038.                 else
  3039.                     RefreshSplats(curSplat);
  3040.                 FakeGrowIcon(DrawWindPtr, prefs.def_alwaysGrowBox);
  3041.                 ENDUpdate(DrawWindPtr);
  3042.                 if showToolWind then
  3043.                     begin
  3044.                         SelectWindow(toolWindPtr);
  3045.                         SetPort(toolWindPtr);
  3046.                     end;
  3047.             end;
  3048.  
  3049.         cursorIs := 0;
  3050.  
  3051.         SetPort(ActivePort);
  3052.     end;{}
  3053.  
  3054.  
  3055.  
  3056. {=======================================================================================    }
  3057.     procedure ClickInZoom (TheZoom: integer);
  3058.  
  3059.         var
  3060.             TheWindow: WindowPtr;
  3061.     begin
  3062.         TheWindow := FrontWindow;
  3063.         with TheWindow^ do
  3064.             if TrackBox(TheWindow, MainEvent.where, TheZoom) then
  3065.                 begin
  3066.                     EraseRect(TheWindow^.portRect);
  3067.                     ZoomWindow(TheWindow, TheZoom, true);
  3068. {•     WSize(gWindow);•}
  3069.                 end;{with…if}
  3070.     end;
  3071.  
  3072.  
  3073. {=======================================================================================    }
  3074.     procedure HandleContent (theWindow: WindowPtr; where: Point);
  3075.         var
  3076.             oldPort: GrafPtr;
  3077.             aBool: boolean;
  3078.             tempRect: rect;
  3079.     begin
  3080.         if thewindow = DrawWindPtr then
  3081.             begin
  3082.                 GetPort(oldPort);
  3083.                 SetPort(DrawWindPtr);
  3084.                 GlobalToLocal(where);
  3085.                 if (PtInRect(where, curSplat.statsBox)) then
  3086.                     DragStatsRect(curSplat)
  3087.                 else if (PtInRect(where, GrowIconRect)) then
  3088.                     begin
  3089.                         DoGrow(DrawWindPtr);
  3090.                         EraseRect(thePort^.portRect);
  3091.                         InvalRect(thePort^.portRect);
  3092.                         with thePort^.portRect do
  3093.                             begin
  3094.                                 curSplat.blnMiddle.h := (right - left) div 2;
  3095.                                 curSplat.blnMiddle.v := (bottom - top) div 2;
  3096.                             end;
  3097.                         tempRect := curSplat.statsBox;        {is it still visible?}
  3098.                         InsetRect(tempRect, 4, 4);
  3099.                         if not SectRect(tempRect, thePort^.portRect, tempRect) then    {well, it's not visible *enough*, so:}
  3100.                             OffSetRect(curSplat.statsBox, -curSplat.statsBox.left + 2, -curSplat.statsBox.top + 2);
  3101.                     end;
  3102.                 SetPort(oldPort);
  3103.             end    { if DrawWindPtr }
  3104.         else if thewindow = toolWindPtr then
  3105.             begin
  3106.                 HandleToolContent(where);
  3107.  
  3108.             end;{ if toolWindPtr}
  3109.     end;
  3110.  
  3111.  
  3112. {=======================================================================================    }
  3113.     procedure HandleGoAway (theWindow: WindowPtr; where: Point);
  3114.     begin
  3115.         if TrackGoAway(theWindow, where) then
  3116.             begin
  3117.                 if WindowPeek(theWindow)^.WindowKind = userKind then
  3118.                     if theWindow = toolWindPtr then
  3119.                         begin
  3120.                             showToolWind := False;
  3121.                             ShowHideTools;
  3122.                         end
  3123.                     else
  3124.                         CloseDeskAcc(WindowPeek(theWindow)^.WindowKind)
  3125.             end;
  3126.     end;
  3127.  
  3128.  
  3129. {=======================================================================================    }
  3130.     procedure ClickInDA (theWindow: WindowPtr);
  3131.     begin
  3132.         SystemClick(MainEvent, theWindow);
  3133. {•  CheckMenus;•}
  3134.     end;{ClickInDA}
  3135.  
  3136. {=======================================================================================    }
  3137.     procedure ClickAppleMenu (TheItem: integer);
  3138.         var
  3139.             SavedPort: GrafPtr;
  3140.             TheName: Str255;
  3141.             aDLOGPtr: dialogPtr;
  3142.             OldPort: GrafPtr;
  3143.             itemHit: integer;
  3144.     begin
  3145.         case theItem of
  3146.             MenuAbout: 
  3147.                 begin
  3148.                     InitCursor;
  3149.                     cursorIs := k_arrowCurs;
  3150.                     GetPort(OldPort);
  3151.                     aDLOGPtr := GetNewDialog(1000, nil, Pointer(-1));
  3152.                     CenterWindow(WindowPtr(aDLOGPtr));
  3153.                     SetPort(aDLOGPtr);
  3154.                     ShowWindow(aDLOGPtr);
  3155.                     repeat
  3156.                         ModalDialog(nil, itemHit);
  3157.     {Wait until an item is hit}
  3158.                     until itemhit <> 0;
  3159. {Flush the dialog out of memory}
  3160.                     DisposDialog(aDLOGPtr);
  3161.                     SetPort(oldPort);
  3162.                 end;
  3163.             menuHelp: 
  3164.                 begin
  3165.                     Help(256, 256);
  3166.                 end;
  3167.             otherwise
  3168.                 begin
  3169.                     GetPort(SavedPort);
  3170.                     GetItem(myMenus[AppleMenuID], TheItem, TheName);
  3171.                     itemHit := OpenDeskAcc(TheName);
  3172.                     SetPort(SavedPort);
  3173.                 end;    {otherwise}
  3174.         end;{case}
  3175.     end;{ClickAppleMenu}
  3176.  
  3177. {=======================================================================================    }
  3178.     procedure ClickFileMenu (TheItem: integer);
  3179.         var
  3180.             Dummy: boolean;
  3181.     begin
  3182.         case TheItem of
  3183.             MenuNew: 
  3184.                 NewSplat(curSplat);
  3185.             MenuQuit: 
  3186.                 begin
  3187.                     quitting := TRUE;
  3188.                 end;
  3189.             otherwise
  3190.                 ;
  3191.         end;    {case}
  3192.         if quitting = TRUE then
  3193.             finished := TRUE;
  3194.     end;{ClickFileMenu}
  3195.  
  3196. {=======================================================================================    }
  3197.     procedure DoCutCopy;
  3198.         var
  3199.             aLong, longSize: longint;
  3200.             resultStr: Str255;
  3201.     begin
  3202.         SplatPICT(curSplat, graphPICHdl);
  3203.         MoveHHi(Handle(graphPICHdl));    {get the PICT on the clipboard}
  3204.         HLock(Handle(graphPICHdl));
  3205.         aLong := ZeroScrap;
  3206.         if aLong = noErr then
  3207.             begin
  3208.                 longSize := GetHandlesize(Handle(graphPICHdl));
  3209.                 aLong := PutScrap(longSize, 'PICT', Ptr(graphPICHdl^));
  3210.                 if aLong = noErr then
  3211.                     aLong := UnloadScrap;
  3212.             end;
  3213.         if aLong <> noErr then
  3214.             SysBeep(1);
  3215.         HUnlock(Handle(graphPICHdl));
  3216.         KillPicture(graphPICHdl);
  3217.         graphPICHdl := nil;
  3218.     end;    {DoCutCopy}
  3219.  
  3220.  
  3221. {=======================================================================================    }
  3222.     procedure ClickEditMenu (TheItem: integer);
  3223.         var
  3224.             aLong: longint;
  3225.     begin
  3226.         if not SystemEdit(TheItem - 1) then    {okay, it's us, not a DA}
  3227.             case theItem of
  3228.                 MenuUndo: 
  3229.                     ;
  3230.                 MenuCopy, MenuCut: 
  3231.                     begin
  3232.                         if ZeroScrap = noerr then
  3233.                             begin
  3234.                                 aLong := ZeroScrap;
  3235.                                 if aLong = noErr then
  3236.                                     DoCutCopy
  3237.                                 else
  3238.                                     SysBeep(1);
  3239. {    MoveHHi(Handle(ourPictureHdl));}
  3240. {    HLock(Handle(ourPictureHdl));}
  3241. {    longSize := GetHandlesize(Handle(ourPictureHdl));}
  3242. {    aLong := PutScrap(longSize, 'PICT', Ptr(ourPictureHdl^));}
  3243. {    if aLong = noErr then}
  3244. {    aLong := UnloadScrap;}
  3245. {    HUnlock(Handle(ourPictureHdl));}
  3246.                             end
  3247.                         else
  3248.                             SysBeep(1);
  3249.                     end;
  3250.                 MenuPaste: 
  3251.                     ;
  3252.                 MenuClear: 
  3253.                     ;
  3254.                 MenuPrefs: 
  3255.                     PrefsDLOG;
  3256.                 otherwise
  3257.                     ;
  3258.             end;{case}
  3259. {•   if (TheItem = MenuCut) or (TheItem = MenuCopy) then•}
  3260. {•     ClipChanged := true;•}
  3261.     end;{ClickEditMenu}
  3262.  
  3263.  
  3264. {=======================================================================================    }
  3265.     procedure ClickGoodiesMenu (TheItem: integer);
  3266.         var
  3267.             oldPort: GrafPtr;
  3268.     begin
  3269.         case theItem of
  3270.             MenuMultiSplat: 
  3271.                 if MakeMacro(curSplat) then
  3272.                     begin
  3273.                         DoMultiSplat(curSplat);
  3274.                         SplatStatistics(curSplat);
  3275.                     end;
  3276.             MenuClearSplats: 
  3277.                 ClearAllSplats(curSplat);
  3278.             MenuHidePalette: 
  3279.                 begin
  3280.                     showToolWind := not showToolWind;
  3281.                     ShowHideTools;
  3282.                 end;
  3283.             otherwise
  3284.                 ;
  3285.         end;{case}
  3286.     end;{ClickGoodiesMenu}
  3287.  
  3288.  
  3289. {=======================================================================================    }
  3290.     procedure ClickInMenu;
  3291.         var
  3292.             Selection: longint;
  3293.     begin
  3294.         Selection := MenuSelect(MainEvent.where);
  3295.         case HiWord(Selection) of
  3296.             AppleMenuID: 
  3297.                 ClickAppleMenu(LoWord(Selection));
  3298.             FileMenuID: 
  3299.                 ClickFileMenu(LoWord(Selection));
  3300.             EditMenuID: 
  3301.                 ClickEditMenu(LoWord(Selection));
  3302.             GoodiesMenuID: 
  3303.                 ClickGoodiesMenu(LoWord(Selection));
  3304.             otherwise
  3305.                 ;
  3306.         end;
  3307.         HiliteMenu(0);        {turns off menu after action has taken place}
  3308.     end;{ClickInMenu}
  3309.  
  3310. {=======================================================================================    }
  3311.     procedure AClick;
  3312.  
  3313.         var
  3314.             theWindow: WindowPtr;
  3315.             where: Point;
  3316.             windowLoc: INTEGER;
  3317.  
  3318.     begin
  3319.  
  3320.         where := MainEvent.where;
  3321.         theWindow := WindowPtr(MainEvent.message);
  3322.         windowLoc := FindWindow(where, theWindow);
  3323.  
  3324.         case windowLoc of
  3325.             inDesk: 
  3326.                 ;
  3327.             InMenuBar: 
  3328.                 ClickInMenu;
  3329.             inSysWindow: 
  3330.                 ClickInDA(theWindow);
  3331.             InGrow: 
  3332.                 DoGrow(theWindow);
  3333.             InContent: 
  3334.                 HandleContent(theWindow, where);
  3335.             InGoAway: 
  3336.                 HandleGoAway(theWindow, where);
  3337.             InDrag: 
  3338.                 DoDrag(theWindow);
  3339.             inZoomIn: 
  3340.                 ClickInZoom(inZoomIn);
  3341.             inZoomOut: 
  3342.                 ClickInZoom(inZoomOut);
  3343.         end;
  3344.  
  3345.     end;
  3346.  
  3347. {•    AKey•}
  3348. {•    ----•}
  3349. {•    •}
  3350. {•    AKey first recovers the keycode from the gMainEvent.message•}
  3351. {•    field and converts it to a character.  If the command key is•}
  3352. {•    down, the keystroke is a keyboard equivalent for a menu item,•}
  3353. {•    and is sent to the CommandKey routine.  Otherwise, it is sent•}
  3354. {•    to the current edit record.•}
  3355.  
  3356.  
  3357. {=======================================================================================    }
  3358. {•    Commandkey•}
  3359. {•    ----------•}
  3360. {•    •}
  3361. {•    The Commandkey routine dispatches to the various menu routines•}
  3362. {•    according to the result of MenuKey.  MenuKey converts a key•}
  3363. {•    into the corresponding menu Selection, and highlights the•}
  3364. {•    appropriate menu.•}
  3365.     procedure CommandKey (TheKey: char);
  3366.         var
  3367.             Selection: longint;
  3368.     begin
  3369. {    if (DrawNow) and (TheKey = '.') then}
  3370. {    begin}
  3371. {    StopDrawing;}
  3372. {    if userPrefs^^.continueRandom then}
  3373. {    userPrefs^^.continueRandom := FALSE;}
  3374. {    end}
  3375. {    else}
  3376.         Selection := MenuKey(TheKey);
  3377.         case HiWord(Selection) of
  3378.             AppleMenuID: 
  3379.                 ClickAppleMenu(LoWord(Selection));
  3380.             FileMenuID: 
  3381.                 ClickFileMenu(LoWord(Selection));
  3382.             EditMenuID: 
  3383.                 ClickEditMenu(LoWord(Selection));
  3384.             GoodiesMenuID: 
  3385.                 ClickGoodiesMenu(LoWord(Selection));
  3386.             otherwise
  3387.                 ;
  3388.         end;
  3389.         HiliteMenu(0);
  3390.     end;{CommandKey}
  3391.  
  3392. {=======================================================================================    }
  3393.     procedure AKey;
  3394.         var
  3395.             TheCode: integer;
  3396.             TheChar: char;
  3397.     begin
  3398.         TheCode := BitAnd(MainEvent.message, charCodeMask);
  3399.         TheChar := chr(TheCode);
  3400.  
  3401.         if BitAnd(MainEvent.modifiers, cmdKey) <> 0 then
  3402.             CommandKey(TheChar)
  3403.     end;{AKey}
  3404.  
  3405. {=======================================================================================    }
  3406. {***************************************************************}
  3407. {   DoActivate - Activate the selected window.                          }
  3408. {                                                                        }
  3409. {    This guy checks to see if we need to activate or deactivate.    }
  3410. { It then calls the appropriate routine.  It is also responsible        }
  3411. { for the edit menu items.  If we are becoming active, the items    }
  3412. { are deactivated, otherwise, activate them for the application    }
  3413. { or desk accessory that is becoming active.                        }
  3414. {***************************************************************}
  3415.     procedure AnActivate;
  3416.         var
  3417.             itemIndex: Integer;
  3418.             Activate: Boolean;
  3419.             theWindow: WindowPtr;
  3420.             thePeek: WindowPeek;
  3421.     begin
  3422.         with MainEvent do
  3423.             begin
  3424.                 theWindow := WindowPtr(message);
  3425.                 Activate := BAnd(modifiers, activeFlag) <> 0;
  3426.                 if Activate then
  3427.                     begin
  3428.                         SelectWindow(theWindow);
  3429.                     end
  3430.                 else
  3431.                     begin
  3432.                         HiliteWindow(theWindow, FALSE);
  3433.                     end;
  3434.             end
  3435.     end; {AnActivate}
  3436.  
  3437.  
  3438. {=======================================================================================    }
  3439.     procedure MenuMaintenance;
  3440.         label
  3441.             99;
  3442.         var
  3443.             x: integer;
  3444.     begin
  3445.  
  3446. 99:
  3447.  
  3448.         DrawMenuBar;
  3449.         refreshMenus := FALSE;
  3450.     end;{MenuMaintenance}
  3451.  
  3452.  
  3453. {=======================================================================================    }
  3454.     procedure CursorMaintenance;
  3455.         var
  3456.             mouse: point;
  3457.     begin
  3458.  
  3459.         GetMouse(mouse);
  3460.  
  3461.         if PtInRgn(mouse, toolWindPtr^.visRgn) then
  3462.             begin
  3463.                 if cursorIs <> k_crossCurs then
  3464.                     begin
  3465.                         SetCursor(gCrossHairs^^);
  3466.                         cursorIs := k_crossCurs
  3467.                     end
  3468.             end
  3469.         else if cursorIs <> k_arrowCurs then
  3470.             begin
  3471.                 InitCursor;
  3472.                 cursorIs := k_arrowCurs
  3473.             end;
  3474.     end;{CursorMaintenance}
  3475.  
  3476.  
  3477. {=======================================================================================    }
  3478.     procedure HandleNull;
  3479.     begin
  3480.         if refreshMenus then
  3481.             MenuMaintenance;
  3482.  
  3483.         CursorMaintenance;
  3484.  
  3485.     end;{HandleNull}
  3486.  
  3487. {=======================================================================================    }
  3488.     procedure MainLoop;
  3489.         var
  3490.             Dummy: boolean;
  3491.             whichDialog: DialogPtr;
  3492.             whichItem: integer;
  3493.     begin
  3494.  
  3495.         repeat
  3496.  
  3497.             if gWNEImplemented then
  3498.                 Dummy := WaitNextEvent(everyEvent, MainEvent, 6, nil)
  3499.             else
  3500.                 begin
  3501.                     SystemTask;
  3502.                     Dummy := GetNextEvent(everyEvent, MainEvent);
  3503.                 end;
  3504.  
  3505. {    UnloadSeg(@GetPrefs);    set it free--we may need the room!}
  3506.             HandleNull;
  3507.             if Dummy then
  3508.                 case MainEvent.what of
  3509.                     mouseDown: 
  3510.                         AClick;
  3511.                     mouseUp: 
  3512.                         ;
  3513.                     keyDown: 
  3514.                         AKey;
  3515.                     keyUp: 
  3516.                         ;
  3517.                     autoKey: 
  3518.                         AKey;
  3519.                     updateEvt: 
  3520.                         AnUpDate;
  3521.                     DiskEvt: 
  3522.                         HandleDiskEvt;
  3523.                     activateEvt: 
  3524.                         AnActivate;
  3525.                     nullEvent: 
  3526.                         ;
  3527.                     otherwise
  3528.                         ;
  3529.                 end;    {case}
  3530.  
  3531.         until finished;
  3532.  
  3533.     end;
  3534.  
  3535. {=======================================================================================    }
  3536. {MAIN}
  3537.  
  3538. begin
  3539.     InitMac;
  3540.  
  3541.     InitGlobs;
  3542.     SetUpPrefs(prefs);
  3543. {if sysCheck then}
  3544.                         {find out about our environment}
  3545. {begin}
  3546.     sysCheck;
  3547.     MakeMenus;
  3548.     PutUpDrawingWIND;
  3549.     InitSplat(curSplat);
  3550.     PutUpToolWIND;
  3551. {PutUpPaletteWIND;}
  3552.     SelectWindow(toolWindPtr);
  3553.     SetPort(toolWindPtr);
  3554.     MainLoop;                    {let's jam}
  3555. {end;}
  3556.     RewritePrefs(prefs);
  3557. end.