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