winecfg: Remove some superfluous casts.
[wine] / programs / taskmgr / graph.c
1 /*
2  *  ReactOS Task Manager
3  *
4  *  graph.c
5  *
6  *  Copyright (C) 1999 - 2001  Brian Palmer  <brianp@reactos.org>
7  *  Copyright (C) 2008  Vladimir Pankratov
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23     
24 #define WIN32_LEAN_AND_MEAN    /* Exclude rarely-used stuff from Windows headers */
25 #include <windows.h>
26 #include <commctrl.h>
27 #include <stdlib.h>
28 #include <malloc.h>
29 #include <memory.h>
30 #include <stdio.h>
31 #include <winnt.h>
32     
33 #include "wine/unicode.h"
34 #include "taskmgr.h"
35 #include "perfdata.h"
36
37 #define BRIGHT_GREEN    RGB(0, 255, 0)
38 #define DARK_GREEN      RGB(0, 130, 0)
39 #define RED             RGB(255, 0, 0)
40
41
42 WNDPROC             OldGraphWndProc;
43
44 static void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd)
45 {
46     RECT            rcClient;
47     RECT            rcBarLeft;
48     RECT            rcBarRight;
49     WCHAR            Text[256];
50     ULONG            CpuUsage;
51     ULONG            CpuKernelUsage;
52     int                nBars;
53     int                nBarsUsed; 
54 /* Bottom bars that are "used", i.e. are bright green, representing used cpu time */
55     int                nBarsUsedKernel; 
56 /* Bottom bars that are "used", i.e. are bright green, representing used cpu kernel time */
57     int                nBarsFree; 
58 /* Top bars that are "unused", i.e. are dark green, representing free cpu time */
59     int                i;
60
61     static const WCHAR    wszFormatI[] = {'%','d','%','%',0};
62     static const WCHAR    wszFormatII[] = {' ',' ','%','d','%','%',0};
63     static const WCHAR    wszFormatIII[] = {' ','%','d','%','%',0};
64     
65     /*
66      * Get the client area rectangle
67      */
68     GetClientRect(hWnd, &rcClient);
69     
70     /*
71      * Fill it with blackness
72      */
73     FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
74     
75     /*
76      * Get the CPU usage
77      */
78     CpuUsage = PerfDataGetProcessorUsage();
79     CpuKernelUsage = PerfDataGetProcessorSystemUsage();
80
81     /*
82      * Check and see how many digits it will take
83      * so we get the indentation right every time.
84      */
85     if (CpuUsage == 100)
86     {
87         sprintfW(Text, wszFormatI, (int)CpuUsage);
88     }
89     else if (CpuUsage < 10)
90     {
91         sprintfW(Text, wszFormatII, (int)CpuUsage);
92     }
93     else
94     {
95         sprintfW(Text, wszFormatIII, (int)CpuUsage);
96     }
97     
98     /*
99      * Draw the font text onto the graph
100      * The bottom 20 pixels are reserved for the text
101      */
102     Font_DrawText(hDC, Text, ((rcClient.right - rcClient.left) - 32) / 2, rcClient.bottom - 11 - 5);
103
104     /*
105      * Now we have to draw the graph
106      * So first find out how many bars we can fit
107      */
108     nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
109     nBarsUsed = (nBars * CpuUsage) / 100;
110     if ((CpuUsage) && (nBarsUsed == 0))
111     {
112         nBarsUsed = 1;
113     }
114     nBarsFree = nBars - nBarsUsed;
115     if (TaskManagerSettings.ShowKernelTimes)
116     {
117         nBarsUsedKernel = ((nBars * 2) * CpuKernelUsage) / 100;
118         nBarsUsed -= (nBarsUsedKernel / 2);
119     }
120     else
121     {
122         nBarsUsedKernel = 0;
123     }
124
125     /*
126      * Now draw the bar graph
127      */
128     rcBarLeft.left =  ((rcClient.right - rcClient.left) - 33) / 2;
129     rcBarLeft.right =  rcBarLeft.left + 16;
130     rcBarRight.left = rcBarLeft.left + 17;
131     rcBarRight.right = rcBarLeft.right + 17;
132     rcBarLeft.top = rcBarRight.top = 5;
133     rcBarLeft.bottom = rcBarRight.bottom = 7;
134
135     if (nBarsUsed < 0)     nBarsUsed = 0;
136     if (nBarsUsed > nBars) nBarsUsed = nBars;
137
138     if (nBarsFree < 0)     nBarsFree = 0;
139     if (nBarsFree > nBars) nBarsFree = nBars;
140
141     if (nBarsUsedKernel < 0)     nBarsUsedKernel = 0;
142     if (nBarsUsedKernel > nBars) nBarsUsedKernel = nBars;
143
144     /*
145      * Draw the "free" bars
146      */
147     for (i=0; i<nBarsFree; i++)
148     {
149         FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
150         FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
151         
152         rcBarLeft.top += 3;
153         rcBarLeft.bottom += 3;
154         
155         rcBarRight.top += 3;
156         rcBarRight.bottom += 3;
157     }
158     
159     /*
160      * Draw the "used" bars
161      */
162     for (i=0; i<nBarsUsed; i++)
163     {
164         if (nBarsUsed > 5000) nBarsUsed = 5000;
165
166         FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
167         FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
168         
169         rcBarLeft.top += 3;
170         rcBarLeft.bottom += 3;
171         
172         rcBarRight.top += 3;
173         rcBarRight.bottom += 3;
174     }
175     
176     /*
177      * Draw the "used" kernel bars
178      */
179     rcBarLeft.bottom--;
180     rcBarRight.bottom--;
181     if (nBarsUsedKernel && nBarsUsedKernel % 2)
182     {
183         rcBarLeft.top -= 2;
184         rcBarLeft.bottom -= 2;
185         
186         rcBarRight.top -= 2;
187         rcBarRight.bottom -= 2;
188
189         FillSolidRect(hDC, &rcBarLeft, RED);
190         FillSolidRect(hDC, &rcBarRight, RED);
191         
192         rcBarLeft.top += 2;
193         rcBarLeft.bottom += 2;
194         
195         rcBarRight.top += 2;
196         rcBarRight.bottom += 2;
197
198         nBarsUsedKernel--;
199     }
200     for (i=0; i<nBarsUsedKernel; i++)
201     {
202         if (nBarsUsedKernel > 5000) nBarsUsedKernel = 5000;
203
204         FillSolidRect(hDC, &rcBarLeft, RED);
205         FillSolidRect(hDC, &rcBarRight, RED);
206         
207         rcBarLeft.top++;
208         rcBarLeft.bottom++;
209         
210         rcBarRight.top++;
211         rcBarRight.bottom++;
212
213         if (i % 2)
214         {
215             rcBarLeft.top++;
216             rcBarLeft.bottom++;
217             
218             rcBarRight.top++;
219             rcBarRight.bottom++;
220         }
221     }
222 }
223
224 static void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd)
225 {
226     RECT            rcClient;
227     RECT            rcBarLeft;
228     RECT            rcBarRight;
229     WCHAR            Text[256];
230     ULONGLONG        CommitChargeTotal;
231     ULONGLONG        CommitChargeLimit;
232     int                nBars;
233     int                nBarsUsed = 0; 
234 /* Bottom bars that are "used", i.e. are bright green, representing used memory */
235     int                nBarsFree; 
236 /* Top bars that are "unused", i.e. are dark green, representing free memory */
237     int                i;
238
239     static const WCHAR    wszFormat[] = {'%','d','K',0};
240     
241     /*
242      * Get the client area rectangle
243      */
244     GetClientRect(hWnd, &rcClient);
245     
246     /*
247      * Fill it with blackness
248      */
249     FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
250     
251     /*
252      * Get the memory usage
253      */
254     CommitChargeTotal = (ULONGLONG)PerfDataGetCommitChargeTotalK();
255     CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
256
257     sprintfW(Text, wszFormat, (int)CommitChargeTotal);
258     
259     /*
260      * Draw the font text onto the graph
261      * The bottom 20 pixels are reserved for the text
262      */
263     Font_DrawText(hDC, Text, ((rcClient.right - rcClient.left) - (strlenW(Text) * 8)) / 2, rcClient.bottom - 11 - 5);
264
265     /*
266      * Now we have to draw the graph
267      * So first find out how many bars we can fit
268      */
269     nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
270         if (CommitChargeLimit)
271     nBarsUsed = (nBars * (int)((CommitChargeTotal * 100) / CommitChargeLimit)) / 100;
272     nBarsFree = nBars - nBarsUsed;
273
274     if (nBarsUsed < 0)     nBarsUsed = 0;
275     if (nBarsUsed > nBars) nBarsUsed = nBars;
276
277     if (nBarsFree < 0)     nBarsFree = 0;
278     if (nBarsFree > nBars) nBarsFree = nBars;
279
280     /*
281      * Now draw the bar graph
282      */
283     rcBarLeft.left =  ((rcClient.right - rcClient.left) - 33) / 2;
284     rcBarLeft.right =  rcBarLeft.left + 16;
285     rcBarRight.left = rcBarLeft.left + 17;
286     rcBarRight.right = rcBarLeft.right + 17;
287     rcBarLeft.top = rcBarRight.top = 5;
288     rcBarLeft.bottom = rcBarRight.bottom = 7;
289     
290     /*
291      * Draw the "free" bars
292      */
293     for (i=0; i<nBarsFree; i++)
294     {
295         FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
296         FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
297         
298         rcBarLeft.top += 3;
299         rcBarLeft.bottom += 3;
300         
301         rcBarRight.top += 3;
302         rcBarRight.bottom += 3;
303     }
304     
305     /*
306      * Draw the "used" bars
307      */
308     for (i=0; i<nBarsUsed; i++)
309     {
310         FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
311         FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
312         
313         rcBarLeft.top += 3;
314         rcBarLeft.bottom += 3;
315         
316         rcBarRight.top += 3;
317         rcBarRight.bottom += 3;
318     }
319 }
320
321 static void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd)
322 {
323     RECT            rcClient;
324     ULONGLONG        CommitChargeLimit;
325     int                i;
326     static int        offset = 0;
327     
328     if (offset++ >= 10)
329         offset = 0;
330     
331     /*
332      * Get the client area rectangle
333      */
334     GetClientRect(hWnd, &rcClient);
335     
336     /*
337      * Fill it with blackness
338      */
339     FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
340
341     /*
342      * Get the memory usage
343      */
344     CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
345
346     /*
347      * Draw the graph background
348      *
349      * Draw the horizontal bars
350      */
351     for (i=0; i<rcClient.bottom; i++)
352     {
353         if ((i % 11) == 0)
354         {
355             /* FillSolidRect2(hDC, 0, i, rcClient.right, 1, DARK_GREEN);  */
356         }
357     }
358     /*
359      * Draw the vertical bars
360      */
361     for (i=11; i<rcClient.right + offset; i++)
362     {
363         if ((i % 11) == 0)
364         {
365             /* FillSolidRect2(hDC, i - offset, 0, 1, rcClient.bottom, DARK_GREEN);  */
366         }
367     }
368
369     /*
370      * Draw the memory usage
371      */
372     for (i=rcClient.right; i>=0; i--)
373     {
374     }
375 }
376
377 INT_PTR CALLBACK
378 Graph_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
379 {
380     HDC                hdc;
381     PAINTSTRUCT        ps;
382     LONG            WindowId;
383     
384     switch (message)
385     {
386     case WM_ERASEBKGND:
387         return TRUE;
388
389     /*
390      * Filter out mouse  & keyboard messages
391      */
392     /* case WM_APPCOMMAND: */
393     case WM_CAPTURECHANGED:
394     case WM_LBUTTONDBLCLK:
395     case WM_LBUTTONDOWN:
396     case WM_LBUTTONUP:
397     case WM_MBUTTONDBLCLK:
398     case WM_MBUTTONDOWN:
399     case WM_MBUTTONUP:
400     case WM_MOUSEACTIVATE:
401     case WM_MOUSEHOVER:
402     case WM_MOUSELEAVE:
403     case WM_MOUSEMOVE:
404     /* case WM_MOUSEWHEEL: */
405     case WM_NCHITTEST:
406     case WM_NCLBUTTONDBLCLK:
407     case WM_NCLBUTTONDOWN:
408     case WM_NCLBUTTONUP:
409     case WM_NCMBUTTONDBLCLK:
410     case WM_NCMBUTTONDOWN:
411     case WM_NCMBUTTONUP:
412     /* case WM_NCMOUSEHOVER: */
413     /* case WM_NCMOUSELEAVE: */
414     case WM_NCMOUSEMOVE:
415     case WM_NCRBUTTONDBLCLK:
416     case WM_NCRBUTTONDOWN:
417     case WM_NCRBUTTONUP:
418     /* case WM_NCXBUTTONDBLCLK: */
419     /* case WM_NCXBUTTONDOWN: */
420     /* case WM_NCXBUTTONUP: */
421     case WM_RBUTTONDBLCLK:
422     case WM_RBUTTONDOWN:
423     case WM_RBUTTONUP:
424     /* case WM_XBUTTONDBLCLK: */
425     /* case WM_XBUTTONDOWN: */
426     /* case WM_XBUTTONUP: */
427     case WM_ACTIVATE:
428     case WM_CHAR:
429     case WM_DEADCHAR:
430     case WM_GETHOTKEY:
431     case WM_HOTKEY:
432     case WM_KEYDOWN:
433     case WM_KEYUP:
434     case WM_KILLFOCUS:
435     case WM_SETFOCUS:
436     case WM_SETHOTKEY:
437     case WM_SYSCHAR:
438     case WM_SYSDEADCHAR:
439     case WM_SYSKEYDOWN:
440     case WM_SYSKEYUP:
441             
442     case WM_NCCALCSIZE:
443         return 0;
444
445     case WM_PAINT:
446         
447         hdc = BeginPaint(hWnd, &ps);
448
449         WindowId = GetWindowLongPtr(hWnd, GWLP_ID);
450
451         switch (WindowId)
452         {
453         case IDC_CPU_USAGE_GRAPH:
454             Graph_DrawCpuUsageGraph(hdc, hWnd);
455             break;
456         case IDC_MEM_USAGE_GRAPH:
457             Graph_DrawMemUsageGraph(hdc, hWnd);
458             break;
459         case IDC_MEM_USAGE_HISTORY_GRAPH:
460             Graph_DrawMemUsageHistoryGraph(hdc, hWnd);
461             break;
462         }
463         
464         EndPaint(hWnd, &ps);
465         
466         return 0;
467         
468     }
469     
470     /*
471      * We pass on all non-handled messages
472      */
473     return CallWindowProc((WNDPROC)OldGraphWndProc, hWnd, message, wParam, lParam);
474 }