home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / desktop / t / utils / !Clock_C_Clock < prev    next >
Encoding:
Text File  |  1993-05-31  |  24.2 KB  |  947 lines

  1. /*
  2.  *
  3.  *      Title     : Clock
  4.  *      System    : Risc-OS clock.
  5.  *      Version     "3.0"
  6.  *      Copyright : (c) John Winters
  7.  *      Date      : 10th January, 1992
  8.  *      Author    : John H. Winters
  9.  *
  10.  *      Function  : A re-write of the Risc-OS clock in C.
  11.  *
  12.  *
  13.  *      Modification history.
  14.  *
  15.  *      Version   : 1.1 (Reflect in header IDENT)
  16.  *      Date      : 19th January, 1992
  17.  *      Author    : John H. Winters
  18.  *      Changes   : Use a table of ratios instead of a table of
  19.  *                  doubles.
  20.  *
  21.  *      Version   : 2.0 (Reflect in header IDENT)
  22.  *      Date      : 25th January, 1992
  23.  *      Author    : John H. Winters
  24.  *      Changes   : Access the library at a lower level in order
  25.  *                  to remove unwanted components from the
  26.  *                  final executable.
  27.  *
  28.  *      Version   : 2.1 (Reflect in header IDENT)
  29.  *      Date      : 25th January, 1992
  30.  *      Author    : John H. Winters
  31.  *      Changes   : Changed to correctly detect window size
  32.  *                  changes, where the smaller dimension does
  33.  *                  not change.
  34.  *
  35.  *      Version   : 3.0
  36.  *      Date      : 31st May, 1993
  37.  *      Author    : John H. Winters
  38.  *      Changes   : RISC OS 3.1 changes.
  39.  *
  40.  *      Version   : 
  41.  *      Date      : 
  42.  *      Author    : 
  43.  *      Changes   : 
  44.  *
  45.  */
  46.  
  47. #include <stdlib.h>
  48. #include <time.h>
  49. #include "kernel.h"
  50. #include "swis.h"
  51. #include "vdu.h"
  52. #include "spritelib.h"
  53. #include "wimplib.h"
  54. #include "winapp.h"
  55.  
  56. /*
  57.  *==========================================================================
  58.  *
  59.  *  Hash defines.
  60.  *
  61.  *==========================================================================
  62.  */
  63.  
  64. #define Log2BPP 9
  65.  
  66. /*
  67.  *==========================================================================
  68.  *
  69.  *  Local data.
  70.  *
  71.  *==========================================================================
  72.  */
  73.  
  74. static unsigned short int ratios [16][2] = {
  75.     {0,     1}       /* 0.000000, error 0.000000 */,
  76.     {5369,  51364}   /* 0.104528, error 0.000000 */,
  77.     {13581, 65321}   /* 0.207912, error 0.000000 */,
  78.     {17711, 57314}   /* 0.309017, error 0.000000 */,
  79.     {9455,  23246}   /* 0.406737, error 0.000000 */,
  80.     {11,    22}      /* 0.500000, error 0.000000 */,
  81.     {4456,  7581}    /* 0.587785, error 0.000000 */,
  82.     {25437, 38015}   /* 0.669131, error 0.000000 */,
  83.     {33877, 45586}   /* 0.743145, error 0.000000 */,
  84.     {51841, 64079}   /* 0.809017, error 0.000000 */,
  85.     {35113, 40545}   /* 0.866025, error 0.000000 */,
  86.     {56733, 62102}   /* 0.913545, error 0.000000 */,
  87.     {54506, 57311}   /* 0.951057, error 0.000000 */,
  88.     {12578, 12859}   /* 0.978148, error 0.000000 */,
  89.     {58639, 58962}   /* 0.994522, error 0.000000 */,
  90.     {10,    10}      /* 1.000000, error 0.000000 */
  91. } ;
  92.  
  93. static t_window_block window_block = {
  94.     {0, -400, 400, 0},          /* Visible area */
  95.     0,                          /* Scroll offset X */
  96.     0,                          /* Scroll offset Y */
  97.     -1,                         /* Behind */
  98.     {FALSE,                     /* Dummy0 */
  99.      TRUE,                      /* Moveable */
  100.      FALSE,                     /* Dummy2 */
  101.      FALSE,                     /* Dummy3 */
  102.      FALSE,                     /* Redraw_ok */
  103.      FALSE,                     /* Is_pane */
  104.      FALSE,                     /* No_bounds */
  105.      FALSE,                     /* Dummy7 */
  106.      FALSE,                     /* Scroll_request */
  107.      FALSE,                     /* Scroll_request_nr */
  108.      FALSE,                     /* Real_colours */
  109.      FALSE,                     /* Back_window */
  110.      FALSE,                     /* Hot_keys */
  111.      FALSE,                     /* Dummy13 */
  112.      FALSE,                     /* Dummy14 */
  113.      FALSE,                     /* Dummy15 */
  114.      FALSE,                     /* Is_open */
  115.      FALSE,                     /* Is_top */
  116.      FALSE,                     /* Is_full */
  117.      FALSE,                     /* Is_toggling */
  118.      FALSE,                     /* Has_focus */
  119.      FALSE,                     /* Dummy21 */
  120.      FALSE,                     /* Dummy22 */
  121.      FALSE,                     /* Dummy23 */
  122.      TRUE,                      /* Back_icon */
  123.      TRUE,                      /* Close_icon */
  124.      TRUE,                      /* Title_bar */
  125.      TRUE,                      /* Toggle_icon */
  126.      TRUE,                      /* Ver_scroll */
  127.      TRUE,                      /* Adjust_icon */
  128.      FALSE,                     /* Hor_scroll */
  129.      TRUE},                     /* New_flags */
  130.     {7, 2, 7, 0, 3, 1, 12, 0},  /* Colours */
  131.     {0, -980, 1280, 0},         /* Work area */
  132.     {0x2d},                     /* Title flags */
  133.     {0x3000},                   /* Work flags */
  134.     0,                          /* Sprite area */
  135.     0,                          /* Min width */
  136.     0,                          /* Min height */
  137.     {"'C' Clock"},                  /* Title */
  138.     0                           /* Num icons */
  139. } ;
  140.  
  141. static t_window_handle window_handle ;
  142.  
  143. /*
  144.  *  Current time.
  145.  */
  146. static unsigned int hour ;
  147. static unsigned int minute ;
  148. static unsigned int second ;
  149.  
  150. /*
  151.  *  Clock and window sizes.
  152.  */
  153. static unsigned int radius ;
  154.  
  155. /*
  156.  *  Palette data.
  157.  */
  158. static unsigned int    bpp ;
  159. static unsigned int    colour0 ;
  160. static t_palette_block palette ;
  161. static unsigned int    tint0 ;
  162.  
  163. /*
  164.  *==========================================================================
  165.  *
  166.  *  Externally visible data.
  167.  *
  168.  *==========================================================================
  169.  */
  170.  
  171. const char WA_resource_dir [] = "Clock" ;
  172. const char WA_task_name []    = "'C' Clock" ;
  173. int __root_stack_size = 2048 ;
  174.  
  175. /*
  176.  *==========================================================================
  177.  *
  178.  *  Forward declarations.
  179.  *
  180.  *==========================================================================
  181.  */
  182.  
  183. static unsigned int calc_radius (
  184.     t_window_handle  window_handle,
  185.     unsigned int    *radius) ;
  186.  
  187. static void draw_hand (
  188.     unsigned int angle,
  189.     int          centrex,
  190.     int          centrey,
  191.     unsigned int length) ;
  192.  
  193. static void draw_sweep_hand (
  194.     unsigned int angle,
  195.     int          centrex,
  196.     int          centrey,
  197.     unsigned int length) ;
  198.  
  199. static void event_handler (
  200.     t_poll_block *poll_block) ;
  201.  
  202. static void gcol (
  203.     unsigned int m,
  204.     unsigned int c) ;
  205.  
  206. static void message_handler (
  207.     t_poll_block *poll_block) ;
  208.  
  209. static unsigned int pop_up_clock (void) ;
  210.  
  211. static void read_time (
  212.     unsigned int *hour,
  213.     unsigned int *minute,
  214.     unsigned int *second) ;
  215.  
  216. static void report_error (
  217.     const _kernel_oserror *error_ptr) ;
  218.  
  219. static void reset_palette (void) ;
  220.  
  221. static void tick_handler (
  222.     void *reference) ;
  223.  
  224. static int times_cos (
  225.     int multiplier,
  226.     int angle) ;
  227.  
  228. static int times_sin (
  229.     int multiplier,
  230.     int angle) ;
  231.  
  232. /*
  233.  *==========================================================================
  234.  *
  235.  *  Externally visible routines.
  236.  *
  237.  *==========================================================================
  238.  */
  239.  
  240. unsigned int WA_BeginProcessing (void)
  241.  
  242. /*
  243.  *  Function :
  244.  *                  Start the clock going.
  245.  *
  246.  *  Parameters :
  247.  *                  None.
  248.  *
  249.  *  Returns :
  250.  *                  TRUE if all is OK, FALSE otherwise.
  251.  *
  252.  */
  253.  
  254. {
  255.     const _kernel_oserror *error_ptr ;
  256.     unsigned int           result ;
  257.  
  258.     result = FALSE ;
  259.     error_ptr = WIMP_CreateWindow (&window_block, &window_handle) ;
  260.     if (error_ptr == NULL)
  261.     {
  262.         WAI_AttachHandler (ET_RedrawRequest,
  263.                            event_handler) ;
  264.         WAI_AttachHandler (ET_OpenRequest,
  265.                            event_handler) ;
  266.         WAI_AttachHandler (ET_CloseRequest,
  267.                            event_handler) ;
  268.         WAI_AttachHandler (ET_UserMessage,
  269.                            message_handler) ;
  270.         WAI_AttachHandler (ET_UserMessageRecorded,
  271.                            message_handler) ;
  272.         WA_AlarmEvery (100,
  273.                        FALSE,
  274.                        tick_handler,
  275.                        NULL) ;
  276.         read_time (&hour, &minute, &second) ;
  277.         calc_radius (window_handle, &radius) ;
  278.         reset_palette () ;
  279.         pop_up_clock () ;
  280.         result = TRUE ;
  281.     }
  282.     else
  283.     {
  284.         report_error (error_ptr) ;
  285.     }
  286.     return (result) ;
  287. }
  288.  
  289. /*
  290.  *==========================================================================
  291.  *
  292.  *  Local routines.
  293.  *
  294.  *==========================================================================
  295.  */
  296.  
  297. static unsigned int calc_radius (
  298.     t_window_handle  window_handle,
  299.     unsigned int    *radius)
  300.  
  301. /*
  302.  *  Function :
  303.  *                  Calculate the radius to use.
  304.  *
  305.  *  Parameters :
  306.  *                  window_handle Handle on the window.
  307.  *                  radius        Pointer to location to store the radius.
  308.  *
  309.  *  Returns :
  310.  *                  TRUE if it has changed, FALSE otherwise.
  311.  *
  312.  */
  313.  
  314. {
  315.     unsigned int        height ;
  316.     unsigned int        lr ;
  317.     static unsigned int prev_height = 1 ;
  318.     static unsigned int prev_width  = 1 ;
  319.     unsigned int        result ;
  320.     t_state_block       state_block ;
  321.     unsigned int        width ;
  322.  
  323.     WIMP_GetWindowState (window_handle, &state_block) ;
  324.     width  = state_block.open_block.visible_area.max.x -
  325.              state_block.open_block.visible_area.min.x ;
  326.     height = state_block.open_block.visible_area.max.y -
  327.              state_block.open_block.visible_area.min.y ;
  328.     if (width > height)
  329.     {
  330.         lr = height ;
  331.     }
  332.     else
  333.     {
  334.         lr = width ;
  335.     }
  336.     lr >>= 1 ;
  337.     lr -= (lr >> 4) ;
  338.     *radius = lr ;
  339.     result = ((height != prev_height) ||
  340.               (width != prev_width)) ;
  341.     prev_height = height ;
  342.     prev_width  = width ;
  343.     return (result) ;
  344. }
  345.  
  346.  
  347. static void draw_clock (
  348.     t_redraw_block *redraw_block)
  349.  
  350. /*
  351.  *  Function :
  352.  *                  Redraw the clock.
  353.  *
  354.  *  Parameters :
  355.  *                  redraw_block    Tells us where the window is.
  356.  *
  357.  *  Returns :
  358.  *                  None.
  359.  *
  360.  */
  361.  
  362. {
  363.     int centrex ;
  364.     int centrey ;
  365.     int i ;
  366.     int t ;
  367.  
  368.     centrex = (redraw_block->visible_area.min.x + redraw_block->visible_area.max.x) / 2 ;
  369.     centrey = (redraw_block->visible_area.min.y + redraw_block->visible_area.max.y) / 2 ;
  370.     gcol (0, 7) ;
  371.     if (radius > 150)
  372.     {
  373.         t = radius - (radius >> 5) - 8 ;
  374.         for (i = 0; i < 60; i++)
  375.         {
  376.             VDU_Plot (69,
  377.                       centrex + times_sin (t, i),
  378.                       centrey + times_cos (t, i)) ;
  379.         }
  380.     }
  381.     if (radius > 50)
  382.     {
  383.         gcol (0, 8) ;
  384.         t = radius - (radius >> 4) ;
  385.         for (i = 0; i < 60; i+= 5)
  386.         {
  387.             VDU_Plot (4, 
  388.                       centrex + times_sin (t, i) - (radius >> 5),
  389.                       centrey + times_cos (t, i) - (radius >> 5)) ;
  390.             VDU_Plot (97,
  391.                       radius >> 4,
  392.                       radius >> 4) ;
  393.         }
  394.         gcol (0, 7) ;
  395.     }
  396.     VDU_Plot (4, centrex, centrey) ;
  397.     VDU_Plot (145, radius, 0) ;
  398.     /*
  399.      *  And now the hands.
  400.      */
  401.     gcol (3, 3) ;
  402.     draw_hand (hour * 5 + (minute / 12),
  403.                centrex,
  404.                centrey,
  405.                radius - (radius >> 1)) ;
  406.     draw_hand (minute,
  407.                centrex,
  408.                centrey,
  409.                radius - (radius >> 2)) ;
  410.     gcol (3, 11) ;
  411.     draw_sweep_hand (second,
  412.                      centrex,
  413.                      centrey,
  414.                      radius) ;
  415.     gcol (0, 11) ;
  416.     VDU_Move (centrex, centrey) ;
  417.     VDU_Plot (153, 0, radius >> 4) ;
  418. }
  419.  
  420.  
  421. static void draw_hand (
  422.     unsigned int angle,
  423.     int          centrex,
  424.     int          centrey,
  425.     unsigned int length)
  426.  
  427. /*
  428.  *  Function :
  429.  *                  Draw a single hand.
  430.  *
  431.  *  Parameters :
  432.  *                  angle   The angle of the hand - 0 to 59.
  433.  *                  centrex X co-ordinate of the clock centre.
  434.  *                  centrey Y co-ordinate of the clock centre.
  435.  *                  length  Length of the hand.
  436.  *
  437.  *  Returns :
  438.  *                  None.
  439.  *
  440.  */
  441.  
  442. {
  443.     int t ;
  444.  
  445.     t = length >> 1 ;
  446.     VDU_Move (centrex + times_sin (t, angle + 1),
  447.               centrey + times_cos (t, angle + 1)) ;
  448.     VDU_Move (centrex, centrey) ;
  449.     VDU_Plot (117,
  450.               centrex + times_sin (t, angle + 59),
  451.               centrey + times_cos (t, angle + 59)) ;
  452. }
  453.  
  454.  
  455. static void draw_sweep_hand (
  456.     unsigned int angle,
  457.     int          centrex,
  458.     int          centrey,
  459.     unsigned int length)
  460.  
  461. /*
  462.  *  Function :
  463.  *                  Draw the sweep hand.
  464.  *
  465.  *  Parameters :
  466.  *                  angle   The angle of the hand - 0 to 59.
  467.  *                  centrex X co-ordinate of the clock centre.
  468.  *                  centrey Y co-ordinate of the clock centre.
  469.  *                  length  Length of the hand.
  470.  *
  471.  *  Returns :
  472.  *                  None.
  473.  *
  474.  */
  475.  
  476. {
  477.     VDU_Move (centrex, centrey) ;
  478.     VDU_Plot (64,
  479.               times_sin (length >> 4, angle),
  480.               times_cos (length >> 4, angle)) ;
  481.     VDU_Plot (1,
  482.               times_sin (length - (length >> 4), angle),
  483.               times_cos (length - (length >> 4), angle)) ;
  484. }
  485.  
  486.  
  487. static void event_handler (
  488.     t_poll_block *poll_block)
  489.  
  490. /*
  491.  *  Function :
  492.  *                  Handle wimp events.
  493.  *
  494.  *  Parameters :
  495.  *                  poll_block  Pointer to event block.
  496.  *
  497.  *  Returns :
  498.  *                  None.
  499.  *
  500.  */
  501.  
  502. {
  503.     unsigned int   more ;
  504.     t_redraw_block redraw_block ;
  505.  
  506.     switch (poll_block->event_type)
  507.     {
  508.         case ET_RedrawRequest :
  509.             redraw_block.handle = poll_block->data.ob.window_handle ;
  510.             WIMP_RedrawWindow (&redraw_block,
  511.                                &more) ;
  512.             while (more)
  513.             {
  514.                 draw_clock (&redraw_block) ;
  515.                 WIMP_GetRectangle (&redraw_block,
  516.                                    &more) ;
  517.             }
  518.             break ;
  519.  
  520.         case ET_OpenRequest :
  521.             poll_block->data.ob.scroll_offset.y = 0 ;
  522.             WIMP_OpenWindow (&(poll_block->data.ob)) ;
  523.             if (calc_radius (poll_block->data.ob.window_handle,
  524.                              &radius))
  525.             {
  526.                 /*
  527.                  *  Effective size has changed.
  528.                  */
  529.                 redraw_block.handle       = -1 ;
  530.                 redraw_block.visible_area = poll_block->data.ob.visible_area ;
  531.                 WIMP_ForceRedraw (&redraw_block) ;
  532.             }
  533.             break ;
  534.  
  535.         case ET_CloseRequest :
  536.             WA_WindUp () ;
  537.  
  538.     }
  539. }
  540.  
  541.  
  542. static void gcol (
  543.     unsigned int m,
  544.     unsigned int c)
  545.  
  546. /*
  547.  *  Function :
  548.  *                  Not quite sure.
  549.  *
  550.  *  Parameters :
  551.  *                  m
  552.  *                  c
  553.  *
  554.  *  Returns :
  555.  *                  None.
  556.  *
  557.  */
  558.  
  559. {
  560.     unsigned int c1 ;
  561.     t_colour     colour ;
  562.     unsigned int i ;
  563.     unsigned int t1 ;
  564.  
  565.     if ((m == 3) &&
  566.         (bpp == 8))
  567.     {
  568.         c1 = (palette.sc [c].bytes.gcol) >> 2 ;
  569.         t1 = palette.sc [c].bytes.gcol & 0x03 ;
  570.         VDU_Gcol (3, c1 ^ colour0) ;
  571.         VDU (23) ;
  572.         VDU (17) ;
  573.         VDU (2) ;
  574.         VDU (t1 ^ tint0) ;
  575.         for (i = 0; i < 6; i++)
  576.         {
  577.             VDU (0) ;
  578.         }
  579.     }
  580.     else
  581.     {
  582.         colour.wimp_colour = c ;
  583.         colour.gcol_action = m ;
  584.         colour.foreback    = 0 ;
  585.         WIMP_SetColour (colour) ;
  586.     }
  587. }
  588.  
  589.  
  590. static void message_handler (
  591.     t_poll_block *poll_block)
  592.  
  593. /*
  594.  *  Function :
  595.  *                  Handle messages.
  596.  *
  597.  *  Parameters :
  598.  *                  poll_block  Pointer to event block.
  599.  *
  600.  *  Returns :
  601.  *                  None.
  602.  *
  603.  */
  604.  
  605. {
  606.     if ((poll_block->data.mb.action == Message_PaletteChange) ||
  607.         (poll_block->data.mb.action == Message_ModeChange))
  608.     {
  609.         reset_palette () ;
  610.     }
  611. }
  612.  
  613.  
  614. static unsigned int pop_up_clock (void)
  615.  
  616. /*
  617.  *  Function :
  618.  *                  Make the clock appear.
  619.  *
  620.  *  Parameters :
  621.  *                  None.
  622.  *
  623.  *  Returns :
  624.  *                  TRUE for success, FALSE for failure.
  625.  *
  626.  */
  627.  
  628. {
  629.     const _kernel_oserror *error_ptr ;
  630.     unsigned int           height ;
  631.     t_mouse_block          pointer_state ;
  632.     t_state_block          state_block ;
  633.     unsigned int           width ;
  634.  
  635.     error_ptr = WIMP_GetWindowState (window_handle,
  636.                                      &state_block) ;
  637.     if (error_ptr == NULL)
  638.     {
  639.         /*
  640.          *  Where is the mouse?
  641.          */
  642.         error_ptr = WIMP_GetPointerInfo (&pointer_state) ;
  643.         if (error_ptr == NULL)
  644.         {
  645.             /*
  646.              *  Adjust the window to appear just below the mouse.
  647.              *  The Wimp will adjust it if this would make it appear off
  648.              *  the screen.
  649.              */
  650.             width  = state_block.open_block.visible_area.max.x -
  651.                      state_block.open_block.visible_area.min.x ;
  652.             height = state_block.open_block.visible_area.max.y -
  653.                      state_block.open_block.visible_area.min.y ;
  654.             state_block.open_block.visible_area.min.x = pointer_state.x - (width / 2) ;
  655.             state_block.open_block.visible_area.max.x = pointer_state.x + (width / 2) ;
  656.             state_block.open_block.visible_area.max.y = pointer_state.y - 64 ;
  657.             state_block.open_block.visible_area.min.y = 
  658.               state_block.open_block.visible_area.max.y - height ;
  659.             error_ptr = WIMP_OpenWindow (&(state_block.open_block)) ;
  660.         }
  661.     }
  662.     report_error (error_ptr) ;
  663.     return (error_ptr == NULL) ;
  664. }
  665.  
  666.  
  667. static void read_time (
  668.     unsigned int *hour,
  669.     unsigned int *minute,
  670.     unsigned int *second)
  671.  
  672. /*
  673.  *  Function :
  674.  *                  Read the current date and time (12 hour clock).
  675.  *
  676.  *  Parameters :
  677.  *                  hour    Pointer to location to store the hour.
  678.  *                  minute  Pointer to location to store the minute.
  679.  *                  second  Pointer to location to store the second.
  680.  *
  681.  *  Returns :
  682.  *                  None.
  683.  *
  684.  */
  685.  
  686. {
  687.     struct tm *lt ;
  688.     time_t     t ;
  689.  
  690.     time (&t) ;
  691.     lt = localtime (&t) ;
  692.     *second = lt->tm_sec ;
  693.     *minute = lt->tm_min ;
  694.     *hour   = (lt->tm_hour % 12) ;
  695. }
  696.  
  697.  
  698. static void report_error (
  699.     const _kernel_oserror *error_ptr)
  700.  
  701. /*
  702.  *  Function :
  703.  *                  Report error if any.
  704.  *
  705.  *  Parameters :
  706.  *                  error_ptr   Pointer to error block, or NULL.
  707.  *
  708.  *  Returns :
  709.  *                  None.
  710.  *
  711.  */
  712.  
  713. {
  714.     t_error_flags error_flags ;
  715.     unsigned int  result ;
  716.  
  717.     if (error_ptr != NULL)
  718.     {
  719.         error_flags.value = 0 ;
  720.         error_flags.m.ok = TRUE ;
  721.         WIMP_ReportError (error_ptr, error_flags, WA_resource_dir, &result) ;
  722.     }
  723. }
  724.  
  725.  
  726. static void reset_palette (void)
  727.  
  728. /*
  729.  *  Function :
  730.  *                  Read palette variables.
  731.  *
  732.  *  Parameters :
  733.  *                  None.
  734.  *
  735.  *  Returns :
  736.  *                  None.
  737.  *
  738.  */
  739.  
  740. {
  741.     _kernel_swi_regs registers ;
  742.  
  743.     registers.r [0] = -1 ;
  744.     registers.r [1] = Log2BPP ;
  745.     _kernel_swi (OS_ReadModeVariable,
  746.                  ®isters,
  747.                  ®isters) ;
  748.     bpp = 1 << registers.r [2] ;
  749.     WIMP_ReadPalette (&palette) ;
  750.     colour0 = palette.sc [0].bytes.gcol >> 2 ;
  751.     tint0   = palette.sc [0].bytes.gcol & 0x03 ;
  752. }
  753.  
  754.  
  755. static void tick_handler (
  756.     void *reference)
  757.  
  758. /*
  759.  *  Function :
  760.  *                  Handle a timer event.
  761.  *
  762.  *  Parameters :
  763.  *                  reference  Ignored.
  764.  *
  765.  *  Returns :
  766.  *                  None.
  767.  *
  768.  */
  769.  
  770. {
  771.     int                    centrex ;
  772.     int                    centrey ;
  773.     unsigned int           do_hour ;
  774.     unsigned int           do_minute ;
  775.     unsigned int           do_second ;
  776.     const _kernel_oserror *error_ptr ;
  777.     unsigned int           more ;
  778.     unsigned int           previous_hour ;
  779.     unsigned int           previous_minute ;
  780.     unsigned int           previous_second ;
  781.     t_redraw_block         redraw_block ;
  782.     t_state_block          state_block ;
  783.  
  784.     reference = reference ;
  785.  
  786.     previous_hour   = hour ;
  787.     previous_minute = minute ;
  788.     previous_second = second ;
  789.     read_time (&hour, &minute, &second) ;
  790.     if ((hour != previous_hour) ||
  791.         (minute != previous_minute) ||
  792.         (second != previous_second))
  793.     {
  794.         /*
  795.          *  Update required.
  796.          */
  797.         error_ptr = WIMP_GetWindowState (window_handle,
  798.                                          &state_block) ;
  799.         if (error_ptr == NULL)
  800.         {
  801.             redraw_block.handle = window_handle ;
  802.             redraw_block.visible_area.min.x = 0 ;
  803.             redraw_block.visible_area.max.x = 1280 ;
  804.             redraw_block.visible_area.max.y = 0 ;
  805.             redraw_block.visible_area.min.y = -1024 ;
  806.             error_ptr = WIMP_UpdateWindow (&redraw_block, &more) ;
  807.             if (error_ptr == NULL)
  808.             {
  809.                 while (more)
  810.                 {
  811.                     /*
  812.                      *  Redraw the clock.  First remove old hands as
  813.                      *  necessary.  Then draw new ones.
  814.                      */
  815.                     centrex = (redraw_block.visible_area.min.x + redraw_block.visible_area.max.x) / 2 ;
  816.                     centrey = (redraw_block.visible_area.min.y + redraw_block.visible_area.max.y) / 2 ;
  817.                     gcol (3, 3) ;
  818.                     do_hour = ((hour != previous_hour) ||
  819.                                ((minute / 12) != (previous_minute / 12))) ;
  820.                     do_minute = (minute != previous_minute) ;
  821.                     do_second = (second != previous_second) ;
  822.                     if (do_hour)
  823.                     {
  824.                         draw_hand (previous_hour * 5 + (previous_minute / 12),
  825.                                    centrex,
  826.                                    centrey,
  827.                                    radius - (radius >> 1)) ;
  828.                     }
  829.                     if (do_minute)
  830.                     {
  831.                         draw_hand (previous_minute,
  832.                                    centrex,
  833.                                    centrey,
  834.                                    radius - (radius >> 2)) ;
  835.                     }
  836.                     gcol (3, 11) ;
  837.                     if (do_second)
  838.                     {
  839.                         draw_sweep_hand (previous_second,
  840.                                          centrex,
  841.                                          centrey,
  842.                                          radius) ;
  843.                     }
  844.                     gcol (3, 3) ;
  845.                     if (do_hour)
  846.                     {
  847.                         draw_hand (hour * 5 + (minute / 12),
  848.                                    centrex,
  849.                                    centrey,
  850.                                    radius - (radius >> 1)) ;
  851.                     }
  852.                     if (do_minute)
  853.                     {
  854.                         draw_hand (minute,
  855.                                    centrex,
  856.                                    centrey,
  857.                                    radius - (radius >> 2)) ;
  858.                     }
  859.                     gcol (3, 11) ;
  860.                     if (do_second)
  861.                     {
  862.                         draw_sweep_hand (second,
  863.                                          centrex,
  864.                                          centrey,
  865.                                          radius) ;
  866.                     }
  867.                     gcol (0, 11) ;
  868.                     VDU_Move (centrex, centrey) ;
  869.                     VDU_Plot (153, 0, radius >> 4) ;
  870.                     WIMP_GetRectangle (&redraw_block, &more) ;
  871.                 }
  872.             }
  873.         }
  874.         report_error (error_ptr) ;
  875.     }
  876. }
  877.  
  878.  
  879. static int times_cos (
  880.     int multiplier,
  881.     int angle)
  882.  
  883. /*
  884.  *  Function :
  885.  *                  Multiply by a cos.
  886.  *
  887.  *  Parameters :
  888.  *                  multiplier   Number to multiply.
  889.  *                  angle        Angle to look up.
  890.  *
  891.  *  Returns :
  892.  *                  Multiplied value.
  893.  *
  894.  */
  895.  
  896. {
  897.     return (times_sin (multiplier, angle + 15)) ;
  898. }
  899.  
  900.  
  901. static int times_sin (
  902.     int multiplier,
  903.     int angle)
  904.  
  905. /*
  906.  *  Function :
  907.  *                  Multiply an integer by the indicated sin value.
  908.  *                  Angle will be considered mod 60.
  909.  *
  910.  *  Parameters :
  911.  *                  multiplier   Number to multiply.
  912.  *                  angle        Angle to look up.
  913.  *
  914.  *  Returns :
  915.  *                  Multiplied value.
  916.  *
  917.  */
  918.  
  919. {
  920.     unsigned int invert_sign ;
  921.     int          result ;
  922.  
  923.     angle = angle % 60 ;
  924.     /*
  925.      *  0 to 15 can be addressed directly.  Others require adjustment.
  926.      */
  927.     if (angle >= 30)
  928.     {
  929.         angle-= 30 ;
  930.         invert_sign = TRUE ;
  931.     }
  932.     else
  933.     {
  934.         invert_sign = FALSE ;
  935.     }
  936.     if (angle > 15)
  937.     {
  938.         angle = 30 - angle ;
  939.     }
  940.     result = (multiplier * ratios [angle][0]) / ratios [angle][1] ;
  941.     if (invert_sign)
  942.     {
  943.         result = (-result) ;
  944.     }
  945.     return (result) ;
  946. }
  947.