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