home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / Dave Mark / Mac C Primer 1 (SC++7) / 5.1 - WorldClock / WorldClock.c next >
Encoding:
C/C++ Source or Header  |  1994-05-13  |  10.8 KB  |  535 lines  |  [TEXT/KAHL]

  1. /********************************************************/
  2. /*                                                        */
  3. /*  WorldClock Code from Chapter Five of                */
  4. /*                                                        */
  5. /*    *** The Macintosh Programming Primer, 2nd Ed. ***    */
  6. /*                                                      */
  7. /*    Copyright 1992, Dave Mark and Cartwright Reed       */
  8. /*                                                        */
  9. /*  This program demonstrates specific Mac programming    */
  10. /*    techniques.                                            */
  11. /*                                                        */    
  12. /*    See the WindowMaker project for a more complete        */
  13. /*    example of a standalone Mac application.              */
  14. /*                                                        */
  15. /********************************************************/
  16.  
  17. #include <Packages.h>
  18. #include <GestaltEqu.h>
  19.  
  20. #define kBaseResID            128
  21. #define kMoveToFront        (WindowPtr)-1L
  22. #define kUseDefaultProc        (void *)-1L
  23. #define kSleep                20L
  24. #define kLeaveWhereItIs        false
  25.  
  26. #define kIncludeSeconds        true
  27. #define kTicksPerSecond        60
  28. #define kSecondsPerHour        3600L
  29.  
  30. #define kAddCheckMark        true
  31. #define kRemoveCheckMark    false
  32.  
  33. #define kPopupControlID        kBaseResID
  34.  
  35. #define kNotANormalMenu        -1
  36.  
  37. #define mApple                kBaseResID
  38. #define iAbout                1
  39.  
  40. #define mFile                kBaseResID+1
  41. #define iQuit                1
  42.  
  43. #define mFont                100
  44.  
  45. #define mStyle                101
  46. #define iPlain                1
  47. #define iBold                2
  48. #define iItalic                3
  49. #define iUnderline            4
  50. #define iOutline            5
  51. #define iShadow                6
  52.  
  53. #define kPlainStyle            0
  54.  
  55. #define kExtraPopupPixels    25
  56.  
  57. #define kClockLeft            12
  58. #define kClockTop            25
  59. #define kClockSize            24
  60.  
  61. #define kCurrentTimeZone    1
  62. #define kNewYorkTimeZone    2
  63. #define kMoscowTimeZone        3
  64. #define kUlanBatorTimeZone    4
  65.  
  66. #define TopLeft( r )        (*(Point *) &(r).top)
  67. #define BottomRight( r )    (*(Point *) &(r).bottom)
  68.  
  69. #define IsHighBitSet( longNum )        ( (longNum >> 23) & 1 )
  70. #define SetHighByte( longNum )        ( longNum |= 0xFF000000 )
  71. #define ClearHighByte( longNum )    ( longNum &= 0x00FFFFFF )
  72.  
  73.  
  74. /*************/
  75. /*  Globals  */
  76. /*************/
  77.  
  78. Boolean         gDone, gHasPopupControl;
  79. short        gLastFont = 1, gCurrentZoneID = kCurrentTimeZone;
  80. Style        gCurrentStyle = kPlainStyle;
  81. Rect        gClockRect;
  82.  
  83.  
  84. /***************/
  85. /*  Functions  */
  86. /***************/
  87.  
  88. void    ToolBoxInit( void );
  89. void    WindowInit( void );
  90. void    MenuBarInit( void );
  91. void    EventLoop( void );
  92. void    DoEvent( EventRecord *eventPtr );
  93. void     HandleNull( EventRecord *eventPtr );
  94. void    HandleMouseDown( EventRecord *eventPtr );
  95. void    SetUpZoomPosition( WindowPtr window, short zoomInOrOut );
  96. void    HandleMenuChoice( long menuChoice );
  97. void    HandleAppleChoice( short item );
  98. void    HandleFileChoice( short item );
  99. void    HandleFontChoice( short item );
  100. void    HandleStyleChoice( short item );
  101. void    DoUpdate( EventRecord *eventPtr );
  102. long    GetZoneOffset( void );
  103.  
  104.  
  105. /**************************** main **********************/
  106.  
  107. void    main( void )
  108. {
  109.     ToolBoxInit();
  110.     WindowInit();
  111.     MenuBarInit();
  112.     
  113.     EventLoop();
  114. }
  115.  
  116.  
  117. /****************** ToolBoxInit *********************/
  118.  
  119. void    ToolBoxInit( void )
  120. {
  121.     InitGraf( &qd.thePort );
  122.     InitFonts();
  123.     InitWindows();
  124.     InitMenus();
  125.     TEInit();
  126.     InitDialogs( 0L );
  127.     InitCursor();
  128. }
  129.  
  130.  
  131. /****************** WindowInit ***********************/
  132.  
  133. void     WindowInit( void )
  134. {
  135.     WindowPtr         window;
  136.  
  137.     window = GetNewWindow( kBaseResID, nil, kMoveToFront );
  138.     
  139.     if ( window == nil )
  140.     {
  141.         SysBeep( 10 );    /*  Couldn't load the WIND resource!!! */
  142.         ExitToShell();
  143.     }
  144.     
  145.     SetPort( window );
  146.     TextSize( kClockSize );
  147.     
  148.     gClockRect = window->portRect;
  149.     
  150.     ShowWindow( window );
  151. }
  152.  
  153.  
  154. /****************** MenuBarInit ***********************/
  155.  
  156. void    MenuBarInit( void )
  157. {
  158.     Handle            menuBar;
  159.     MenuHandle        menu;
  160.     ControlHandle    control;
  161.     OSErr            myErr;
  162.     long            feature;
  163.     
  164.     menuBar = GetNewMBar( kBaseResID );
  165.     SetMenuBar( menuBar );
  166.  
  167.     menu = GetMHandle( mApple );
  168.     AddResMenu( menu, 'DRVR' );
  169.     
  170.     menu = GetMenu( mFont );
  171.     InsertMenu( menu, kNotANormalMenu );
  172.     AddResMenu( menu, 'FONT' );
  173.     
  174.     menu = GetMenu( mStyle );
  175.     InsertMenu( menu, kNotANormalMenu );
  176.     CheckItem( menu, iPlain, true );
  177.     
  178.     DrawMenuBar();
  179.  
  180.     HandleFontChoice( gLastFont );
  181.     
  182.     myErr = Gestalt( gestaltPopupAttr, &feature );
  183.     gHasPopupControl = ((myErr == noErr) && (feature & (1 << gestaltPopupPresent)));
  184.     
  185.     if ( gHasPopupControl )
  186.         control = GetNewControl( kPopupControlID, FrontWindow() );
  187. }
  188.  
  189.  
  190. /****************** EventLoop ***********************/
  191.  
  192. void    EventLoop( void )
  193. {        
  194.     EventRecord        event;
  195.     
  196.     gDone = false;
  197.     
  198.     while ( gDone == false )
  199.     {
  200.         if ( WaitNextEvent( everyEvent, &event, kSleep, nil ) )
  201.             DoEvent( &event );
  202.         else
  203.             HandleNull( &event );
  204.     }
  205. }
  206.  
  207.  
  208. /****************** DoEvent ***********************/
  209.  
  210. void    DoEvent( EventRecord *eventPtr )
  211. {
  212.     char    theChar;
  213.     
  214.     switch ( eventPtr->what )
  215.     {
  216.         case mouseDown: 
  217.             HandleMouseDown( eventPtr );
  218.             break;
  219.         case keyDown:
  220.         case autoKey:
  221.             theChar = eventPtr->message & charCodeMask;
  222.             if ( (eventPtr->modifiers & cmdKey) != 0 ) 
  223.                 HandleMenuChoice( MenuKey( theChar ) );
  224.             break;
  225.         case updateEvt:
  226.             DoUpdate( eventPtr );
  227.             break;
  228.     }
  229. }
  230.  
  231.  
  232. /****************** HandleNull ***********************/
  233.  
  234. void HandleNull( EventRecord *eventPtr )
  235. {
  236.     static long    lastTime = 0;
  237.  
  238.     if ( (eventPtr->when / kTicksPerSecond) > lastTime )
  239.     {
  240.         InvalRect( &gClockRect );
  241.         lastTime = eventPtr->when / kTicksPerSecond;
  242.     }
  243. }
  244.  
  245.  
  246. /****************** HandleMouseDown ***********************/
  247.  
  248. void    HandleMouseDown( EventRecord *eventPtr )
  249. {
  250.     WindowPtr        whichWindow;
  251.     short            thePart;
  252.     long            menuChoice;
  253.     ControlHandle    control;
  254.     short            ignored;
  255.     
  256.     thePart = FindWindow( eventPtr->where, &whichWindow );
  257.     switch ( thePart )
  258.     {
  259.         case inMenuBar:
  260.             menuChoice = MenuSelect( eventPtr->where );
  261.             HandleMenuChoice( menuChoice );
  262.             break;
  263.         case inSysWindow: 
  264.             SystemClick( eventPtr, whichWindow );
  265.             break;
  266.         case inContent:
  267.             SetPort( whichWindow );
  268.             GlobalToLocal( &eventPtr->where );
  269.             
  270.             if ( FindControl( eventPtr->where, whichWindow, &control ) )
  271.             {
  272.                 ignored = TrackControl( control, eventPtr->where, kUseDefaultProc );
  273.                 gCurrentZoneID = GetCtlValue( control );
  274.             }
  275.             break;
  276.         case inDrag: 
  277.             DragWindow( whichWindow, eventPtr->where, &qd.screenBits.bounds );
  278.             break;
  279.         case inZoomIn:
  280.         case inZoomOut:
  281.             if ( TrackBox( whichWindow, eventPtr->where, thePart ) )
  282.             {
  283.                 SetUpZoomPosition( whichWindow, thePart );
  284.                 ZoomWindow( whichWindow, thePart, kLeaveWhereItIs );
  285.             }
  286.             break;
  287.     }
  288. }
  289.  
  290.  
  291. /****************** SetUpZoomPosition ****************/
  292.  
  293. void    SetUpZoomPosition( WindowPtr window, short zoomInOrOut )
  294. {
  295.     WindowPeek        wPeek;
  296.     WStateData        *wStatePtr;
  297.     Rect            windowRect;
  298.     Boolean            isBig;
  299.     short            deltaPixels;
  300.     
  301.     wPeek = (WindowPeek) window;
  302.     wStatePtr = (WStateData *) *(wPeek->dataHandle);
  303.     
  304.     windowRect = window->portRect;
  305.     LocalToGlobal( &TopLeft( windowRect ) );
  306.     LocalToGlobal( &BottomRight( windowRect ) );
  307.     
  308.     wStatePtr->stdState = windowRect;
  309.     wStatePtr->userState = wStatePtr->stdState;
  310.     
  311.     if ( gHasPopupControl )
  312.     {
  313.         isBig = (windowRect.bottom - windowRect.top) >
  314.                 (gClockRect.bottom - gClockRect.top);
  315.         
  316.         if ( isBig )
  317.             deltaPixels = -kExtraPopupPixels;
  318.         else
  319.             deltaPixels = kExtraPopupPixels;
  320.             
  321.         if ( zoomInOrOut == inZoomIn )
  322.             wStatePtr->userState.bottom += deltaPixels;
  323.         else
  324.             wStatePtr->stdState.bottom += deltaPixels;
  325.     }
  326.     else
  327.         SysBeep( 20 );
  328. }
  329.  
  330.  
  331. /****************** HandleMenuChoice ***********************/
  332.  
  333. void    HandleMenuChoice( long menuChoice )
  334. {
  335.     short    menu;
  336.     short    item;
  337.     
  338.     if ( menuChoice != 0 )
  339.     {
  340.         menu = HiWord( menuChoice );
  341.         item = LoWord( menuChoice );
  342.         
  343.         switch ( menu )
  344.         {
  345.             case mApple:
  346.                 HandleAppleChoice( item );
  347.                 break;
  348.             case mFile:
  349.                 HandleFileChoice( item );
  350.                 break;
  351.             case mFont:
  352.                 HandleFontChoice( item );
  353.                 break;
  354.             case mStyle:
  355.                 HandleStyleChoice( item );
  356.                 break;
  357.         }
  358.         HiliteMenu( 0 );
  359.     }
  360. }
  361.  
  362.  
  363. /****************** HandleAppleChoice ***********************/
  364.  
  365. void    HandleAppleChoice( short item )
  366. {
  367.     MenuHandle    appleMenu;
  368.     Str255        accName;
  369.     short        accNumber;
  370.     
  371.     switch ( item )
  372.     {
  373.         case iAbout:    /*  We'll put up an about box next chapter.*/
  374.             SysBeep( 20 );
  375.             break;
  376.         default:
  377.             appleMenu = GetMHandle( mApple );
  378.             GetItem( appleMenu, item, accName );
  379.             accNumber = OpenDeskAcc( accName );
  380.             break;
  381.     }
  382. }
  383.  
  384.  
  385. /****************** HandleFileChoice ***********************/
  386.  
  387. void    HandleFileChoice( short item )
  388. {
  389.     switch ( item )
  390.     {
  391.         case iQuit :
  392.             gDone = true;
  393.             break;
  394.     }
  395. }
  396.  
  397.  
  398. /****************** HandleFontChoice ***********************/
  399.  
  400. void    HandleFontChoice( short item )
  401. {
  402.     short        fontNumber;
  403.     Str255        fontName;
  404.     MenuHandle     menuHandle;
  405.     
  406.     menuHandle = GetMHandle( mFont );
  407.     
  408.     CheckItem( menuHandle, gLastFont, kRemoveCheckMark );
  409.     CheckItem( menuHandle, item, kAddCheckMark );
  410.     
  411.     gLastFont = item;
  412.     
  413.     GetItem( menuHandle, item, fontName );
  414.     GetFNum( fontName, &fontNumber );
  415.     
  416.     TextFont( fontNumber );
  417. }
  418.  
  419.  
  420. /****************** HandleStyleChoice ***********************/
  421.  
  422. void    HandleStyleChoice( short item )
  423. {
  424.     MenuHandle menuHandle;
  425.     
  426.     switch( item )
  427.     {
  428.         case iPlain:
  429.             gCurrentStyle = kPlainStyle;
  430.             break;
  431.         case iBold:
  432.             if ( gCurrentStyle & bold )
  433.                 gCurrentStyle -= bold;
  434.             else
  435.                 gCurrentStyle |= bold;
  436.             break;
  437.         case iItalic:
  438.             if ( gCurrentStyle & italic )
  439.                 gCurrentStyle -= italic;
  440.             else
  441.                 gCurrentStyle |= italic;
  442.             break;
  443.         case iUnderline:
  444.             if ( gCurrentStyle & underline )
  445.                 gCurrentStyle -= underline;
  446.             else
  447.                 gCurrentStyle |= underline;
  448.             break;
  449.         case iOutline:
  450.             if ( gCurrentStyle & outline )
  451.                 gCurrentStyle -= outline;
  452.             else
  453.                 gCurrentStyle |= outline;
  454.             break;
  455.         case iShadow:
  456.             if ( gCurrentStyle & shadow )
  457.                 gCurrentStyle -= shadow;
  458.             else
  459.                 gCurrentStyle |= shadow;
  460.             break;
  461.     }
  462.     
  463.     menuHandle = GetMHandle( mStyle );
  464.     
  465.     CheckItem( menuHandle, iPlain, gCurrentStyle == kPlainStyle );
  466.     CheckItem( menuHandle, iBold, gCurrentStyle & bold );
  467.     CheckItem( menuHandle, iItalic, gCurrentStyle & italic );
  468.     CheckItem( menuHandle, iUnderline, gCurrentStyle & underline );
  469.     CheckItem( menuHandle, iOutline, gCurrentStyle & outline );
  470.     CheckItem( menuHandle, iShadow, gCurrentStyle & shadow );
  471.     
  472.     TextFace( gCurrentStyle );
  473. }
  474.  
  475.  
  476. /****************** DoUpdate ***********************/
  477.  
  478. void    DoUpdate( EventRecord *eventPtr )
  479. {
  480.     WindowPtr        window;
  481.     Str255            timeString;
  482.     unsigned long    curTimeInSecs;
  483.     
  484.     window = (WindowPtr)eventPtr->message;
  485.     
  486.     BeginUpdate( window );
  487.     
  488.     GetDateTime ( &curTimeInSecs );
  489.     curTimeInSecs += GetZoneOffset();
  490.     
  491.     IUTimeString( (long)curTimeInSecs, kIncludeSeconds,
  492.             timeString );
  493.     
  494.     EraseRect( &gClockRect );
  495.     MoveTo( kClockLeft, kClockTop );
  496.     DrawString( timeString );
  497.     
  498.     DrawControls( window );
  499.     
  500.     EndUpdate( window );
  501. }
  502.  
  503.  
  504. /****************** GetZoneOffset ***********************/
  505.  
  506. long GetZoneOffset( void )
  507. {
  508.     MachineLocation    loc;
  509.     long            delta, defaultZoneOffset;
  510.     
  511.     ReadLocation( &loc );
  512.     defaultZoneOffset = ClearHighByte( loc.gmtFlags.gmtDelta );
  513.     
  514.     if ( IsHighBitSet( defaultZoneOffset ) )
  515.         SetHighByte( defaultZoneOffset );
  516.         
  517.     switch ( gCurrentZoneID )
  518.     {
  519.         case kCurrentTimeZone :
  520.             delta = defaultZoneOffset;
  521.             break;
  522.         case kNewYorkTimeZone :
  523.             delta = -5L * kSecondsPerHour ;
  524.             break;
  525.         case kMoscowTimeZone :
  526.             delta = 3L * kSecondsPerHour;
  527.             break;
  528.         case kUlanBatorTimeZone :
  529.             delta = 8L * kSecondsPerHour;
  530.             break;
  531.     }
  532.     delta -= defaultZoneOffset;
  533.     
  534.     return delta;
  535. }