Avoid deadlock in VGA_DoSetMode.
[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  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26
27 #include <math.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include "winclock.h"
31 #include "windows.h"
32 #include "main.h"
33 #include "winnls.h"
34
35 COLORREF FaceColor = RGB(192,192,192);
36 COLORREF HandColor = RGB(0,0,0);
37 COLORREF EtchColor = RGB(0,0,0);
38
39 float Pi=3.1415926;
40
41 int nLastSecond = 60;
42
43 HandData OldSecond,OldHour,OldMinute;
44
45 int MiddleX(void) {
46   int X, diff;
47
48   X    = (Globals.MaxX/2);  
49   diff = (Globals.MaxX-Globals.MaxY);
50   if (diff>0) { X = (X-(diff/2)); }
51   return X;
52 }
53
54 int MiddleY(void) {
55   int Y, diff;
56   
57   Y    = (Globals.MaxY/2);
58   diff = (Globals.MaxX-Globals.MaxY);
59   if (diff<0) { Y = Y+(diff/2); }
60   return Y;
61 }
62
63 void DrawFace(HDC dc)
64 {
65   int MidX, MidY, t, DiffX, DiffY;
66   
67   MidX = MiddleX();
68   MidY = MiddleY();
69   DiffX = (Globals.MaxX-MidX*2)/2;
70   DiffY = (Globals.MaxY-MidY*2)/2;
71
72   SelectObject(dc,CreateSolidBrush(FaceColor));
73   SelectObject(dc,CreatePen(PS_SOLID,1,EtchColor));
74   Ellipse(dc,DiffX,DiffY,2*MidX+DiffX,2*MidY+DiffY);
75
76   for(t=0; t<12; t++)
77   {
78     MoveToEx(dc,(MidX+DiffX)+sin(t*Pi/6)*0.9*MidX,(MidY+DiffY)-cos(t*Pi/6)*0.9*MidY,NULL);
79     LineTo(dc,(MidY+DiffX)+sin(t*Pi/6)*0.8*MidX,(MidY+DiffY)-cos(t*Pi/6)*0.8*MidY);
80   }
81   if(Globals.MaxX>64 && Globals.MaxY>64)
82     for(t=0; t<60; t++)
83       SetPixel(dc,(MidX+DiffX)+sin(t*Pi/30)*0.9*MidX,(MidY+DiffY)-cos(t*Pi/30)*0.9*MidY
84                ,EtchColor);
85   DeleteObject(SelectObject(dc,GetStockObject(NULL_BRUSH)));
86   DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
87   memset(&OldSecond,0,sizeof(OldSecond));
88   memset(&OldMinute,0,sizeof(OldMinute));
89   memset(&OldHour,0,sizeof(OldHour));
90 }
91
92 void DrawHourHand(HDC dc)
93 {
94   if (OldHour.DontRedraw) return;
95   MoveToEx(dc, OldHour.StartX, OldHour.StartY, NULL);
96   LineTo(dc, OldHour.EndX, OldHour.EndY);
97 }
98
99 void DrawMinuteHand(HDC dc)
100 {
101   if (OldMinute.DontRedraw) return;
102   MoveToEx(dc, OldMinute.StartX, OldMinute.StartY, NULL);
103   LineTo(dc, OldMinute.EndX, OldMinute.EndY);
104 }
105
106 void DrawSecondHand(HDC dc)
107 {
108     if (OldSecond.DontRedraw) return;
109     MoveToEx(dc, OldSecond.StartX, OldSecond.StartY, NULL);
110     LineTo(dc, OldSecond.EndX, OldSecond.EndY);
111 }
112
113 BOOL UpdateHourHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
114 {
115   int Sx, Sy, Ex, Ey;
116   BOOL rv;
117
118   rv = FALSE;
119   Sx = MidX; Sy = MidY;
120   Ex = MidX+sin(Pos*Pi/6000)*XExt;
121   Ey = MidY-cos(Pos*Pi/6000)*YExt;
122   rv = ( Sx!=OldHour.StartX || Ex!=OldHour.EndX || 
123          Sy!=OldHour.StartY || Ey!=OldHour.EndY );
124   if (Globals.bAnalog && rv)DrawHourHand(dc);
125   OldHour.StartX = Sx; OldHour.EndX = Ex;
126   OldHour.StartY = Sy; OldHour.EndY = Ey;
127   OldHour.DontRedraw=FALSE;
128   return rv;
129 }
130
131 BOOL UpdateMinuteHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
132 {
133   int Sx, Sy, Ex, Ey;
134   BOOL rv;
135
136   rv = FALSE;
137   Sx = MidX; Sy = MidY;
138   Ex = MidX+sin(Pos*Pi/30000)*XExt;
139   Ey = MidY-cos(Pos*Pi/30000)*YExt;
140   rv = ( Sx!=OldMinute.StartX || Ex!=OldMinute.EndX ||
141          Sy!=OldMinute.StartY || Ey!=OldMinute.EndY );
142   if (Globals.bAnalog && rv)DrawMinuteHand(dc);
143   OldMinute.StartX = Sx; OldMinute.EndX = Ex;
144   OldMinute.StartY = Sy; OldMinute.EndY = Ey;
145   OldMinute.DontRedraw=FALSE;
146   return rv;
147 }
148
149 BOOL UpdateSecondHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos)
150 {
151   int Sx, Sy, Ex, Ey;
152   BOOL rv;
153
154   rv = FALSE;
155   
156   if (Globals.bSeconds) {
157     Sx = MidX; Sy = MidY;
158     Ex = MidX+sin(Pos*Pi/3000)*XExt;
159     Ey = MidY-cos(Pos*Pi/3000)*YExt;
160     rv = ( Sx!=OldSecond.StartX || Ex!=OldSecond.EndX ||
161            Sy!=OldSecond.StartY || Ey!=OldSecond.EndY );
162     if (Globals.bAnalog && rv) DrawSecondHand(dc);
163     OldSecond.StartX = Sx; OldSecond.EndX = Ex;
164     OldSecond.StartY = Sy; OldSecond.EndY = Ey;
165     OldSecond.DontRedraw=FALSE;
166   }
167   
168   return rv;
169 }
170
171 void DigitalClock(HDC dc) {
172
173   CHAR szTime[MAX_STRING_LEN];
174   LPSTR time = szTime;
175   static short xChar, yChar;
176   TEXTMETRIC tm;
177   
178   SYSTEMTIME st;
179   LPSYSTEMTIME lpst = &st;
180   
181   GetLocalTime(&st);
182   GetTimeFormat(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, lpst, NULL, time, 
183                 MAX_STRING_LEN);
184                 
185   SelectObject(dc,CreatePen(PS_SOLID,1,FaceColor));
186   xChar = tm.tmAveCharWidth;
187   yChar = tm.tmHeight;
188   
189   xChar = 100;
190   yChar = 100;
191   TextOut (dc, xChar, yChar, szTime, strlen (szTime)); 
192   DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN)));
193               
194 }
195
196
197
198 void AnalogClock(HDC dc) {
199
200   SYSTEMTIME st;
201   WORD H, M, S, F;
202   int MidX, MidY, DiffX, DiffY;
203   BOOL Redraw;
204
205   GetLocalTime(&st);
206
207   S = st.wSecond;
208   if (nLastSecond==S) { exit; }
209   nLastSecond = S;
210   H = st.wHour;
211   M = st.wMinute;
212   F = st.wMilliseconds / 10;
213   F = F + S*100;
214   M = M*1000+F/6;
215   H = H*1000+M/60;
216   MidX = MiddleX();
217   MidY = MiddleY();
218   DiffX = (Globals.MaxX-MidX*2)/2;
219   DiffY = (Globals.MaxY-MidY*2)/2;
220
221   SelectObject(dc,CreatePen(PS_SOLID,1,FaceColor));
222   Redraw = FALSE;
223   if(UpdateHourHand(dc,MidX+DiffX,MidY+DiffY,MidX*0.5,MidY*0.5,H)) Redraw = TRUE;
224   if(UpdateMinuteHand(dc,MidX+DiffX,MidY+DiffY,MidX*0.65,MidY*0.65,M)) Redraw = TRUE;
225   if(UpdateSecondHand(dc,MidX+DiffX,MidY+DiffY,MidX*0.79,MidY*0.79,F)) Redraw = TRUE;
226
227   DeleteObject(SelectObject(dc,CreatePen(PS_SOLID,1,HandColor)));
228     if(Redraw)
229       {
230         DrawSecondHand(dc);
231         DrawMinuteHand(dc);
232         DrawHourHand(dc);
233       }
234   DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN))); 
235   
236 }
237
238 void Idle(HDC idc)
239 {
240   HDC context;
241
242   if(idc)
243         context=idc;
244   else
245         context=GetDC(Globals.hMainWnd);
246
247   if (!context) return;
248
249   if (Globals.bAnalog)
250   {
251     AnalogClock(context);
252   }
253   else 
254   {
255     DigitalClock(context);
256   }
257   if(!idc) ReleaseDC(Globals.hMainWnd, context);
258 }