dinput: Remove redundant declaration.
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 #include "config.h"
27 #include "wine/port.h"
28
29 #include <math.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include "windows.h"
33 #include "winclock.h"
34
35 #define Black  RGB(0,0,0)
36 #define Gray   RGB(128,128,128)
37 #define LtGray RGB(192,192,192)
38 #define White  RGB(255,255,255)
39
40 static const COLORREF FaceColor = LtGray;
41 static const COLORREF HandColor = White;
42 static const COLORREF TickColor = White;
43 static const COLORREF ShadowColor = Black;
44 static const COLORREF BackgroundColor = LtGray;
45
46 static const int SHADOW_DEPTH = 2;
47  
48 typedef struct
49 {
50     POINT Start;
51     POINT End;
52 } HandData;
53
54 HandData HourHand, MinuteHand, SecondHand;
55
56 static void DrawTicks(HDC dc, const POINT* centre, int radius)
57 {
58     int t;
59
60     /* Minute divisions */
61     if (radius>64)
62         for(t=0; t<60; t++) {
63             MoveToEx(dc,
64                      centre->x + sin(t*M_PI/30)*0.9*radius,
65                      centre->y - cos(t*M_PI/30)*0.9*radius,
66                      NULL);
67             LineTo(dc,
68                    centre->x + sin(t*M_PI/30)*0.89*radius,
69                    centre->y - cos(t*M_PI/30)*0.89*radius);
70         }
71
72     /* Hour divisions */
73     for(t=0; t<12; t++) {
74
75         MoveToEx(dc,
76                  centre->x + sin(t*M_PI/6)*0.9*radius,
77                  centre->y - cos(t*M_PI/6)*0.9*radius,
78                  NULL);
79         LineTo(dc,
80                centre->x + sin(t*M_PI/6)*0.8*radius,
81                centre->y - cos(t*M_PI/6)*0.8*radius);
82     }
83 }
84
85 static void DrawFace(HDC dc, const POINT* centre, int radius, int border)
86 {
87     /* Ticks */
88     SelectObject(dc, CreatePen(PS_SOLID, 2, ShadowColor));
89     OffsetWindowOrgEx(dc, -SHADOW_DEPTH, -SHADOW_DEPTH, NULL);
90     DrawTicks(dc, centre, radius);
91     DeleteObject(SelectObject(dc, CreatePen(PS_SOLID, 2, TickColor)));
92     OffsetWindowOrgEx(dc, SHADOW_DEPTH, SHADOW_DEPTH, NULL);
93     DrawTicks(dc, centre, radius);
94     if (border)
95     {
96         SelectObject(dc, GetStockObject(NULL_BRUSH));
97         DeleteObject(SelectObject(dc, CreatePen(PS_SOLID, 5, ShadowColor)));
98         Ellipse(dc, centre->x - radius, centre->y - radius, centre->x + radius, centre->y + radius);
99     }
100     DeleteObject(SelectObject(dc, GetStockObject(NULL_PEN)));
101 }
102
103 static void DrawHand(HDC dc,HandData* hand)
104 {
105     MoveToEx(dc, hand->Start.x, hand->Start.y, NULL);
106     LineTo(dc, hand->End.x, hand->End.y);
107 }
108
109 static void DrawHands(HDC dc, BOOL bSeconds)
110 {
111     if (bSeconds) {
112 #if 0
113         SelectObject(dc, CreatePen(PS_SOLID, 1, ShadowColor));
114         OffsetWindowOrgEx(dc, -SHADOW_DEPTH, -SHADOW_DEPTH, NULL);
115         DrawHand(dc, &SecondHand);
116         DeleteObject(SelectObject(dc, CreatePen(PS_SOLID, 1, HandColor)));
117         OffsetWindowOrgEx(dc, SHADOW_DEPTH, SHADOW_DEPTH, NULL);
118 #else
119         SelectObject(dc, CreatePen(PS_SOLID, 1, HandColor));
120 #endif
121         DrawHand(dc, &SecondHand);
122         DeleteObject(SelectObject(dc, GetStockObject(NULL_PEN)));
123     }
124
125     SelectObject(dc, CreatePen(PS_SOLID, 4, ShadowColor));
126
127     OffsetWindowOrgEx(dc, -SHADOW_DEPTH, -SHADOW_DEPTH, NULL);
128     DrawHand(dc, &MinuteHand);
129     DrawHand(dc, &HourHand);
130
131     DeleteObject(SelectObject(dc, CreatePen(PS_SOLID, 4, HandColor)));
132     OffsetWindowOrgEx(dc, SHADOW_DEPTH, SHADOW_DEPTH, NULL);
133     DrawHand(dc, &MinuteHand);
134     DrawHand(dc, &HourHand);
135
136     DeleteObject(SelectObject(dc, GetStockObject(NULL_PEN)));
137 }
138
139 static void PositionHand(const POINT* centre, double length, double angle, HandData* hand)
140 {
141     hand->Start = *centre;
142     hand->End.x = centre->x + sin(angle)*length;
143     hand->End.y = centre->y - cos(angle)*length;
144 }
145
146 static void PositionHands(const POINT* centre, int radius, BOOL bSeconds)
147 {
148     SYSTEMTIME st;
149     double hour, minute, second;
150
151     /* 0 <= hour,minute,second < 2pi */
152     /* Adding the millisecond count makes the second hand move more smoothly */
153
154     GetLocalTime(&st);
155
156     second = st.wSecond + st.wMilliseconds/1000.0;
157     minute = st.wMinute + second/60.0;
158     hour   = st.wHour % 12 + minute/60.0;
159
160     PositionHand(centre, radius * 0.5,  hour/12   * 2*M_PI, &HourHand);
161     PositionHand(centre, radius * 0.65, minute/60 * 2*M_PI, &MinuteHand);
162     if (bSeconds)
163         PositionHand(centre, radius * 0.79, second/60 * 2*M_PI, &SecondHand);  
164 }
165
166 void AnalogClock(HDC dc, int x, int y, BOOL bSeconds, BOOL border)
167 {
168     POINT centre;
169     int radius;
170     
171     radius = min(x, y)/2 - SHADOW_DEPTH;
172     if (radius < 0)
173         return;
174
175     centre.x = x/2;
176     centre.y = y/2;
177
178     DrawFace(dc, &centre, radius, border);
179
180     PositionHands(&centre, radius, bSeconds);
181     DrawHands(dc, bSeconds);
182 }
183
184
185 HFONT SizeFont(HDC dc, int x, int y, BOOL bSeconds, const LOGFONT* font)
186 {
187     SIZE extent;
188     LOGFONT lf;
189     double xscale, yscale;
190     HFONT oldFont, newFont;
191     CHAR szTime[255];
192     int chars;
193
194     chars = GetTimeFormat(LOCALE_USER_DEFAULT, bSeconds ? 0 : TIME_NOSECONDS, NULL,
195                           NULL, szTime, sizeof (szTime));
196     if (!chars)
197         return 0;
198
199     --chars;
200
201     lf = *font;
202     lf.lfHeight = -20;
203
204     x -= 2 * SHADOW_DEPTH;
205     y -= 2 * SHADOW_DEPTH;
206
207     oldFont = SelectObject(dc, CreateFontIndirect(&lf));
208     GetTextExtentPoint(dc, szTime, chars, &extent);
209     DeleteObject(SelectObject(dc, oldFont));
210
211     xscale = (double)x/extent.cx;
212     yscale = (double)y/extent.cy;
213     lf.lfHeight *= min(xscale, yscale);    
214     newFont = CreateFontIndirect(&lf);
215
216     return newFont;
217 }
218
219 void DigitalClock(HDC dc, int x, int y, BOOL bSeconds, HFONT font)
220 {
221     SIZE extent;
222     HFONT oldFont;
223     CHAR szTime[255];
224     int chars;
225
226     chars = GetTimeFormat(LOCALE_USER_DEFAULT, bSeconds ? 0 : TIME_NOSECONDS, NULL,
227                   NULL, szTime, sizeof (szTime));
228     if (!chars)
229         return;
230     --chars;
231
232     oldFont = SelectObject(dc, font);
233     GetTextExtentPoint(dc, szTime, chars, &extent);
234
235     SetBkColor(dc, BackgroundColor);
236     SetTextColor(dc, ShadowColor);
237     TextOut(dc, (x - extent.cx)/2 + SHADOW_DEPTH, (y - extent.cy)/2 + SHADOW_DEPTH,
238             szTime, chars);
239     SetBkMode(dc, TRANSPARENT);
240
241     SetTextColor(dc, HandColor);
242     TextOut(dc, (x - extent.cx)/2, (y - extent.cy)/2, szTime, chars);
243
244     SelectObject(dc, oldFont);
245 }