winedbg: Disassemble more Thumb instructions.
[wine] / programs / taskmgr / applpage.c
1 /*
2  *  ReactOS Task Manager
3  *
4  *  applpage.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 #include <stdio.h>
25 #include <stdlib.h>
26
27 #include <windows.h>
28 #include <commctrl.h>
29
30 #include "wine/unicode.h"
31 #include "taskmgr.h"
32
33 typedef struct
34 {
35     HWND    hWnd;
36     WCHAR   wszTitle[256];
37     HICON   hIcon;
38     BOOL    bHung;
39 } APPLICATION_PAGE_LIST_ITEM, *LPAPPLICATION_PAGE_LIST_ITEM;
40
41 HWND            hApplicationPage;               /* Application List Property Page */
42 HWND            hApplicationPageListCtrl;       /* Application ListCtrl Window */
43 HWND            hApplicationPageEndTaskButton;  /* Application End Task button */
44 HWND            hApplicationPageSwitchToButton; /* Application Switch To button */
45 HWND            hApplicationPageNewTaskButton;  /* Application New Task button */
46 static int      nApplicationPageWidth;
47 static int      nApplicationPageHeight;
48 static HANDLE   hApplicationPageEvent = NULL;   /* When this event becomes signaled then we refresh the app list */
49 static BOOL     bSortAscending = TRUE;
50
51 static const WCHAR    wszUser32[] = {'U','S','E','R','3','2','.','D','L','L',0};
52 #if 0
53 void SwitchToThisWindow (
54 HWND hWnd,   /* Handle to the window that should be activated */
55 BOOL bRestore /* Restore the window if it is minimized */
56 );
57 #endif
58
59 static void ApplicationPageUpdate(void)
60 {
61     /* Enable or disable the "End Task" & "Switch To" buttons */
62     if (SendMessageW(hApplicationPageListCtrl, LVM_GETSELECTEDCOUNT, 0, 0))
63     {
64         EnableWindow(hApplicationPageEndTaskButton, TRUE);
65         EnableWindow(hApplicationPageSwitchToButton, TRUE);
66     }
67     else
68     {
69         EnableWindow(hApplicationPageEndTaskButton, FALSE);
70         EnableWindow(hApplicationPageSwitchToButton, FALSE);
71     }
72
73     /* If we are on the applications tab, then the windows menu will */
74     /* be present on the menu bar so enable & disable the menu items */
75     if (SendMessageW(hTabWnd, TCM_GETCURSEL, 0, 0) == 0)
76     {
77         HMENU   hMenu;
78         HMENU   hWindowsMenu;
79         UINT    count;
80
81         hMenu = GetMenu(hMainWnd);
82         hWindowsMenu = GetSubMenu(hMenu, 3);
83         count = SendMessageW(hApplicationPageListCtrl, LVM_GETSELECTEDCOUNT, 0, 0);
84
85         /* Only one item selected */
86         if (count == 1)
87         {
88             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
89             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
90             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
91             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
92             EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
93             EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_ENABLED);
94         }
95         /* More than one item selected */
96         else if (count > 1)
97         {
98             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_ENABLED);
99             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_ENABLED);
100             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
101             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
102             EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_ENABLED);
103             EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
104         }
105         /* No items selected */
106         else
107         {
108             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
109             EnableMenuItem(hWindowsMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
110             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
111             EnableMenuItem(hWindowsMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
112             EnableMenuItem(hWindowsMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
113             EnableMenuItem(hWindowsMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
114         }
115     }
116 }
117
118 static void AddOrUpdateHwnd(HWND hWnd, WCHAR *wszTitle, HICON hIcon, BOOL bHung)
119 {
120     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
121     HIMAGELIST                      hImageListLarge;
122     HIMAGELIST                      hImageListSmall;
123     LV_ITEMW                        item;
124     int                             i, count;
125     BOOL                            bAlreadyInList = FALSE;
126     BOOL                            bItemRemoved = FALSE;
127
128     memset(&item, 0, sizeof(LV_ITEMW));
129
130     /* Get the image lists */
131     hImageListLarge = (HIMAGELIST)SendMessageW(hApplicationPageListCtrl, LVM_GETIMAGELIST, LVSIL_NORMAL, 0);
132     hImageListSmall = (HIMAGELIST)SendMessageW(hApplicationPageListCtrl, LVM_GETIMAGELIST, LVSIL_SMALL, 0);
133
134     count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
135     /* Check to see if it's already in our list */
136     for (i=0; i<count; i++)
137     {
138         memset(&item, 0, sizeof(LV_ITEMW));
139         item.mask = LVIF_IMAGE|LVIF_PARAM;
140         item.iItem = i;
141         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
142
143         pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
144         if (pAPLI->hWnd == hWnd)
145         {
146             bAlreadyInList = TRUE;
147             break;
148         }
149     }
150
151     /* If it is already in the list then update it if necessary */
152     if (bAlreadyInList)
153     {
154         /* Check to see if anything needs updating */
155         if ((pAPLI->hIcon != hIcon) ||
156             (strcmpW(pAPLI->wszTitle, wszTitle) != 0) ||
157             (pAPLI->bHung != bHung))
158         {
159             /* Update the structure */
160             pAPLI->hIcon = hIcon;
161             pAPLI->bHung = bHung;
162             strcpyW(pAPLI->wszTitle, wszTitle);
163
164             /* Update the image list */
165             ImageList_ReplaceIcon(hImageListLarge, item.iItem, hIcon);
166             ImageList_ReplaceIcon(hImageListSmall, item.iItem, hIcon);
167
168             /* Update the list view */
169             count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
170             SendMessageW(hApplicationPageListCtrl, LVM_REDRAWITEMS, 0, count);
171             /* UpdateWindow(hApplicationPageListCtrl); */
172             InvalidateRect(hApplicationPageListCtrl, NULL, 0);
173         }
174     }
175     /* It is not already in the list so add it */
176     else
177     {
178         pAPLI = HeapAlloc(GetProcessHeap(), 0, sizeof(APPLICATION_PAGE_LIST_ITEM));
179
180         pAPLI->hWnd = hWnd;
181         pAPLI->hIcon = hIcon;
182         pAPLI->bHung = bHung;
183         strcpyW(pAPLI->wszTitle, wszTitle);
184
185         /* Add the item to the list */
186         memset(&item, 0, sizeof(LV_ITEMW));
187         item.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
188         ImageList_AddIcon(hImageListLarge, hIcon);
189         item.iImage = ImageList_AddIcon(hImageListSmall, hIcon);
190         item.pszText = LPSTR_TEXTCALLBACKW;
191         item.iItem = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
192         item.lParam = (LPARAM)pAPLI;
193         SendMessageW(hApplicationPageListCtrl, LVM_INSERTITEMW, 0, (LPARAM) &item);
194     }
195
196
197     /* Check to see if we need to remove any items from the list */
198     for (i=SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0)-1; i>=0; i--)
199     {
200         memset(&item, 0, sizeof(LV_ITEMW));
201         item.mask = LVIF_IMAGE|LVIF_PARAM;
202         item.iItem = i;
203         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
204
205         pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
206         if (!IsWindow(pAPLI->hWnd)||
207             (strlenW(pAPLI->wszTitle) <= 0) ||
208             !IsWindowVisible(pAPLI->hWnd) ||
209             (GetParent(pAPLI->hWnd) != NULL) ||
210             (GetWindow(pAPLI->hWnd, GW_OWNER) != NULL) ||
211             (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
212         {
213             ImageList_Remove(hImageListLarge, item.iItem);
214             ImageList_Remove(hImageListSmall, item.iItem);
215
216             SendMessageW(hApplicationPageListCtrl, LVM_DELETEITEM, item.iItem, 0);
217             HeapFree(GetProcessHeap(), 0, pAPLI);
218             bItemRemoved = TRUE;
219         }
220     }
221
222     /*
223      * If an item was removed from the list then
224      * we need to resync all the items with the
225      * image list
226      */
227     if (bItemRemoved)
228     {
229         count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
230         for (i=0; i<count; i++)
231         {
232             memset(&item, 0, sizeof(LV_ITEMW));
233             item.mask = LVIF_IMAGE;
234             item.iItem = i;
235             item.iImage = i;
236             SendMessageW(hApplicationPageListCtrl, LVM_SETITEMW, 0, (LPARAM) &item);
237         }
238     }
239
240     ApplicationPageUpdate();
241 }
242
243 static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
244 {
245     HICON hIcon;
246     WCHAR wszText[256];
247     BOOL  bLargeIcon;
248     BOOL  bHung = FALSE;
249     typedef int (__stdcall *IsHungAppWindowProc)(HWND);
250     IsHungAppWindowProc IsHungAppWindow;
251
252
253     /* Skip our window */
254     if (hWnd == hMainWnd)
255         return TRUE;
256
257     bLargeIcon = TaskManagerSettings.View_LargeIcons ? TRUE : FALSE;
258
259     /* Check and see if this is a top-level app window */
260     if (!GetWindowTextW(hWnd, wszText, sizeof(wszText)/sizeof(WCHAR)) ||
261         !IsWindowVisible(hWnd) ||
262         (GetParent(hWnd) != NULL) ||
263         (GetWindow(hWnd, GW_OWNER) != NULL) ||
264         (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
265     {
266         return TRUE; /* Skip this window */
267     }
268
269     /* Get the icon for this window */
270     hIcon = NULL;
271     SendMessageTimeoutW(hWnd, WM_GETICON, bLargeIcon ? ICON_BIG /*1*/ : ICON_SMALL /*0*/, 0, 0, 1000, (PDWORD_PTR)&hIcon);
272
273     if (!hIcon)
274     {
275         hIcon = (HICON)GetClassLongPtrW(hWnd, bLargeIcon ? GCLP_HICON : GCLP_HICONSM);
276         if (!hIcon) hIcon = (HICON)GetClassLongPtrW(hWnd, bLargeIcon ? GCLP_HICONSM : GCLP_HICON);
277         if (!hIcon) SendMessageTimeoutW(hWnd, WM_QUERYDRAGICON, 0, 0, 0, 1000, (PDWORD_PTR)&hIcon);
278         if (!hIcon) SendMessageTimeoutW(hWnd, WM_GETICON, bLargeIcon ? ICON_SMALL /*0*/ : ICON_BIG /*1*/, 0, 0, 1000, (PDWORD_PTR)&hIcon);
279     }
280
281     if (!hIcon)
282         hIcon = LoadIconW(hInst, bLargeIcon ? MAKEINTRESOURCEW(IDI_WINDOW) : MAKEINTRESOURCEW(IDI_WINDOWSM));
283
284     bHung = FALSE;
285
286     IsHungAppWindow = (IsHungAppWindowProc)(FARPROC)GetProcAddress(GetModuleHandleW(wszUser32), "IsHungAppWindow");
287
288     if (IsHungAppWindow)
289         bHung = IsHungAppWindow(hWnd);
290
291     AddOrUpdateHwnd(hWnd, wszText, hIcon, bHung);
292
293     return TRUE;
294 }
295
296 static DWORD WINAPI ApplicationPageRefreshThread(void *lpParameter)
297 {
298     /* Create the event */
299     hApplicationPageEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
300
301     /* If we couldn't create the event then exit the thread */
302     if (!hApplicationPageEvent)
303         return 0;
304
305     while (1)
306     {
307         DWORD   dwWaitVal;
308
309         /* Wait on the event */
310         dwWaitVal = WaitForSingleObject(hApplicationPageEvent, INFINITE);
311
312         /* If the wait failed then the event object must have been */
313         /* closed and the task manager is exiting so exit this thread */
314         if (dwWaitVal == WAIT_FAILED)
315             return 0;
316
317         if (dwWaitVal == WAIT_OBJECT_0)
318         {
319             /* Reset our event */
320             ResetEvent(hApplicationPageEvent);
321
322             /*
323              * FIXME:
324              *
325              * Should this be EnumDesktopWindows() instead?
326              */
327             EnumWindows(EnumWindowsProc, 0);
328         }
329     }
330 }
331
332 static void ApplicationPageShowContextMenu1(void)
333 {
334     HMENU   hMenu;
335     HMENU   hSubMenu;
336     POINT   pt;
337
338     GetCursorPos(&pt);
339
340     hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_APPLICATION_PAGE_CONTEXT1));
341     hSubMenu = GetSubMenu(hMenu, 0);
342
343     if (TaskManagerSettings.View_LargeIcons)
344         CheckMenuRadioItem(hSubMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_LARGE, MF_BYCOMMAND);
345     else if (TaskManagerSettings.View_SmallIcons)
346         CheckMenuRadioItem(hSubMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_SMALL, MF_BYCOMMAND);
347     else
348         CheckMenuRadioItem(hSubMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_DETAILS, MF_BYCOMMAND);
349
350     TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL);
351
352     DestroyMenu(hMenu);
353 }
354
355 static void ApplicationPageShowContextMenu2(void)
356 {
357     HMENU   hMenu;
358     HMENU   hSubMenu;
359     UINT    count;
360     POINT   pt;
361
362     GetCursorPos(&pt);
363
364     hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_APPLICATION_PAGE_CONTEXT2));
365     hSubMenu = GetSubMenu(hMenu, 0);
366
367     count = SendMessageW(hApplicationPageListCtrl, LVM_GETSELECTEDCOUNT, 0, 0);
368     if (count == 1)
369     {
370         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
371         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
372         EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
373         EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
374         EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
375         EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_ENABLED);
376     }
377     else if (count > 1)
378     {
379         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_ENABLED);
380         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_ENABLED);
381         EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_ENABLED);
382         EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED);
383         EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_ENABLED);
384         EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
385     }
386     else
387     {
388         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEHORIZONTALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
389         EnableMenuItem(hSubMenu, ID_WINDOWS_TILEVERTICALLY, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
390         EnableMenuItem(hSubMenu, ID_WINDOWS_MINIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
391         EnableMenuItem(hSubMenu, ID_WINDOWS_MAXIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
392         EnableMenuItem(hSubMenu, ID_WINDOWS_CASCADE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
393         EnableMenuItem(hSubMenu, ID_WINDOWS_BRINGTOFRONT, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
394     }
395
396     SetMenuDefaultItem(hSubMenu, ID_APPLICATION_PAGE_SWITCHTO, MF_BYCOMMAND);
397
398     TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL);
399
400     DestroyMenu(hMenu);
401 }
402
403 static int CALLBACK ApplicationPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
404 {
405     LPAPPLICATION_PAGE_LIST_ITEM Param1;
406     LPAPPLICATION_PAGE_LIST_ITEM Param2;
407
408     if (bSortAscending) {
409         Param1 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam1;
410         Param2 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam2;
411     } else {
412         Param1 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam2;
413         Param2 = (LPAPPLICATION_PAGE_LIST_ITEM)lParam1;
414     }
415     return strcmpW(Param1->wszTitle, Param2->wszTitle);
416 }
417
418 static void ApplicationPageOnNotify(WPARAM wParam, LPARAM lParam)
419 {
420     LPNMHDR         pnmh;
421     LV_DISPINFOW*   pnmdi;
422     LPAPPLICATION_PAGE_LIST_ITEM pAPLI;
423     WCHAR    wszNotResponding[255];
424     WCHAR    wszRunning[255];
425
426     LoadStringW(hInst, IDS_APPLICATION_NOT_RESPONDING, wszNotResponding, sizeof(wszNotResponding)/sizeof(WCHAR));
427     LoadStringW(hInst, IDS_APPLICATION_RUNNING, wszRunning, sizeof(wszRunning)/sizeof(WCHAR));
428
429     pnmh = (LPNMHDR) lParam;
430     pnmdi = (LV_DISPINFOW*) lParam;
431
432     if (pnmh->hwndFrom == hApplicationPageListCtrl) {
433         switch (pnmh->code) {
434         case LVN_ITEMCHANGED:
435             ApplicationPageUpdate();
436             break;
437             
438         case LVN_GETDISPINFOW:
439             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)pnmdi->item.lParam;
440
441             /* Update the item text */
442             if (pnmdi->item.iSubItem == 0)
443             {
444                 lstrcpynW(pnmdi->item.pszText, pAPLI->wszTitle, pnmdi->item.cchTextMax);
445             }
446
447             /* Update the item status */
448             else if (pnmdi->item.iSubItem == 1)
449             {
450                 if (pAPLI->bHung)
451                     lstrcpynW(pnmdi->item.pszText, wszNotResponding, pnmdi->item.cchTextMax);
452                 else
453                     lstrcpynW(pnmdi->item.pszText, wszRunning, pnmdi->item.cchTextMax);
454             }
455
456             break;
457
458         case NM_RCLICK:
459
460             if (SendMessageW(hApplicationPageListCtrl, LVM_GETSELECTEDCOUNT, 0, 0) < 1)
461             {
462                 ApplicationPageShowContextMenu1();
463             }
464             else
465             {
466                 ApplicationPageShowContextMenu2();
467             }
468
469             break;
470
471         case NM_DBLCLK:
472
473             ApplicationPage_OnSwitchTo();
474
475             break;
476         }
477     }
478     else if (pnmh->hwndFrom == (HWND)SendMessageW(hApplicationPageListCtrl, LVM_GETHEADER, 0, 0))
479     {
480         switch (pnmh->code)
481         {
482         case NM_RCLICK:
483
484             if (SendMessageW(hApplicationPageListCtrl, LVM_GETSELECTEDCOUNT, 0, 0) < 1)
485             {
486                 ApplicationPageShowContextMenu1();
487             }
488             else
489             {
490                 ApplicationPageShowContextMenu2();
491             }
492
493             break;
494
495         case HDN_ITEMCLICKW:
496
497             SendMessageW(hApplicationPageListCtrl, LVM_SORTITEMS, 0, (LPARAM) ApplicationPageCompareFunc);
498             bSortAscending = !bSortAscending;
499
500             break;
501         }
502     }
503
504 }
505
506 void RefreshApplicationPage(void)
507 {
508     /* Signal the event so that our refresh thread */
509     /* will wake up and refresh the application page */
510     SetEvent(hApplicationPageEvent);
511 }
512
513 static void UpdateApplicationListControlViewSetting(void)
514 {
515     DWORD   dwStyle = GetWindowLongW(hApplicationPageListCtrl, GWL_STYLE);
516
517     dwStyle &= ~LVS_REPORT;
518     dwStyle &= ~LVS_ICON;
519     dwStyle &= ~LVS_LIST;
520     dwStyle &= ~LVS_SMALLICON;
521
522     if (TaskManagerSettings.View_LargeIcons)
523         dwStyle |= LVS_ICON;
524     else if (TaskManagerSettings.View_SmallIcons)
525         dwStyle |= LVS_SMALLICON;
526     else
527         dwStyle |= LVS_REPORT;
528
529     SetWindowLongW(hApplicationPageListCtrl, GWL_STYLE, dwStyle);
530
531     RefreshApplicationPage();
532 }
533
534 void ApplicationPage_OnViewLargeIcons(void)
535 {
536     HMENU   hMenu;
537     HMENU   hViewMenu;
538
539     hMenu = GetMenu(hMainWnd);
540     hViewMenu = GetSubMenu(hMenu, 2);
541
542     TaskManagerSettings.View_LargeIcons = TRUE;
543     TaskManagerSettings.View_SmallIcons = FALSE;
544     TaskManagerSettings.View_Details = FALSE;
545     CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_LARGE, MF_BYCOMMAND);
546
547     UpdateApplicationListControlViewSetting();
548 }
549
550 void ApplicationPage_OnViewSmallIcons(void)
551 {
552     HMENU   hMenu;
553     HMENU   hViewMenu;
554
555     hMenu = GetMenu(hMainWnd);
556     hViewMenu = GetSubMenu(hMenu, 2);
557
558     TaskManagerSettings.View_LargeIcons = FALSE;
559     TaskManagerSettings.View_SmallIcons = TRUE;
560     TaskManagerSettings.View_Details = FALSE;
561     CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_SMALL, MF_BYCOMMAND);
562
563     UpdateApplicationListControlViewSetting();
564 }
565
566 void ApplicationPage_OnViewDetails(void)
567 {
568     HMENU   hMenu;
569     HMENU   hViewMenu;
570
571     hMenu = GetMenu(hMainWnd);
572     hViewMenu = GetSubMenu(hMenu, 2);
573
574     TaskManagerSettings.View_LargeIcons = FALSE;
575     TaskManagerSettings.View_SmallIcons = FALSE;
576     TaskManagerSettings.View_Details = TRUE;
577     CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_DETAILS, MF_BYCOMMAND);
578
579     UpdateApplicationListControlViewSetting();
580 }
581
582 void ApplicationPage_OnWindowsTileHorizontally(void)
583 {
584     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
585     LV_ITEMW                        item;
586     int                             i, count;
587     HWND*                           hWndArray;
588     int                             nWndCount;
589
590     count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
591     hWndArray = HeapAlloc(GetProcessHeap(), 0,
592                     sizeof(HWND) * count);
593     nWndCount = 0;
594
595     for (i=0; i<count; i++) {
596         memset(&item, 0, sizeof(LV_ITEMW));
597         item.mask = LVIF_STATE|LVIF_PARAM;
598         item.iItem = i;
599         item.stateMask = (UINT)-1;
600         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
601
602         if (item.state & LVIS_SELECTED) {
603             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
604
605             if (pAPLI) {
606                 hWndArray[nWndCount] = pAPLI->hWnd;
607                 nWndCount++;
608             }
609         }
610     }
611     TileWindows(NULL, MDITILE_HORIZONTAL, NULL, nWndCount, hWndArray);
612     HeapFree(GetProcessHeap(), 0, hWndArray);
613 }
614
615 void ApplicationPage_OnWindowsTileVertically(void)
616 {
617     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
618     LV_ITEMW                        item;
619     int                             i, count;
620     HWND*                           hWndArray;
621     int                             nWndCount;
622
623     count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
624     hWndArray = HeapAlloc(GetProcessHeap(), 0,
625                     sizeof(HWND) * count);
626     nWndCount = 0;
627
628     for (i=0; i<count; i++) {
629         memset(&item, 0, sizeof(LV_ITEMW));
630         item.mask = LVIF_STATE|LVIF_PARAM;
631         item.iItem = i;
632         item.stateMask = (UINT)-1;
633         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
634
635         if (item.state & LVIS_SELECTED) {
636             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
637             if (pAPLI) {
638                 hWndArray[nWndCount] = pAPLI->hWnd;
639                 nWndCount++;
640             }
641         }
642     }
643
644     TileWindows(NULL, MDITILE_VERTICAL, NULL, nWndCount, hWndArray);
645     HeapFree(GetProcessHeap(), 0, hWndArray);
646 }
647
648 void ApplicationPage_OnWindowsMinimize(void)
649 {
650     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
651     LV_ITEMW                        item;
652     int                             i, count;
653
654     count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
655     for (i=0; i<count; i++) {
656         memset(&item, 0, sizeof(LV_ITEMW));
657         item.mask = LVIF_STATE|LVIF_PARAM;
658         item.iItem = i;
659         item.stateMask = (UINT)-1;
660         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
661         if (item.state & LVIS_SELECTED) {
662             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
663             if (pAPLI) {
664                 ShowWindow(pAPLI->hWnd, SW_MINIMIZE);
665             }
666         }
667     }
668 }
669
670 void ApplicationPage_OnWindowsMaximize(void)
671 {
672     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
673     LV_ITEMW                        item;
674     int                             i, count;
675
676     count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
677     for (i=0; i<count; i++) {
678         memset(&item, 0, sizeof(LV_ITEMW));
679         item.mask = LVIF_STATE|LVIF_PARAM;
680         item.iItem = i;
681         item.stateMask = (UINT)-1;
682         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
683         if (item.state & LVIS_SELECTED) {
684             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
685             if (pAPLI) {
686                 ShowWindow(pAPLI->hWnd, SW_MAXIMIZE);
687             }
688         }
689     }
690 }
691
692 void ApplicationPage_OnWindowsCascade(void)
693 {
694     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
695     LV_ITEMW                        item;
696     int                             i, count;
697     HWND*                           hWndArray;
698     int                             nWndCount;
699
700     count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
701     hWndArray = HeapAlloc(GetProcessHeap(), 0,
702                     sizeof(HWND) * count);
703     nWndCount = 0;
704
705     for (i=0; i<count; i++) {
706         memset(&item, 0, sizeof(LV_ITEMW));
707         item.mask = LVIF_STATE|LVIF_PARAM;
708         item.iItem = i;
709         item.stateMask = (UINT)-1;
710         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
711         if (item.state & LVIS_SELECTED) {
712             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
713             if (pAPLI) {
714                 hWndArray[nWndCount] = pAPLI->hWnd;
715                 nWndCount++;
716             }
717         }
718     }
719     CascadeWindows(NULL, 0, NULL, nWndCount, hWndArray);
720     HeapFree(GetProcessHeap(), 0, hWndArray);
721 }
722
723 void ApplicationPage_OnWindowsBringToFront(void)
724 {
725     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
726     LV_ITEMW                        item;
727     int                             i, count;
728
729     count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
730     for (i=0; i<count; i++) {
731         memset(&item, 0, sizeof(LV_ITEMW));
732         item.mask = LVIF_STATE|LVIF_PARAM;
733         item.iItem = i;
734         item.stateMask = (UINT)-1;
735         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
736         if (item.state & LVIS_SELECTED) {
737             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
738             break;
739         }
740     }
741     if (pAPLI) {
742         if (IsIconic(pAPLI->hWnd))
743             ShowWindow(pAPLI->hWnd, SW_RESTORE);
744         BringWindowToTop(pAPLI->hWnd);
745     }
746 }
747
748 void ApplicationPage_OnSwitchTo(void)
749 {
750     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
751     LV_ITEMW                        item;
752     int                             i, count;
753
754     count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
755     for (i=0; i<count; i++) {
756         memset(&item, 0, sizeof(LV_ITEMW));
757         item.mask = LVIF_STATE|LVIF_PARAM;
758         item.iItem = i;
759         item.stateMask = (UINT)-1;
760         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
761
762         if (item.state & LVIS_SELECTED) {
763             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
764             break;
765         }
766     }
767     if (pAPLI) {
768         typedef void (WINAPI *PROCSWITCHTOTHISWINDOW) (HWND, BOOL);
769         PROCSWITCHTOTHISWINDOW SwitchToThisWindow;
770
771         HMODULE hUser32 = GetModuleHandleW(wszUser32);
772         SwitchToThisWindow = (PROCSWITCHTOTHISWINDOW)GetProcAddress(hUser32, "SwitchToThisWindow");
773         if (SwitchToThisWindow) {
774             SwitchToThisWindow(pAPLI->hWnd, TRUE);
775         } else {
776             if (IsIconic(pAPLI->hWnd))
777                 ShowWindow(pAPLI->hWnd, SW_RESTORE);
778             BringWindowToTop(pAPLI->hWnd);
779             SetForegroundWindow(pAPLI->hWnd);
780         }
781         if (TaskManagerSettings.MinimizeOnUse)
782             ShowWindow(hMainWnd, SW_MINIMIZE);
783     }
784 }
785
786 void ApplicationPage_OnEndTask(void)
787 {
788     LPAPPLICATION_PAGE_LIST_ITEM    pAPLI = NULL;
789     LV_ITEMW                        item;
790     int                             i, count;
791
792     count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
793     for (i=0; i<count; i++) {
794         memset(&item, 0, sizeof(LV_ITEMW));
795         item.mask = LVIF_STATE|LVIF_PARAM;
796         item.iItem = i;
797         item.stateMask = (UINT)-1;
798         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
799         if (item.state & LVIS_SELECTED) {
800             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
801             if (pAPLI) {
802                 PostMessageW(pAPLI->hWnd, WM_CLOSE, 0, 0);
803             }
804         }
805     }
806 }
807
808 void ApplicationPage_OnGotoProcess(void)
809 {
810     LPAPPLICATION_PAGE_LIST_ITEM pAPLI = NULL;
811     LV_ITEMW item;
812     int i, count;
813     /* NMHDR nmhdr; */
814
815     count = SendMessageW(hApplicationPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
816     for (i=0; i<count; i++) {
817         memset(&item, 0, sizeof(LV_ITEMW));
818         item.mask = LVIF_STATE|LVIF_PARAM;
819         item.iItem = i;
820         item.stateMask = (UINT)-1;
821         SendMessageW(hApplicationPageListCtrl, LVM_GETITEMW, 0, (LPARAM) &item);
822         if (item.state & LVIS_SELECTED) {
823             pAPLI = (LPAPPLICATION_PAGE_LIST_ITEM)item.lParam;
824             break;
825         }
826     }
827     if (pAPLI) {
828         DWORD   dwProcessId;
829
830         GetWindowThreadProcessId(pAPLI->hWnd, &dwProcessId);
831         /*
832          * Switch to the process tab
833          */
834         SendMessageW(hTabWnd, TCM_SETCURFOCUS, 1, 0);
835         /*
836          * FIXME: Select the process item in the list
837          */
838     }
839 }
840
841 INT_PTR CALLBACK
842 ApplicationPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
843 {
844     RECT        rc;
845     int         nXDifference;
846     int         nYDifference;
847     int         cx, cy;
848     LVCOLUMNW   column;
849
850     WCHAR wszTask[255];
851     WCHAR wszStatus[255];
852
853     LoadStringW(hInst, IDS_APPLICATION_TASK, wszTask, sizeof(wszTask)/sizeof(WCHAR));
854     LoadStringW(hInst, IDS_APPLICATION_STATUS, wszStatus, sizeof(wszStatus)/sizeof(WCHAR));
855
856     switch (message) {
857     case WM_INITDIALOG:
858
859         /* Save the width and height */
860         GetClientRect(hDlg, &rc);
861         nApplicationPageWidth = rc.right;
862         nApplicationPageHeight = rc.bottom;
863
864         /* Update window position */
865         SetWindowPos(hDlg, NULL, 15, 30, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
866
867         /* Get handles to the controls */
868         hApplicationPageListCtrl = GetDlgItem(hDlg, IDC_APPLIST);
869         hApplicationPageEndTaskButton = GetDlgItem(hDlg, IDC_ENDTASK);
870         hApplicationPageSwitchToButton = GetDlgItem(hDlg, IDC_SWITCHTO);
871         hApplicationPageNewTaskButton = GetDlgItem(hDlg, IDC_NEWTASK);
872
873         /* Initialize the application page's controls */
874         column.mask = LVCF_TEXT|LVCF_WIDTH;
875         column.pszText = wszTask;
876         column.cx = 250;
877         /* Add the "Task" column */
878         SendMessageW(hApplicationPageListCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM) &column);
879         column.mask = LVCF_TEXT|LVCF_WIDTH;
880         column.pszText = wszStatus;
881         column.cx = 95;
882         /* Add the "Status" column */
883         SendMessageW(hApplicationPageListCtrl, LVM_INSERTCOLUMNW, 1, (LPARAM) &column);
884
885         SendMessageW(hApplicationPageListCtrl, LVM_SETIMAGELIST, LVSIL_SMALL,
886                     (LPARAM) ImageList_Create(16, 16, ILC_COLOR8|ILC_MASK, 0, 1));
887         SendMessageW(hApplicationPageListCtrl, LVM_SETIMAGELIST, LVSIL_NORMAL,
888                     (LPARAM) ImageList_Create(32, 32, ILC_COLOR8|ILC_MASK, 0, 1));
889
890         UpdateApplicationListControlViewSetting();
891
892         /* Start our refresh thread */
893         CloseHandle( CreateThread(NULL, 0, ApplicationPageRefreshThread, NULL, 0, NULL));
894
895         return TRUE;
896
897     case WM_DESTROY:
898         /* Close the event handle, this will make the */
899         /* refresh thread exit when the wait fails */
900         CloseHandle(hApplicationPageEvent);
901         break;
902
903     case WM_COMMAND:
904
905         /* Handle the button clicks */
906         switch (LOWORD(wParam))
907         {
908         case IDC_ENDTASK:
909             ApplicationPage_OnEndTask();
910             break;
911         case IDC_SWITCHTO:
912             ApplicationPage_OnSwitchTo();
913             break;
914         case IDC_NEWTASK:
915             SendMessageW(hMainWnd, WM_COMMAND, MAKEWPARAM(ID_FILE_NEW, 0), 0);
916             break;
917         }
918
919         break;
920
921     case WM_SIZE:
922         if (wParam == SIZE_MINIMIZED)
923             return 0;
924
925         cx = LOWORD(lParam);
926         cy = HIWORD(lParam);
927         nXDifference = cx - nApplicationPageWidth;
928         nYDifference = cy - nApplicationPageHeight;
929         nApplicationPageWidth = cx;
930         nApplicationPageHeight = cy;
931
932         /* Reposition the application page's controls */
933         GetWindowRect(hApplicationPageListCtrl, &rc);
934         cx = (rc.right - rc.left) + nXDifference;
935         cy = (rc.bottom - rc.top) + nYDifference;
936         SetWindowPos(hApplicationPageListCtrl, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
937         InvalidateRect(hApplicationPageListCtrl, NULL, TRUE);
938
939         GetClientRect(hApplicationPageEndTaskButton, &rc);
940         MapWindowPoints(hApplicationPageEndTaskButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
941         cx = rc.left + nXDifference;
942         cy = rc.top + nYDifference;
943         SetWindowPos(hApplicationPageEndTaskButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
944         InvalidateRect(hApplicationPageEndTaskButton, NULL, TRUE);
945
946         GetClientRect(hApplicationPageSwitchToButton, &rc);
947         MapWindowPoints(hApplicationPageSwitchToButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
948         cx = rc.left + nXDifference;
949         cy = rc.top + nYDifference;
950         SetWindowPos(hApplicationPageSwitchToButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
951         InvalidateRect(hApplicationPageSwitchToButton, NULL, TRUE);
952
953         GetClientRect(hApplicationPageNewTaskButton, &rc);
954         MapWindowPoints(hApplicationPageNewTaskButton, hDlg, (LPPOINT)(&rc), (sizeof(RECT)/sizeof(POINT)) );
955         cx = rc.left + nXDifference;
956         cy = rc.top + nYDifference;
957         SetWindowPos(hApplicationPageNewTaskButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
958         InvalidateRect(hApplicationPageNewTaskButton, NULL, TRUE);
959
960         break;
961
962     case WM_NOTIFY:
963         ApplicationPageOnNotify(wParam, lParam);
964         break;
965
966     }
967
968   return 0;
969 }