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