home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Pascal / Applications / NewWatchP 2.1 / NewWatch.p next >
Encoding:
Text File  |  1995-04-21  |  11.9 KB  |  508 lines  |  [TEXT/PJMM]

  1. {This program was written by Eric Kilk in 1985, as a Desk Accessory. It was revived in 1995 by Ken Long,}
  2. {who turned it into an application. After he posted it to alt.sources.mac, I (Ingemar R), modified it to give it}
  3. {some functionality I found lacking. New features:}
  4. {}
  5. {• Updates automatically}
  6. {• Resizeable}
  7. {• More hour marks}
  8. {• Optional digits (3, 6, 9 and 12), roman or arabic}
  9. {• Black or white}
  10. {}
  11. {Do you feel like working some more on it? Colorize? Seconds? Circular WDEF? Put it in the menu bar?}
  12. {More options?}
  13. {}
  14. {- Fixes 21 of april:}
  15. {• Checked the "can background" flag so it updates when in the background}
  16. {• Modified the hands so they draw correctly}
  17.  
  18. program NewWatch;
  19.  
  20.     const
  21.         appleID = 1;
  22.         fileID = 2;
  23.         editID = 3;
  24.         optionsID = 4;
  25.  
  26.         helpItem = 1;
  27.         defaultItem = 2;
  28.         quitItem = 4;
  29.  
  30.         kTwoPi = 6.2831;
  31.  
  32.     var
  33.         appleMenu, fileMenu, editMenu, optionsMenu: MenuHandle;
  34.  
  35.         clockWindow, whatWindow: WindowPtr;
  36.         dragRect: Rect;
  37.  
  38.     type
  39.         settingsType = record
  40.                 black: Boolean;
  41.                 display: Integer;
  42.             end;
  43.     var
  44.         settings: SettingsType;
  45.  
  46.         gDone, gHasWNE: Boolean;
  47.         gPrevDateTime: DateTimeRec;
  48.  
  49.     type
  50.         WindowTemplate = record
  51.                 boundsRect: Rect;
  52.                 procID: Integer;
  53.                 visible: Boolean;
  54.                 filler1: Boolean;
  55.                 goAwayFlag: Boolean;
  56.                 filler2: Boolean;
  57.                 refCon: LongInt;
  58.                 title: Str255;
  59.             end;
  60.         WindowTPtr = ^WindowTemplate;
  61.         WindowTHnd = ^WindowTPtr;
  62.     var
  63.         wt: WindowTHnd;
  64.  
  65.  
  66.  
  67.     procedure EK;
  68.     begin
  69.         Move(-3, 0);
  70.         Line(0, 4);
  71.         Move(1, -4);
  72.         Line(1, 0);
  73.         Move(-1, 2);
  74.         Line(0, 0);
  75.         Move(0, 2);
  76.         Line(1, 0);
  77.         Move(2, -4);
  78.         Line(0, 4);
  79.         Move(1, -2);
  80.         Line(2, -2);
  81.         Move(-1, 3);
  82.         Line(1, 1);
  83.     end; {EK}
  84.  
  85.     procedure DrawHands (dateTime: DateTimeRec);
  86.         var
  87.             mx, my, hx, hy: Integer;            {• hand end-points */}
  88.             minUnit, min, hr: double;            {• time */}
  89.             cxSize, cySize: Integer;
  90.             hourRgn, minuteRgn: RgnHandle;
  91.     begin
  92.         SetPort(clockWindow);
  93.         cxSize := (clockWindow^.portRect.right - clockWindow^.portRect.left) div 2;
  94.         cySize := (clockWindow^.portRect.bottom - clockWindow^.portRect.top) div 2;
  95.         SetOrigin(-cxSize, -cySize);    {• make 0,0 in center */}
  96.  
  97.         minUnit := dateTime.minute / 60.0;
  98.         min := minUnit * kTwoPi;    {• 2*pi */}
  99.         hr := (dateTime.hour + minUnit) / 12.0 * kTwoPi;
  100.         mx := Trunc(0.75 * cxSize * sin(min));
  101.         my := Trunc(-0.75 * cySize * cos(min));
  102.         hx := Trunc(0.5 * cxSize * sin(hr));
  103.         hy := Trunc(-0.5 * cySize * cos(hr));
  104.  
  105.         hourRgn := NewRgn;
  106.         minuteRgn := NewRgn;
  107.  
  108.         OpenRgn;
  109.         MoveTo(0, 0);        {• create the minute hand region}
  110.         LineTo(mx, my);
  111.         if abs(mx) > abs(my) then
  112.             Line(0, 1)
  113.         else
  114.             Line(1, 0);
  115.         Line(-mx, -my);
  116.         LineTo(0, 0);
  117.         CloseRgn(minuteRgn);
  118.         OpenRgn;
  119.         MoveTo(0, 0);        {• create the hour hand region}
  120.         LineTo(hx, hy);
  121.         if abs(hx) > abs(hy) then
  122.             Line(0, 1)
  123.         else
  124.             Line(1, 0);
  125.         Line(-hx, -hy);
  126.         LineTo(0, 0);
  127.         CloseRgn(hourRgn);
  128.  
  129.         UnionRgn(hourRgn, minuteRgn, minuteRgn);
  130.  
  131.         PaintRgn(minuteRgn);        {• draw the hands.}
  132.         DisposeRgn(minuteRgn);
  133.         DisposeRgn(hourRgn);
  134.  
  135.         MoveTo(0, 0);        {• erase the center dot.}
  136.         PenPat(white);
  137.         LineTo(0, 0);
  138.         PenPat(black);
  139.     end; {DrawHands}
  140.  
  141.     procedure ShowClock;
  142.             {• draw the entire clock face */}
  143.         var
  144.             dateTime: DateTimeRec;    {• date gets read into here */}
  145.  
  146.             cxSize, cySize: Integer;
  147.  
  148.             fInfo: FontInfo;
  149.             theTextSize: Integer;
  150.     begin
  151.         SetPort(clockWindow);
  152.         PenNormal;
  153.         if settings.black then
  154.             PaintRect(clockWindow^.portRect)
  155.         else
  156.             EraseRect(clockWindow^.portRect);
  157.  
  158.         cxSize := (clockWindow^.portRect.right - clockWindow^.portRect.left) div 2;
  159.         cySize := (clockWindow^.portRect.bottom - clockWindow^.portRect.top) div 2;
  160.  
  161.         GetTime(dateTime);
  162.         if (dateTime.hour > 11) then
  163.             dateTime.hour := dateTime.hour - 12;
  164.         SetOrigin(-cxSize, -cySize);    {• make 0,0 in center */}
  165.         PenMode(srcXor);
  166.  
  167. {The text size is determined from the smallest side!}
  168.         if cxSize > cySize then
  169.             theTextSize := cySize div 5
  170.         else
  171.             theTextSize := cxSize div 5;
  172.  
  173.         TextSize(theTextSize);
  174.         GetFontInfo(fInfo);
  175.  
  176.         if (settings.display = 0) or (theTextSize < 6) then
  177.             begin
  178.                 MoveTo(0, cySize - 2);
  179.                 Line(0, 0);    {• draw 4 ticks.}
  180.                 MoveTo(cxSize - 2, 0);
  181.                 Line(0, 0);
  182.                 MoveTo(0, -cySize + 1);
  183.                 Line(0, 0);
  184.                 MoveTo(-cxSize + 1, 0);
  185.                 Line(0, 0);
  186.             end
  187.         else if settings.display = 1 then
  188.             begin
  189.                 PenMode(patXor);
  190.                 if settings.black then
  191.                     ForeColor(whiteColor);
  192.                 MoveTo(0 - StringWidth('6') div 2, cySize - 2);
  193.                 DrawString('6');
  194.                 MoveTo(cxSize - 0 - StringWidth('3'), 0 + fInfo.ascent div 2);
  195.                 DrawString('3');
  196.                 MoveTo(0 - StringWidth('12') div 2, -cySize + 0 + fInfo.ascent);
  197.                 DrawString('12');
  198.                 MoveTo(-cxSize + 1, 0 + fInfo.ascent div 2);
  199.                 DrawString('9');
  200.                 ForeColor(blackColor);
  201.             end
  202.         else
  203.             begin
  204.                 if settings.black then
  205.                     ForeColor(whiteColor);
  206.                 PenMode(patXor);
  207.                 MoveTo(0 - StringWidth('VI') div 2, cySize - 2);
  208.                 DrawString('VI');
  209.                 MoveTo(cxSize - 0 - StringWidth('III'), 0 + fInfo.ascent div 2);
  210.                 DrawString('III');
  211.                 MoveTo(0 - StringWidth('XII') div 2, -cySize + 0 + fInfo.ascent);
  212.                 DrawString('XII');
  213.                 MoveTo(-cxSize + 1, 0 + fInfo.ascent div 2);
  214.                 DrawString('IX');
  215.                 ForeColor(blackColor);
  216.             end;
  217.  
  218. {Draw the rest of the marks}
  219.         MoveTo(Trunc((cxSize - 2) * 0.866), Trunc((cySize - 2) * 0.5));
  220.         Line(0, 0);
  221.         MoveTo(Trunc((cxSize - 2) * 0.5), Trunc((cySize - 2) * 0.866));
  222.         Line(0, 0);
  223.         MoveTo(-Trunc((cxSize - 2) * 0.866), Trunc((cySize - 2) * 0.5));
  224.         Line(0, 0);
  225.         MoveTo(-Trunc((cxSize - 2) * 0.5), Trunc((cySize - 2) * 0.866));
  226.         Line(0, 0);
  227.         MoveTo(Trunc((cxSize - 2) * 0.866), -Trunc((cySize - 2) * 0.5));
  228.         Line(0, 0);
  229.         MoveTo(Trunc((cxSize - 2) * 0.5), -Trunc((cySize - 2) * 0.866));
  230.         Line(0, 0);
  231.         MoveTo(-Trunc((cxSize - 2) * 0.866), -Trunc((cySize - 2) * 0.5));
  232.         Line(0, 0);
  233.         MoveTo(-Trunc((cxSize - 2) * 0.5), -Trunc((cySize - 2) * 0.866));
  234.         Line(0, 0);
  235.  
  236. {Draw EK}
  237.         MoveTo(0, cySize div 2); {5}
  238.         EK;
  239.  
  240.         DrawHands(dateTime);
  241.  
  242.         gPrevDateTime := dateTime;
  243.     end; {ShowClock}
  244.  
  245.     procedure BackgroundTask;
  246.         var
  247.             dateTime: DateTimeRec;    {• date gets read into here */}
  248.     begin
  249.         GetTime(dateTime);
  250.         if dateTime.minute <> gPrevDateTime.minute then
  251.             begin
  252.                 SetPort(clockWindow);
  253.                 PenMode(srcXor);
  254.                 DrawHands(gPrevDateTime);
  255.                 PenMode(srcXor);
  256.                 DrawHands(dateTime);
  257.                 gPrevDateTime := dateTime;
  258.             end;
  259.     end; {BackgroundTask}
  260.  
  261.     procedure SetUpWindow;
  262.         var
  263.             wr: Rect;
  264.     begin
  265.         dragRect := screenBits.bounds;
  266.  
  267.         clockWindow := GetNewWindow(128, nil, WindowPtr(-1));
  268.         SetPort(clockWindow);
  269.     end; {SetUpWindow}
  270.  
  271.     procedure SetUpMenus;
  272.     begin
  273.         appleMenu := NewMenu(appleID, stringof(char($14)));
  274.         InsertMenu(appleMenu, 0);
  275.         fileMenu := NewMenu(fileID, 'File');
  276.         InsertMenu(fileMenu, 0);
  277.         editMenu := NewMenu(editID, 'Edit');
  278.         InsertMenu(editMenu, 0);
  279.         optionsMenu := NewMenu(optionsID, 'Options');
  280.         InsertMenu(optionsMenu, 0);
  281.         AppendMenu(appleMenu, 'About NewWatch…');
  282.         AddResMenu(appleMenu, 'DRVR');
  283.         AppendMenu(fileMenu, 'Help/H;Standard size/N;(-;Quit/Q');
  284.         AppendMenu(editMenu, 'Undo/Z;(-;Cut/X;Copy/C;Paste/V;Clear');
  285.         AppendMenu(optionsMenu, 'White;Black;(-;Dots;Arabic;Roman');
  286.         DrawMenuBar;
  287.     end; {SetUpMenus}
  288.  
  289.     procedure AdjustMenus;
  290.         var
  291.             wp: WindowPeek;
  292.             kind: Integer;
  293.             DA: Boolean;
  294.         procedure Enable (menu: MenuHandle; item: Integer; ok: Boolean);
  295.         begin
  296.             if ok then
  297.                 EnableItem(menu, item)
  298.             else
  299.                 DisableItem(menu, item);
  300.         end; {Enable}
  301.     begin
  302.         wp := WindowPeek(FrontWindow);
  303.         if wp = nil then
  304.             kind := 0
  305.         else
  306.             kind := wp^.windowKind;
  307.         DA := kind < 0;
  308.  
  309.         Enable(editMenu, 1, DA);
  310.         Enable(editMenu, 3, DA);
  311.         Enable(editMenu, 4, DA);
  312.         Enable(editMenu, 5, DA);
  313.         Enable(editMenu, 6, DA);
  314.  
  315.         CheckItem(optionsMenu, 1, not settings.black);
  316.         CheckItem(optionsMenu, 2, settings.black);
  317.  
  318.         CheckItem(optionsMenu, 4, settings.display = 0);
  319.         CheckItem(optionsMenu, 5, settings.display = 1);
  320.         CheckItem(optionsMenu, 6, settings.display = 2);
  321.     end; {AdjustMenus}
  322.  
  323.     procedure HandleMenu (mSelect: LongInt);
  324.         var
  325.             menuID: Integer;
  326.             menuItem: Integer;
  327.             name: Str255;
  328.             savePort: GrafPtr;
  329.             theFrontWindow: WindowPeek;
  330.     begin
  331.         menuID := HiWord(mSelect);
  332.         menuItem := LoWord(mSelect);
  333.  
  334.         case menuID of
  335.             appleID: 
  336.                 if menuItem = 1 then
  337.                     begin
  338.                         if Alert(128, nil) = 1 then {About…}
  339.                             ;
  340.                     end
  341.                 else
  342.                     begin
  343.                         GetPort(savePort);
  344.                         GetItem(appleMenu, menuItem, name);
  345.                         if OpenDeskAcc(name) = 0 then
  346.                             ;
  347.                         SetPort(savePort);
  348.                     end;
  349.             fileID: 
  350.                 case menuItem of
  351.                     helpItem: 
  352.                         begin
  353.                             if Alert(129, nil) = 1 then {Show help text}
  354.                                 ;
  355.                         end;
  356.                     defaultItem: 
  357.                         begin
  358.                             SizeWindow(clockWindow, 32, 32, false);
  359.                             SetPort(clockWindow);
  360.                             InvalRect(clockWindow^.portRect);
  361. {Move it to some safe place too}
  362.                             MoveWindow(clockWindow, 40, 40, true);
  363.                         end;
  364.                     quitItem: 
  365.                         gDone := true;
  366.                 end; {case}
  367.             editID: 
  368.                 if not SystemEdit(menuItem - 1) then
  369.                     SysBeep(5);
  370.             optionsID: 
  371.                 begin
  372.                     case menuItem of
  373.                         1: 
  374.                             settings.black := false;
  375.                         2: 
  376.                             settings.black := true;
  377.                         otherwise
  378.                             settings.display := menuItem - 4;
  379.                     end; {case}
  380.                     InvalRect(clockWindow^.portRect);
  381.                     AdjustMenus;
  382.                 end;
  383.         end;
  384.     end; {HandleMenu}
  385.  
  386.     procedure InitMacintosh;
  387.         const
  388.             _WaitNextEvent = $A860;
  389.             _Unimplemented = $A89F;
  390.     begin
  391. {$IFC UNDEFINED THINK_PASCAL}
  392.         MaxApplZone;
  393.  
  394.         InitGraf(@qd.thePort);
  395.         InitFonts;
  396.         FlushEvents(everyEvent, 0);
  397.         InitWindows;
  398.         InitMenus;
  399.         TEInit;
  400.         InitDialogs(nil);
  401. {$ENDC}
  402.         InitCursor;
  403.  
  404.         gHasWNE := NGetTrapAddress(_WaitNextEvent, ToolTrap) <> NGetTrapAddress(_Unimplemented, ToolTrap);
  405.     end;
  406.  
  407.     procedure HandleMouseDown (var theEvent: EventRecord);
  408.         var
  409.             theWindow: WindowPtr;
  410.             windowCode: Integer;
  411.             growResult: Longint;
  412.     begin
  413.         windowCode := FindWindow(theEvent.where, theWindow);
  414.  
  415.         case windowCode of
  416.             inSysWindow: 
  417.                 SystemClick(theEvent, theWindow);
  418.             inMenuBar: 
  419.                 begin
  420.                     AdjustMenus;
  421.                     HandleMenu(MenuSelect(theEvent.where));
  422.                 end;
  423.             inDrag:  {We should not have any, but just in case someone hacks it…}
  424.                 if theWindow = clockWindow then
  425.                     DragWindow(clockWindow, theEvent.where, dragRect);
  426.             inContent: 
  427.                 if theWindow = clockWindow then
  428.                     begin
  429.                         if theWindow <> FrontWindow then
  430.                             SelectWindow(clockWindow)
  431.                         else if BAnd(theEvent.modifiers, optionKey) <> 0 then {Option-klick = resize!}
  432.                             begin
  433.                                 growResult := GrowWindow(clockWindow, theEvent.where, GetGrayRgn^^.rgnBBox);
  434.                                 if growResult <> 0 then
  435.                                     begin
  436.                                         SizeWindow(clockWindow, LoWord(growResult), HiWord(growResult), false);
  437.                                         SetPort(clockWindow);
  438.                                         InvalRect(clockWindow^.portRect);
  439.                                     end;
  440.                             end
  441.                         else
  442.                             DragWindow(clockWindow, theEvent.where, dragRect);
  443.                     end;
  444. { inGoAway: }
  445. { if (theWindow = clockWindow) then if TrackGoAway(clockWindow, theEvent.where) then}
  446. { gDone := true;}
  447.         end;
  448.     end;
  449.  
  450.     procedure HandleEvent;
  451.         var
  452.             ok: Boolean;
  453.             theEvent: EventRecord;
  454.     begin
  455.         HiliteMenu(0);
  456.  
  457.         if gHasWNE then
  458.             ok := WaitNextEvent(everyEvent, theEvent, 120, nil) {sleeptime of 2 seconds - we don't need more!}
  459.         else
  460.             begin
  461.                 SystemTask;        {• Handle desk accessories.}
  462.                 ok := GetNextEvent(everyEvent, theEvent);
  463.             end;
  464.  
  465.         if ok then
  466.             case theEvent.what of
  467.                 mouseDown: 
  468.                     HandleMouseDown(theEvent);
  469.                 keyDown, autoKey: 
  470.                     if BAnd(theEvent.modifiers, cmdKey) <> 0 then
  471.                         begin
  472.                             AdjustMenus;
  473.                             HandleMenu(MenuKey(char(BAnd(theEvent.message, charCodeMask))));
  474.                         end;
  475.                 updateEvt: 
  476.                     begin
  477.                         BeginUpdate(clockWindow);
  478.                         ShowClock;
  479.                         EndUpdate(clockWindow);
  480.                     end;
  481.                 activateEvt: 
  482.                     InvalRect(clockWindow^.portRect);
  483.             end
  484.         else
  485.             BackgroundTask;
  486.     end; {HandleEvent}
  487.  
  488. { main program }
  489. begin
  490.     InitMacintosh;
  491.     SetUpMenus;
  492.     SetUpWindow;
  493.     settings := SettingsType(GetWRefCon(clockWindow));
  494.     ShowClock;
  495.  
  496.     while not gDone do
  497.         HandleEvent;
  498.  
  499.     SetPort(clockWindow);
  500.  
  501.     wt := WindowTHnd(GetResource('WIND', 128));
  502.     wt^^.boundsRect := clockWindow^.portRect;
  503.     LocalToGlobal(wt^^.boundsRect.topLeft);
  504.     LocalToGlobal(wt^^.boundsRect.botRight);
  505.     wt^^.refCon := Longint(settings);
  506.     ChangedResource(Handle(wt));
  507.  
  508. end.