Handle ReadIntervalTimeout=MAXDWORD special case a bit better.
[wine] / programs / clock / winclock.c
1 /* 
2  *  Clock (winclock.c)
3  *
4  *  Copyright 1998 by Marcel Baur <mbaur@g26.ethz.ch>
5  *
6  *  This file is based on  rolex.c  by Jim Peterson.
7  *
8  *  I just managed to move the relevant parts into the Clock application
9  *  and made it look like the original Windows one. You can find the original
10  *  rolex.c in the wine /libtest directory.
11  *
12  *  Original file header:
13  *  >
14  *  > rolex.c: Windows clock application for WINE (by Jim Peterson)    
15  *  >                                                                 
16  *  > This is a translation of a Turbo Pascal OWL application I made   
17  *  > once, so it's a little flaky (tons of globals, functions that    
18  *  > could have been in-lined, etc.).  The source code should easily  
19  *  > compile with a standard Win32 C compiler.                        
20  *  >                                                                 
21  *  > To try it out, type 'make rolex'.                               
22  *  >
23  *
24  */
25
26 #include <math.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include "winclock.h"
30 #include "windows.h"
31 #include "main.h"
32 #include "winnls.h"
33
34 COLORREF FaceColor = RGB(192,192,192);
35 COLORREF HandColor = RGB(0,0,0);
36 COLORREF EtchColor = RGB(0,0,0);
37
38 float Pi=3.1415926;
39
40 int nLastSecond = 60;
41
42 HandData OldSecond,OldHour,OldMinute;
43
44 int MiddleX(void) {
45   int X, diff;
46
47   X    = (Globals.MaxX/2);  
48   diff = (Globals.MaxX-Globals.MaxY);
49   if (diff>0) { X = (X-(diff/2)); }
50   return X;
51 }
52
53 int MiddleY(void) {
54   int Y, diff;
55   
56   Y    = (Globals.MaxY/2);
57   diff = (Globals.MaxX-Globals.MaxY);
58   if (diff<0) { Y = Y+(diff/2); }
59   return Y;
60 }
61
62 void DrawFace(HDC dc)
63 {
64   int MidX, MidY, t, DiffX, DiffY;
65   
66   MidX = MiddleX();
67   MidY = MiddleY();
68   DiffX = (Globals.MaxX-MidX*2)/2;
69   DiffY = (Globals.MaxY-MidY*2)/2;
70
71   SelectObject(dc,CreateSolidBrush(FaceColor));
72   SelectObject(dc,CreatePen(PS_SOLID,1,EtchColor));
73   Ellipse(dc,DiffX,DiffY,2*MidX+DiffX,2*MidY+DiffY);
74
75   for(t=0; t<12; t++)
76   {
77     MoveToEx(dc,(MidX+DiffX)+sin(t*Pi/6)*0.9*MidX,(MidY+DiffY)-cos(t*Pi/6)*0.9*MidY,NULL);
78     LineTo(dc,(MidY+DiffX)+sin(t*Pi/6)*0.8*MidX,(MidY+DiffY)-cos(t*Pi/6)*0.8*MidY);
79   }
80   if(Globals.MaxX>64 && Globals.MaxY>64)
81     for(t=0; t<60; t++)
82       SetPixel(dc,(MidX+DiffX)+sin(t*Pi/30)*0.9*MidX,(MidY+DiffY)-cos(t*Pi/30)*0.9*MidY
83                ,EtchColor);
84   DeleteObject(SelectObject(dc,GetStockObject(NULL_BRUSH)));
85   DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
86   memset(&OldSecond,0,sizeof(OldSecond));
87   memset(&OldMinute,0,sizeof(OldMinute));
88   memset(&OldHour,0,sizeof(OldHour));
89 }
90
91 void DrawHourHand(HDC dc)
92 {
93   if (OldHour.DontRedraw) return;
94   MoveToEx(dc, OldHour.StartX, OldHour.StartY, NULL);
95   LineTo(dc, OldHour.EndX, OldHour.EndY);
96 }
97
98 void DrawMinuteHand(HDC dc)
99 {
100   if (OldMinute.DontRedraw) return;
101   MoveToEx(dc, OldMinute.StartX, OldMinute.StartY, NULL);
102   LineTo(dc, OldMinute.EndX, OldMinute.EndY);
103 }
104
105 void DrawSecondHand(HDC dc)
106 {
107     if (OldSecond.DontRedraw) return;
108     MoveToEx(dc, OldSecond.StartX, OldSecond.StartY, NULL);
109     LineTo(dc, OldSecond.EndX, OldSecond.EndY);
110 }
111
112 BOOL UpdateHourHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
113 {
114   int Sx, Sy, Ex, Ey;
115   BOOL rv;
116
117   rv = FALSE;
118   Sx = MidX; Sy = MidY;
119   Ex = MidX+sin(Pos*Pi/6000)*XExt;
120   Ey = MidY-cos(Pos*Pi/6000)*YExt;
121   rv = ( Sx!=OldHour.StartX || Ex!=OldHour.EndX || 
122          Sy!=OldHour.StartY || Ey!=OldHour.EndY );
123   if (Globals.bAnalog && rv)DrawHourHand(dc);
124   OldHour.StartX = Sx; OldHour.EndX = Ex;
125   OldHour.StartY = Sy; OldHour.EndY = Ey;
126   OldHour.DontRedraw=FALSE;
127   return rv;
128 }
129
130 BOOL UpdateMinuteHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
131 {
132   int Sx, Sy, Ex, Ey;
133   BOOL rv;
134
135   rv = FALSE;
136   Sx = MidX; Sy = MidY;
137   Ex = MidX+sin(Pos*Pi/30000)*XExt;
138   Ey = MidY-cos(Pos*Pi/30000)*YExt;
139   rv = ( Sx!=OldMinute.StartX || Ex!=OldMinute.EndX ||
140          Sy!=OldMinute.StartY || Ey!=OldMinute.EndY );
141   if (Globals.bAnalog && rv)DrawMinuteHand(dc);
142   OldMinute.StartX = Sx; OldMinute.EndX = Ex;
143   OldMinute.StartY = Sy; OldMinute.EndY = Ey;
144   OldMinute.DontRedraw=FALSE;
145   return rv;
146 }
147
148 BOOL UpdateSecondHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
149 {
150   int Sx, Sy, Ex, Ey;
151   BOOL rv;
152
153   rv = FALSE;
154   
155   if (Globals.bSeconds) {
156     Sx = MidX; Sy = MidY;
157     Ex = MidX+sin(Pos*Pi/3000)*XExt;
158     Ey = MidY-cos(Pos*Pi/3000)*YExt;
159     rv = ( Sx!=OldSecond.StartX || Ex!=OldSecond.EndX ||
160            Sy!=OldSecond.StartY || Ey!=OldSecond.EndY );
161     if (Globals.bAnalog && rv) DrawSecondHand(dc);
162     OldSecond.StartX = Sx; OldSecond.EndX = Ex;
163     OldSecond.StartY = Sy; OldSecond.EndY = Ey;
164     OldSecond.DontRedraw=FALSE;
165   }
166   
167   return rv;
168 }
169
170 void DigitalClock(HDC dc) {
171
172   CHAR szTime[MAX_STRING_LEN];
173   LPSTR time = szTime;
174   static short xChar, yChar;
175   TEXTMETRIC tm;
176   
177   SYSTEMTIME st;
178   LPSYSTEMTIME lpst = &st;
179   
180   GetLocalTime(&st);
181   GetTimeFormat(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, lpst, NULL, time, 
182                 MAX_STRING_LEN);
183                 
184   SelectObject(dc,CreatePen(PS_SOLID,1,FaceColor));
185   xChar = tm.tmAveCharWidth;
186   yChar = tm.tmHeight;
187   
188   xChar = 100;
189   yChar = 100;
190   TextOut (dc, xChar, yChar, szTime, strlen (szTime)); 
191   DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
192               
193 }
194
195
196
197 void AnalogClock(HDC dc) {
198
199   SYSTEMTIME st;
200   WORD H, M, S, F;
201   int MidX, MidY, DiffX, DiffY;
202   BOOL Redraw;
203
204   GetLocalTime(&st);
205
206   S = st.wSecond;
207   if (nLastSecond==S) { exit; }
208   nLastSecond = S;
209   H = st.wHour;
210   M = st.wMinute;
211   F = st.wMilliseconds / 10;
212   F = F + S*100;
213   M = M*1000+F/6;
214   H = H*1000+M/60;
215   MidX = MiddleX();
216   MidY = MiddleY();
217   DiffX = (Globals.MaxX-MidX*2)/2;
218   DiffY = (Globals.MaxY-MidY*2)/2;
219
220   SelectObject(dc,CreatePen(PS_SOLID,1,FaceColor));
221   Redraw = FALSE;
222   if(UpdateHourHand(dc,MidX+DiffX,MidY+DiffY,MidX*0.5,MidY*0.5,H)) Redraw = TRUE;
223   if(UpdateMinuteHand(dc,MidX+DiffX,MidY+DiffY,MidX*0.65,MidY*0.65,M)) Redraw = TRUE;
224   if(UpdateSecondHand(dc,MidX+DiffX,MidY+DiffY,MidX*0.79,MidY*0.79,F)) Redraw = TRUE;
225
226   DeleteObject(SelectObject(dc,CreatePen(PS_SOLID,1,HandColor)));
227     if(Redraw)
228       {
229         DrawSecondHand(dc);
230         DrawMinuteHand(dc);
231         DrawHourHand(dc);
232       }
233   DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN))); 
234   
235 }
236
237 void Idle(HDC idc)
238 {
239   HDC context;
240
241   if(idc)
242         context=idc;
243   else
244         context=GetDC(Globals.hMainWnd);
245
246   if (!context) return;
247
248   if (Globals.bAnalog)
249   {
250     AnalogClock(context);
251   }
252   else 
253   {
254     DigitalClock(context);
255   }
256   if(!idc) ReleaseDC(Globals.hMainWnd, context);
257 }