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