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