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