home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * Title : Clock
- * System : Risc-OS clock.
- * Version "3.0"
- * Copyright : (c) John Winters
- * Date : 10th January, 1992
- * Author : John H. Winters
- *
- * Function : A re-write of the Risc-OS clock in C.
- *
- *
- * Modification history.
- *
- * Version : 1.1 (Reflect in header IDENT)
- * Date : 19th January, 1992
- * Author : John H. Winters
- * Changes : Use a table of ratios instead of a table of
- * doubles.
- *
- * Version : 2.0 (Reflect in header IDENT)
- * Date : 25th January, 1992
- * Author : John H. Winters
- * Changes : Access the library at a lower level in order
- * to remove unwanted components from the
- * final executable.
- *
- * Version : 2.1 (Reflect in header IDENT)
- * Date : 25th January, 1992
- * Author : John H. Winters
- * Changes : Changed to correctly detect window size
- * changes, where the smaller dimension does
- * not change.
- *
- * Version : 3.0
- * Date : 31st May, 1993
- * Author : John H. Winters
- * Changes : RISC OS 3.1 changes.
- *
- * Version :
- * Date :
- * Author :
- * Changes :
- *
- */
-
- #include <stdlib.h>
- #include <time.h>
- #include "kernel.h"
- #include "swis.h"
- #include "vdu.h"
- #include "spritelib.h"
- #include "wimplib.h"
- #include "winapp.h"
-
- /*
- *==========================================================================
- *
- * Hash defines.
- *
- *==========================================================================
- */
-
- #define Log2BPP 9
-
- /*
- *==========================================================================
- *
- * Local data.
- *
- *==========================================================================
- */
-
- static unsigned short int ratios [16][2] = {
- {0, 1} /* 0.000000, error 0.000000 */,
- {5369, 51364} /* 0.104528, error 0.000000 */,
- {13581, 65321} /* 0.207912, error 0.000000 */,
- {17711, 57314} /* 0.309017, error 0.000000 */,
- {9455, 23246} /* 0.406737, error 0.000000 */,
- {11, 22} /* 0.500000, error 0.000000 */,
- {4456, 7581} /* 0.587785, error 0.000000 */,
- {25437, 38015} /* 0.669131, error 0.000000 */,
- {33877, 45586} /* 0.743145, error 0.000000 */,
- {51841, 64079} /* 0.809017, error 0.000000 */,
- {35113, 40545} /* 0.866025, error 0.000000 */,
- {56733, 62102} /* 0.913545, error 0.000000 */,
- {54506, 57311} /* 0.951057, error 0.000000 */,
- {12578, 12859} /* 0.978148, error 0.000000 */,
- {58639, 58962} /* 0.994522, error 0.000000 */,
- {10, 10} /* 1.000000, error 0.000000 */
- } ;
-
- static t_window_block window_block = {
- {0, -400, 400, 0}, /* Visible area */
- 0, /* Scroll offset X */
- 0, /* Scroll offset Y */
- -1, /* Behind */
- {FALSE, /* Dummy0 */
- TRUE, /* Moveable */
- FALSE, /* Dummy2 */
- FALSE, /* Dummy3 */
- FALSE, /* Redraw_ok */
- FALSE, /* Is_pane */
- FALSE, /* No_bounds */
- FALSE, /* Dummy7 */
- FALSE, /* Scroll_request */
- FALSE, /* Scroll_request_nr */
- FALSE, /* Real_colours */
- FALSE, /* Back_window */
- FALSE, /* Hot_keys */
- FALSE, /* Dummy13 */
- FALSE, /* Dummy14 */
- FALSE, /* Dummy15 */
- FALSE, /* Is_open */
- FALSE, /* Is_top */
- FALSE, /* Is_full */
- FALSE, /* Is_toggling */
- FALSE, /* Has_focus */
- FALSE, /* Dummy21 */
- FALSE, /* Dummy22 */
- FALSE, /* Dummy23 */
- TRUE, /* Back_icon */
- TRUE, /* Close_icon */
- TRUE, /* Title_bar */
- TRUE, /* Toggle_icon */
- TRUE, /* Ver_scroll */
- TRUE, /* Adjust_icon */
- FALSE, /* Hor_scroll */
- TRUE}, /* New_flags */
- {7, 2, 7, 0, 3, 1, 12, 0}, /* Colours */
- {0, -980, 1280, 0}, /* Work area */
- {0x2d}, /* Title flags */
- {0x3000}, /* Work flags */
- 0, /* Sprite area */
- 0, /* Min width */
- 0, /* Min height */
- {"'C' Clock"}, /* Title */
- 0 /* Num icons */
- } ;
-
- static t_window_handle window_handle ;
-
- /*
- * Current time.
- */
- static unsigned int hour ;
- static unsigned int minute ;
- static unsigned int second ;
-
- /*
- * Clock and window sizes.
- */
- static unsigned int radius ;
-
- /*
- * Palette data.
- */
- static unsigned int bpp ;
- static unsigned int colour0 ;
- static t_palette_block palette ;
- static unsigned int tint0 ;
-
- /*
- *==========================================================================
- *
- * Externally visible data.
- *
- *==========================================================================
- */
-
- const char WA_resource_dir [] = "Clock" ;
- const char WA_task_name [] = "'C' Clock" ;
- int __root_stack_size = 2048 ;
-
- /*
- *==========================================================================
- *
- * Forward declarations.
- *
- *==========================================================================
- */
-
- static unsigned int calc_radius (
- t_window_handle window_handle,
- unsigned int *radius) ;
-
- static void draw_hand (
- unsigned int angle,
- int centrex,
- int centrey,
- unsigned int length) ;
-
- static void draw_sweep_hand (
- unsigned int angle,
- int centrex,
- int centrey,
- unsigned int length) ;
-
- static void event_handler (
- t_poll_block *poll_block) ;
-
- static void gcol (
- unsigned int m,
- unsigned int c) ;
-
- static void message_handler (
- t_poll_block *poll_block) ;
-
- static unsigned int pop_up_clock (void) ;
-
- static void read_time (
- unsigned int *hour,
- unsigned int *minute,
- unsigned int *second) ;
-
- static void report_error (
- const _kernel_oserror *error_ptr) ;
-
- static void reset_palette (void) ;
-
- static void tick_handler (
- void *reference) ;
-
- static int times_cos (
- int multiplier,
- int angle) ;
-
- static int times_sin (
- int multiplier,
- int angle) ;
-
- /*
- *==========================================================================
- *
- * Externally visible routines.
- *
- *==========================================================================
- */
-
- unsigned int WA_BeginProcessing (void)
-
- /*
- * Function :
- * Start the clock going.
- *
- * Parameters :
- * None.
- *
- * Returns :
- * TRUE if all is OK, FALSE otherwise.
- *
- */
-
- {
- const _kernel_oserror *error_ptr ;
- unsigned int result ;
-
- result = FALSE ;
- error_ptr = WIMP_CreateWindow (&window_block, &window_handle) ;
- if (error_ptr == NULL)
- {
- WAI_AttachHandler (ET_RedrawRequest,
- event_handler) ;
- WAI_AttachHandler (ET_OpenRequest,
- event_handler) ;
- WAI_AttachHandler (ET_CloseRequest,
- event_handler) ;
- WAI_AttachHandler (ET_UserMessage,
- message_handler) ;
- WAI_AttachHandler (ET_UserMessageRecorded,
- message_handler) ;
- WA_AlarmEvery (100,
- FALSE,
- tick_handler,
- NULL) ;
- read_time (&hour, &minute, &second) ;
- calc_radius (window_handle, &radius) ;
- reset_palette () ;
- pop_up_clock () ;
- result = TRUE ;
- }
- else
- {
- report_error (error_ptr) ;
- }
- return (result) ;
- }
-
- /*
- *==========================================================================
- *
- * Local routines.
- *
- *==========================================================================
- */
-
- static unsigned int calc_radius (
- t_window_handle window_handle,
- unsigned int *radius)
-
- /*
- * Function :
- * Calculate the radius to use.
- *
- * Parameters :
- * window_handle Handle on the window.
- * radius Pointer to location to store the radius.
- *
- * Returns :
- * TRUE if it has changed, FALSE otherwise.
- *
- */
-
- {
- unsigned int height ;
- unsigned int lr ;
- static unsigned int prev_height = 1 ;
- static unsigned int prev_width = 1 ;
- unsigned int result ;
- t_state_block state_block ;
- unsigned int width ;
-
- WIMP_GetWindowState (window_handle, &state_block) ;
- width = state_block.open_block.visible_area.max.x -
- state_block.open_block.visible_area.min.x ;
- height = state_block.open_block.visible_area.max.y -
- state_block.open_block.visible_area.min.y ;
- if (width > height)
- {
- lr = height ;
- }
- else
- {
- lr = width ;
- }
- lr >>= 1 ;
- lr -= (lr >> 4) ;
- *radius = lr ;
- result = ((height != prev_height) ||
- (width != prev_width)) ;
- prev_height = height ;
- prev_width = width ;
- return (result) ;
- }
-
-
- static void draw_clock (
- t_redraw_block *redraw_block)
-
- /*
- * Function :
- * Redraw the clock.
- *
- * Parameters :
- * redraw_block Tells us where the window is.
- *
- * Returns :
- * None.
- *
- */
-
- {
- int centrex ;
- int centrey ;
- int i ;
- int t ;
-
- centrex = (redraw_block->visible_area.min.x + redraw_block->visible_area.max.x) / 2 ;
- centrey = (redraw_block->visible_area.min.y + redraw_block->visible_area.max.y) / 2 ;
- gcol (0, 7) ;
- if (radius > 150)
- {
- t = radius - (radius >> 5) - 8 ;
- for (i = 0; i < 60; i++)
- {
- VDU_Plot (69,
- centrex + times_sin (t, i),
- centrey + times_cos (t, i)) ;
- }
- }
- if (radius > 50)
- {
- gcol (0, 8) ;
- t = radius - (radius >> 4) ;
- for (i = 0; i < 60; i+= 5)
- {
- VDU_Plot (4,
- centrex + times_sin (t, i) - (radius >> 5),
- centrey + times_cos (t, i) - (radius >> 5)) ;
- VDU_Plot (97,
- radius >> 4,
- radius >> 4) ;
- }
- gcol (0, 7) ;
- }
- VDU_Plot (4, centrex, centrey) ;
- VDU_Plot (145, radius, 0) ;
- /*
- * And now the hands.
- */
- gcol (3, 3) ;
- draw_hand (hour * 5 + (minute / 12),
- centrex,
- centrey,
- radius - (radius >> 1)) ;
- draw_hand (minute,
- centrex,
- centrey,
- radius - (radius >> 2)) ;
- gcol (3, 11) ;
- draw_sweep_hand (second,
- centrex,
- centrey,
- radius) ;
- gcol (0, 11) ;
- VDU_Move (centrex, centrey) ;
- VDU_Plot (153, 0, radius >> 4) ;
- }
-
-
- static void draw_hand (
- unsigned int angle,
- int centrex,
- int centrey,
- unsigned int length)
-
- /*
- * Function :
- * Draw a single hand.
- *
- * Parameters :
- * angle The angle of the hand - 0 to 59.
- * centrex X co-ordinate of the clock centre.
- * centrey Y co-ordinate of the clock centre.
- * length Length of the hand.
- *
- * Returns :
- * None.
- *
- */
-
- {
- int t ;
-
- t = length >> 1 ;
- VDU_Move (centrex + times_sin (t, angle + 1),
- centrey + times_cos (t, angle + 1)) ;
- VDU_Move (centrex, centrey) ;
- VDU_Plot (117,
- centrex + times_sin (t, angle + 59),
- centrey + times_cos (t, angle + 59)) ;
- }
-
-
- static void draw_sweep_hand (
- unsigned int angle,
- int centrex,
- int centrey,
- unsigned int length)
-
- /*
- * Function :
- * Draw the sweep hand.
- *
- * Parameters :
- * angle The angle of the hand - 0 to 59.
- * centrex X co-ordinate of the clock centre.
- * centrey Y co-ordinate of the clock centre.
- * length Length of the hand.
- *
- * Returns :
- * None.
- *
- */
-
- {
- VDU_Move (centrex, centrey) ;
- VDU_Plot (64,
- times_sin (length >> 4, angle),
- times_cos (length >> 4, angle)) ;
- VDU_Plot (1,
- times_sin (length - (length >> 4), angle),
- times_cos (length - (length >> 4), angle)) ;
- }
-
-
- static void event_handler (
- t_poll_block *poll_block)
-
- /*
- * Function :
- * Handle wimp events.
- *
- * Parameters :
- * poll_block Pointer to event block.
- *
- * Returns :
- * None.
- *
- */
-
- {
- unsigned int more ;
- t_redraw_block redraw_block ;
-
- switch (poll_block->event_type)
- {
- case ET_RedrawRequest :
- redraw_block.handle = poll_block->data.ob.window_handle ;
- WIMP_RedrawWindow (&redraw_block,
- &more) ;
- while (more)
- {
- draw_clock (&redraw_block) ;
- WIMP_GetRectangle (&redraw_block,
- &more) ;
- }
- break ;
-
- case ET_OpenRequest :
- poll_block->data.ob.scroll_offset.y = 0 ;
- WIMP_OpenWindow (&(poll_block->data.ob)) ;
- if (calc_radius (poll_block->data.ob.window_handle,
- &radius))
- {
- /*
- * Effective size has changed.
- */
- redraw_block.handle = -1 ;
- redraw_block.visible_area = poll_block->data.ob.visible_area ;
- WIMP_ForceRedraw (&redraw_block) ;
- }
- break ;
-
- case ET_CloseRequest :
- WA_WindUp () ;
-
- }
- }
-
-
- static void gcol (
- unsigned int m,
- unsigned int c)
-
- /*
- * Function :
- * Not quite sure.
- *
- * Parameters :
- * m
- * c
- *
- * Returns :
- * None.
- *
- */
-
- {
- unsigned int c1 ;
- t_colour colour ;
- unsigned int i ;
- unsigned int t1 ;
-
- if ((m == 3) &&
- (bpp == 8))
- {
- c1 = (palette.sc [c].bytes.gcol) >> 2 ;
- t1 = palette.sc [c].bytes.gcol & 0x03 ;
- VDU_Gcol (3, c1 ^ colour0) ;
- VDU (23) ;
- VDU (17) ;
- VDU (2) ;
- VDU (t1 ^ tint0) ;
- for (i = 0; i < 6; i++)
- {
- VDU (0) ;
- }
- }
- else
- {
- colour.wimp_colour = c ;
- colour.gcol_action = m ;
- colour.foreback = 0 ;
- WIMP_SetColour (colour) ;
- }
- }
-
-
- static void message_handler (
- t_poll_block *poll_block)
-
- /*
- * Function :
- * Handle messages.
- *
- * Parameters :
- * poll_block Pointer to event block.
- *
- * Returns :
- * None.
- *
- */
-
- {
- if ((poll_block->data.mb.action == Message_PaletteChange) ||
- (poll_block->data.mb.action == Message_ModeChange))
- {
- reset_palette () ;
- }
- }
-
-
- static unsigned int pop_up_clock (void)
-
- /*
- * Function :
- * Make the clock appear.
- *
- * Parameters :
- * None.
- *
- * Returns :
- * TRUE for success, FALSE for failure.
- *
- */
-
- {
- const _kernel_oserror *error_ptr ;
- unsigned int height ;
- t_mouse_block pointer_state ;
- t_state_block state_block ;
- unsigned int width ;
-
- error_ptr = WIMP_GetWindowState (window_handle,
- &state_block) ;
- if (error_ptr == NULL)
- {
- /*
- * Where is the mouse?
- */
- error_ptr = WIMP_GetPointerInfo (&pointer_state) ;
- if (error_ptr == NULL)
- {
- /*
- * Adjust the window to appear just below the mouse.
- * The Wimp will adjust it if this would make it appear off
- * the screen.
- */
- width = state_block.open_block.visible_area.max.x -
- state_block.open_block.visible_area.min.x ;
- height = state_block.open_block.visible_area.max.y -
- state_block.open_block.visible_area.min.y ;
- state_block.open_block.visible_area.min.x = pointer_state.x - (width / 2) ;
- state_block.open_block.visible_area.max.x = pointer_state.x + (width / 2) ;
- state_block.open_block.visible_area.max.y = pointer_state.y - 64 ;
- state_block.open_block.visible_area.min.y =
- state_block.open_block.visible_area.max.y - height ;
- error_ptr = WIMP_OpenWindow (&(state_block.open_block)) ;
- }
- }
- report_error (error_ptr) ;
- return (error_ptr == NULL) ;
- }
-
-
- static void read_time (
- unsigned int *hour,
- unsigned int *minute,
- unsigned int *second)
-
- /*
- * Function :
- * Read the current date and time (12 hour clock).
- *
- * Parameters :
- * hour Pointer to location to store the hour.
- * minute Pointer to location to store the minute.
- * second Pointer to location to store the second.
- *
- * Returns :
- * None.
- *
- */
-
- {
- struct tm *lt ;
- time_t t ;
-
- time (&t) ;
- lt = localtime (&t) ;
- *second = lt->tm_sec ;
- *minute = lt->tm_min ;
- *hour = (lt->tm_hour % 12) ;
- }
-
-
- static void report_error (
- const _kernel_oserror *error_ptr)
-
- /*
- * Function :
- * Report error if any.
- *
- * Parameters :
- * error_ptr Pointer to error block, or NULL.
- *
- * Returns :
- * None.
- *
- */
-
- {
- t_error_flags error_flags ;
- unsigned int result ;
-
- if (error_ptr != NULL)
- {
- error_flags.value = 0 ;
- error_flags.m.ok = TRUE ;
- WIMP_ReportError (error_ptr, error_flags, WA_resource_dir, &result) ;
- }
- }
-
-
- static void reset_palette (void)
-
- /*
- * Function :
- * Read palette variables.
- *
- * Parameters :
- * None.
- *
- * Returns :
- * None.
- *
- */
-
- {
- _kernel_swi_regs registers ;
-
- registers.r [0] = -1 ;
- registers.r [1] = Log2BPP ;
- _kernel_swi (OS_ReadModeVariable,
- ®isters,
- ®isters) ;
- bpp = 1 << registers.r [2] ;
- WIMP_ReadPalette (&palette) ;
- colour0 = palette.sc [0].bytes.gcol >> 2 ;
- tint0 = palette.sc [0].bytes.gcol & 0x03 ;
- }
-
-
- static void tick_handler (
- void *reference)
-
- /*
- * Function :
- * Handle a timer event.
- *
- * Parameters :
- * reference Ignored.
- *
- * Returns :
- * None.
- *
- */
-
- {
- int centrex ;
- int centrey ;
- unsigned int do_hour ;
- unsigned int do_minute ;
- unsigned int do_second ;
- const _kernel_oserror *error_ptr ;
- unsigned int more ;
- unsigned int previous_hour ;
- unsigned int previous_minute ;
- unsigned int previous_second ;
- t_redraw_block redraw_block ;
- t_state_block state_block ;
-
- reference = reference ;
-
- previous_hour = hour ;
- previous_minute = minute ;
- previous_second = second ;
- read_time (&hour, &minute, &second) ;
- if ((hour != previous_hour) ||
- (minute != previous_minute) ||
- (second != previous_second))
- {
- /*
- * Update required.
- */
- error_ptr = WIMP_GetWindowState (window_handle,
- &state_block) ;
- if (error_ptr == NULL)
- {
- redraw_block.handle = window_handle ;
- redraw_block.visible_area.min.x = 0 ;
- redraw_block.visible_area.max.x = 1280 ;
- redraw_block.visible_area.max.y = 0 ;
- redraw_block.visible_area.min.y = -1024 ;
- error_ptr = WIMP_UpdateWindow (&redraw_block, &more) ;
- if (error_ptr == NULL)
- {
- while (more)
- {
- /*
- * Redraw the clock. First remove old hands as
- * necessary. Then draw new ones.
- */
- centrex = (redraw_block.visible_area.min.x + redraw_block.visible_area.max.x) / 2 ;
- centrey = (redraw_block.visible_area.min.y + redraw_block.visible_area.max.y) / 2 ;
- gcol (3, 3) ;
- do_hour = ((hour != previous_hour) ||
- ((minute / 12) != (previous_minute / 12))) ;
- do_minute = (minute != previous_minute) ;
- do_second = (second != previous_second) ;
- if (do_hour)
- {
- draw_hand (previous_hour * 5 + (previous_minute / 12),
- centrex,
- centrey,
- radius - (radius >> 1)) ;
- }
- if (do_minute)
- {
- draw_hand (previous_minute,
- centrex,
- centrey,
- radius - (radius >> 2)) ;
- }
- gcol (3, 11) ;
- if (do_second)
- {
- draw_sweep_hand (previous_second,
- centrex,
- centrey,
- radius) ;
- }
- gcol (3, 3) ;
- if (do_hour)
- {
- draw_hand (hour * 5 + (minute / 12),
- centrex,
- centrey,
- radius - (radius >> 1)) ;
- }
- if (do_minute)
- {
- draw_hand (minute,
- centrex,
- centrey,
- radius - (radius >> 2)) ;
- }
- gcol (3, 11) ;
- if (do_second)
- {
- draw_sweep_hand (second,
- centrex,
- centrey,
- radius) ;
- }
- gcol (0, 11) ;
- VDU_Move (centrex, centrey) ;
- VDU_Plot (153, 0, radius >> 4) ;
- WIMP_GetRectangle (&redraw_block, &more) ;
- }
- }
- }
- report_error (error_ptr) ;
- }
- }
-
-
- static int times_cos (
- int multiplier,
- int angle)
-
- /*
- * Function :
- * Multiply by a cos.
- *
- * Parameters :
- * multiplier Number to multiply.
- * angle Angle to look up.
- *
- * Returns :
- * Multiplied value.
- *
- */
-
- {
- return (times_sin (multiplier, angle + 15)) ;
- }
-
-
- static int times_sin (
- int multiplier,
- int angle)
-
- /*
- * Function :
- * Multiply an integer by the indicated sin value.
- * Angle will be considered mod 60.
- *
- * Parameters :
- * multiplier Number to multiply.
- * angle Angle to look up.
- *
- * Returns :
- * Multiplied value.
- *
- */
-
- {
- unsigned int invert_sign ;
- int result ;
-
- angle = angle % 60 ;
- /*
- * 0 to 15 can be addressed directly. Others require adjustment.
- */
- if (angle >= 30)
- {
- angle-= 30 ;
- invert_sign = TRUE ;
- }
- else
- {
- invert_sign = FALSE ;
- }
- if (angle > 15)
- {
- angle = 30 - angle ;
- }
- result = (multiplier * ratios [angle][0]) / ratios [angle][1] ;
- if (invert_sign)
- {
- result = (-result) ;
- }
- return (result) ;
- }
-