/* $Id: clock.c,v 10.1 92/10/06 22:58:09 ca Exp $ */ #include #include #include "sim.h" #include "simx.h" #include "event.h" double cos(), sin(); /* These routines return doubles. */ /* This file contains the code for creating, destroying, painting, and updating the clock window. */ #define Y_CLOCK 0 #define X_CLOCK 0 #define CLOCK_WIDTH 120 #define CLOCK_HEIGHT 147 #define DIGITAL_HEIGHT 27 #define CLOCK_USECS_PER_TICK 1000 /* 10 msec per tick */ #define R1 8 #define R2 40 #define R3 49 #define R4 53 #define R5 58 #define R6 25 #define ERASE (int) 0 #define DRAW (int) 1 /* Tables of points for the hands--eliminates calls to sin() and cos() */ static XPoint bigp[60][4]; static XPoint littlep[60][4]; static int minutes = 0; /* Time currently displayed on long hand*/ static int hours = 0; /* Time currently displayed on short hand. */ static tick_t currenttime = 0; /* Current ticks */ /* This routine creates a window for the clock. It does not paint the clock. */ static char time_string[40]; Status pop_clock() { int i; double angle; /* Create clock window and map it */ the_environment.clock_window = XCreateSimpleWindow(the_environment.the_display, the_environment.back_window, the_environment.width - CLOCK_WIDTH - the_environment.border_width, Y_CLOCK, CLOCK_WIDTH, CLOCK_HEIGHT, the_environment.border_width, the_environment.fore_color, the_environment.clock_color); XSelectInput(the_environment.the_display, the_environment.clock_window, ExposureMask); XMapWindow(the_environment.the_display, the_environment.clock_window); /***************************************** "Compile" values for all possible hand positions */ /* To find the angle of the hand, multiply the time by 6 and add 90 to get the angle in degrees. Then multiply by pi/180 to get radians. Setup of vertices ^ <-- POINTS 0 and 3. / \ / \ / \ | | / \ | | / C \ POINT 1--> |____________| <-- POINT 2 C = Center of clock Distance from points 1 and 2 to C is R1 Distance from points 0 and 3 is R2 or R6 Points 0 and 3 are actually the same point. */ /* Minute hand */ for (i = 0; i < 60; i++) { angle = ((double) (((((double) i) * -6.0) + 450.0) * 0.01745329)); /* 0 and 3*/ bigp[i][0].x = bigp[i][3].x = (short) ((R2 * cos(angle)) + (CLOCK_WIDTH / 2)); bigp[i][0].y = bigp[i][3].y = (short) (((CLOCK_HEIGHT- DIGITAL_HEIGHT) / 2) - (R2 * sin(angle))); /* 1*/ bigp[i][1].x = (short) ((R1 * cos(2.35619 + angle)) + (CLOCK_WIDTH / 2)); bigp[i][1].y = (short) (((CLOCK_HEIGHT- DIGITAL_HEIGHT) / 2) - (R1 * sin(2.35619 + angle))); /*2*/ bigp[i][2].x = (short) ((R1 * cos(3.92699 + angle)) + (CLOCK_WIDTH / 2)); bigp[i][2].y = (short) (((CLOCK_HEIGHT - DIGITAL_HEIGHT) / 2) - (R1 * sin(3.92699 + angle))); /*** Hour hand */ /* 0 and 3*/ littlep[i][0].x = littlep[i][3].x = (short) ((R6 * cos(angle)) + (CLOCK_WIDTH / 2)); littlep[i][0].y = littlep[i][3].y = (short) (((CLOCK_HEIGHT - DIGITAL_HEIGHT) / 2) - (R6 * sin(angle))); /* 1*/ littlep[i][1].x = (short) ((R1 * cos(2.35619 + angle)) + (CLOCK_WIDTH / 2)); littlep[i][1].y = (short) (((CLOCK_HEIGHT - DIGITAL_HEIGHT) / 2) - (R1 * sin(2.35619 + angle))); /*2*/ littlep[i][2].x = (short) ((R1 * cos(3.92699 + angle)) + (CLOCK_WIDTH / 2)); littlep[i][2].y = (short) (((CLOCK_HEIGHT - DIGITAL_HEIGHT) / 2) - (R1 * sin(3.92699 + angle))); } /* Return status */ return (TRUE); } /* This routine destroys the clock window */ unpop_clock() { XDestroyWindow(the_environment.the_display, the_environment.clock_window); the_environment.clock_window = (int) NULL; XFlush(the_environment.the_display); } /* This routine clears the clock face, draws the lines ( which I will call notches from here on) around the edges,and draws the hand at the correct time. It also draws a line near the bottom and displays the exact time.*/ paint_clock() { double cosangle, sinangle; /* cosine and sine of angles around face */ int counter; /* goes from 0 to 59, represents the 60 notches */ int x1, y1, x2, y2; /* variables for x and y */ /* Never need to clear the window. */ /* XClearWindow(the_environment.the_display, the_environment.clock_window); */ /* loop through all 60 notches */ for(counter = 0; counter != 60; ++counter) { /* To get correct units for the angles, multiply counter by 6 and then by pi/180 */ cosangle = cos( ((double) counter) * 6.0 * 0.01745329); sinangle = sin( ((double) counter) * 6.0 * 0.01745329); /* Point 1 is R4 or R3 away from the center, point 2 is R5 away from center. */ if (counter % 5 == 0) /* draw a longer line if at a 1/12 notch */ { x1 = (int) ((R3 * cosangle) + (CLOCK_WIDTH / 2)); y1 = (int) (((CLOCK_HEIGHT - DIGITAL_HEIGHT) / 2) - (R3 * sinangle)); } else { x1 = (int) ((R4 * cosangle) + (CLOCK_WIDTH/2)); y1 = (int) (((CLOCK_HEIGHT - DIGITAL_HEIGHT)/2) - (R4 * sinangle)); } x2 = (int) ((R5 * cosangle) + (CLOCK_WIDTH/2)); y2 = (int) (((CLOCK_HEIGHT - DIGITAL_HEIGHT)/2) - (R5 * sinangle)); /* Draw line from point 1 to point 2. */ XDrawLine(the_environment.the_display, the_environment.clock_window, the_environment.the_gc, x1, y1, x2, y2); } /*draw the hand at time ev_now in black */ minutes = (ev_now() / USECS_TO_TICKS(CLOCK_USECS_PER_TICK)) % 60; hours = (ev_now() / (60 * USECS_TO_TICKS(CLOCK_USECS_PER_TICK))) % 60; currenttime = ev_now(); draw_hands(DRAW); /* Draw a line at the bottom of the digital clock. */ XDrawLine(the_environment.the_display, the_environment.clock_window, the_environment.the_gc, 0, (CLOCK_HEIGHT - DIGITAL_HEIGHT), CLOCK_WIDTH, (CLOCK_HEIGHT - DIGITAL_HEIGHT)); draw_digits(); } /* This routine checks to see if the time has changed, if it has, it erases the old hands and draws new ones. */ update_clock() { /* Get present time from ev_now */ if (the_environment.iconified == FALSE) { register int constant = USECS_TO_TICKS(CLOCK_USECS_PER_TICK); register tick_t newtime = ev_now(); register int newminutes = (newtime / constant) % 60; register int newhours = (newtime / (60 * constant)) % 60; /* Check to see if time has changed */ if ((minutes != newminutes) || (hours != newhours)) { /* Erase old hand */ draw_hands(ERASE); /* Reset time */ minutes = newminutes; hours = newhours; /* Draw new hand */ draw_hands(DRAW); } if (currenttime != newtime) { currenttime = newtime; draw_digits(); } } else { update_icon_clock(); } } /* This routine accepts a time and a color. It then draws a clock hand in the clock window with that color at that time. */ draw_hands(flag) int flag; /* whether to erase or draw a line */ { if (flag == ERASE) { /* Draw minute hand */ XDrawLines(the_environment.the_display, the_environment.clock_window, the_environment.clock_erase_gc, bigp[minutes], 4, CoordModeOrigin); /* Draw hour hand */ XDrawLines(the_environment.the_display, the_environment.clock_window, the_environment.clock_erase_gc, littlep[hours], 4, CoordModeOrigin); } else { /* Draw minute hand */ XDrawLines(the_environment.the_display, the_environment.clock_window, the_environment.clock_draw_gc, bigp[minutes], 4, CoordModeOrigin); /* Draw hour hand */ XDrawLines(the_environment.the_display, the_environment.clock_window, the_environment.clock_draw_gc, littlep[hours], 4, CoordModeOrigin); } } /* Draw the digital clock */ draw_digits() { sprintf(time_string, "%.3f msecs", ((double) TICKS_TO_USECS(currenttime)) / 1000.0); XDrawImageString(the_environment.the_display, the_environment.clock_window, the_environment.clock_draw_gc, 7, (CLOCK_HEIGHT - 7), time_string, strlen(time_string)); } update_icon_clock() { static tick_t oldtime = 0; register tick_t newtime = TICKS_TO_USECS(ev_now()) / 1000; if (oldtime != newtime) { oldtime = newtime; draw_icon_clock(newtime); } } draw_icon_clock(newtime) tick_t newtime; { sprintf(time_string, "MaRS: %d", newtime); XDrawImageString(the_environment.the_display, the_environment.icon_window, the_environment.clock_draw_gc, 5, 20, time_string, strlen(time_string)); }