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