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