[PROGMAN] Properly import from Wine Staging 1.9.4. This fixes PCH usage, marks ReactO...
[reactos.git] / reactos / base / shell / progman / main.c
1 /*
2 * Program Manager
3 *
4 * Copyright 1996 Ulrich Schmid
5 * Copyright 2002 Sylvain Petreolle
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "progman.h"
23
24 #include <shellapi.h>
25
26 GLOBALS Globals;
27
28 static VOID MAIN_CreateGroups(void);
29 static VOID MAIN_MenuCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
30 static ATOM MAIN_RegisterMainWinClass(void);
31 static VOID MAIN_CreateMainWindow(void);
32 static VOID MAIN_CreateMDIWindow(void);
33 static VOID MAIN_AutoStart(void);
34
35 #define BUFFER_SIZE 1000
36
37 /***********************************************************************
38 *
39 * WinMain
40 */
41
42 #ifdef __REACTOS__
43 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
44 #else
45 int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
46 #endif
47 {
48 MSG msg;
49
50 Globals.lpszIniFile = "progman.ini";
51 #ifndef __REACTOS__
52 Globals.lpszIcoFile = "progman.ico";
53 #endif
54
55 Globals.hInstance = hInstance;
56 Globals.hGroups = 0;
57 Globals.hActiveGroup = 0;
58
59 /* Read Options from `progman.ini' */
60 Globals.bAutoArrange =
61 GetPrivateProfileIntA("Settings", "AutoArrange", 0, Globals.lpszIniFile);
62 Globals.bMinOnRun =
63 GetPrivateProfileIntA("Settings", "MinOnRun", 0, Globals.lpszIniFile);
64 Globals.bSaveSettings =
65 GetPrivateProfileIntA("Settings", "SaveSettings", 0, Globals.lpszIniFile);
66
67 /* Load default icons */
68 #ifdef __REACTOS__
69 Globals.hMainIcon = LoadIconW(Globals.hInstance, MAKEINTRESOURCEW(IDI_APPICON));
70 Globals.hGroupIcon = Globals.hMainIcon;
71 Globals.hDefaultIcon = Globals.hMainIcon;
72 #else
73 Globals.hMainIcon = ExtractIconA(Globals.hInstance, Globals.lpszIcoFile, 0);
74 Globals.hGroupIcon = ExtractIconA(Globals.hInstance, Globals.lpszIcoFile, 0);
75 Globals.hDefaultIcon = ExtractIconA(Globals.hInstance, Globals.lpszIcoFile, 0);
76 #endif
77 if (!Globals.hMainIcon) Globals.hMainIcon = LoadIconW(0, (LPWSTR)DEFAULTICON);
78 if (!Globals.hGroupIcon) Globals.hGroupIcon = LoadIconW(0, (LPWSTR)DEFAULTICON);
79 if (!Globals.hDefaultIcon) Globals.hDefaultIcon = LoadIconW(0, (LPWSTR)DEFAULTICON);
80
81 /* Register classes */
82 if (!prev)
83 {
84 if (!MAIN_RegisterMainWinClass()) return(FALSE);
85 if (!GROUP_RegisterGroupWinClass()) return(FALSE);
86 if (!PROGRAM_RegisterProgramWinClass()) return(FALSE);
87 }
88
89 /* Create main window */
90 MAIN_CreateMainWindow();
91 Globals.hAccel = LoadAcceleratorsW(Globals.hInstance, MAKEINTRESOURCEW(IDA_ACCEL));
92
93 /* Setup menu, stringtable and resourcenames */
94 STRING_LoadMenus();
95
96 MAIN_CreateMDIWindow();
97
98 /* Initialize groups */
99 MAIN_CreateGroups();
100
101 /* Start initial applications */
102 MAIN_AutoStart();
103
104 /* Message loop */
105 while (GetMessageW (&msg, 0, 0, 0))
106 if (!TranslateAcceleratorW(Globals.hMainWnd, Globals.hAccel, &msg))
107 {
108 TranslateMessage (&msg);
109 DispatchMessageW (&msg);
110 }
111 return 0;
112 }
113
114 /***********************************************************************
115 *
116 * MAIN_CreateGroups
117 */
118
119 static VOID MAIN_CreateGroups(void)
120 {
121 CHAR buffer[BUFFER_SIZE];
122 CHAR szPath[MAX_PATHNAME_LEN];
123 CHAR key[20], *ptr;
124
125 /* Initialize groups according the `Order' entry of `progman.ini' */
126 GetPrivateProfileStringA("Settings", "Order", "", buffer, sizeof(buffer), Globals.lpszIniFile);
127 ptr = buffer;
128 while (ptr < buffer + sizeof(buffer))
129 {
130 int num, skip, ret;
131 ret = sscanf(ptr, "%d%n", &num, &skip);
132 if (ret == 0)
133 MAIN_MessageBoxIDS_s(IDS_FILE_READ_ERROR_s, Globals.lpszIniFile, IDS_ERROR, MB_OK);
134 if (ret != 1) break;
135
136 sprintf(key, "Group%d", num);
137 GetPrivateProfileStringA("Groups", key, "", szPath,
138 sizeof(szPath), Globals.lpszIniFile);
139 if (!szPath[0]) continue;
140
141 GRPFILE_ReadGroupFile(szPath);
142
143 ptr += skip;
144 }
145 /* FIXME initialize other groups, not enumerated by `Order' */
146 }
147
148 /***********************************************************************
149 *
150 * MAIN_AutoStart
151 */
152
153 VOID MAIN_AutoStart(void)
154 {
155 CHAR buffer[BUFFER_SIZE];
156 HLOCAL hGroup, hProgram;
157
158 GetPrivateProfileStringA("Settings", "AutoStart", "Autostart", buffer,
159 sizeof(buffer), Globals.lpszIniFile);
160
161 for (hGroup = GROUP_FirstGroup(); hGroup; hGroup = GROUP_NextGroup(hGroup))
162 if (!lstrcmpA(buffer, GROUP_GroupName(hGroup)))
163 for (hProgram = PROGRAM_FirstProgram(hGroup); hProgram;
164 hProgram = PROGRAM_NextProgram(hProgram))
165 PROGRAM_ExecuteProgram(hProgram);
166 }
167
168 /***********************************************************************
169 *
170 * MAIN_MainWndProc
171 */
172
173 static LRESULT CALLBACK MAIN_MainWndProc(HWND hWnd, UINT msg,
174 WPARAM wParam, LPARAM lParam)
175 {
176 switch (msg)
177 {
178 case WM_INITMENU:
179 CheckMenuItem(Globals.hOptionMenu, PM_AUTO_ARRANGE,
180 MF_BYCOMMAND | (Globals.bAutoArrange ? MF_CHECKED : MF_UNCHECKED));
181 CheckMenuItem(Globals.hOptionMenu, PM_MIN_ON_RUN,
182 MF_BYCOMMAND | (Globals.bMinOnRun ? MF_CHECKED : MF_UNCHECKED));
183 CheckMenuItem(Globals.hOptionMenu, PM_SAVE_SETTINGS,
184 MF_BYCOMMAND | (Globals.bSaveSettings ? MF_CHECKED : MF_UNCHECKED));
185 break;
186
187 case WM_COMMAND:
188 if (LOWORD(wParam) < PM_FIRST_CHILD){
189 MAIN_MenuCommand(hWnd, LOWORD(wParam), lParam);
190 }
191 break;
192
193 case WM_DESTROY:
194 PostQuitMessage (0);
195 break;
196 }
197 return DefFrameProcW(hWnd, Globals.hMDIWnd, msg, wParam, lParam);
198 }
199
200 /***********************************************************************
201 *
202 * MAIN_MenuCommand
203 */
204
205 static VOID MAIN_MenuCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
206 {
207 HLOCAL hActiveGroup = GROUP_ActiveGroup();
208 HLOCAL hActiveProgram = PROGRAM_ActiveProgram(hActiveGroup);
209 HWND hActiveGroupWnd = GROUP_GroupWnd(hActiveGroup);
210
211 switch(wParam)
212 {
213 /* Menu File */
214 case PM_NEW:
215 switch (DIALOG_New((hActiveGroupWnd && !IsIconic(hActiveGroupWnd)) ?
216 PM_NEW_PROGRAM : PM_NEW_GROUP))
217 {
218 case PM_NEW_PROGRAM:
219 if (hActiveGroup) PROGRAM_NewProgram(hActiveGroup);
220 break;
221
222 case PM_NEW_GROUP:
223 GROUP_NewGroup();
224 break;
225 }
226 break;
227
228 case PM_OPEN:
229 if (hActiveProgram)
230 PROGRAM_ExecuteProgram(hActiveProgram);
231 else if (hActiveGroupWnd)
232 OpenIcon(hActiveGroupWnd);
233 break;
234
235 case PM_MOVE:
236 case PM_COPY:
237 if (hActiveProgram)
238 PROGRAM_CopyMoveProgram(hActiveProgram, wParam == PM_MOVE);
239 break;
240
241 case PM_DELETE:
242 if (hActiveProgram)
243 {
244 if (DIALOG_Delete(IDS_DELETE_PROGRAM_s, PROGRAM_ProgramName(hActiveProgram)))
245 PROGRAM_DeleteProgram(hActiveProgram, TRUE);
246 }
247 else if (hActiveGroup)
248 {
249 if (DIALOG_Delete(IDS_DELETE_GROUP_s, GROUP_GroupName(hActiveGroup)))
250 GROUP_DeleteGroup(hActiveGroup);
251 }
252 break;
253
254 case PM_ATTRIBUTES:
255 if (hActiveProgram)
256 PROGRAM_ModifyProgram(hActiveProgram);
257 else if (hActiveGroup)
258 GROUP_ModifyGroup(hActiveGroup);
259 break;
260
261 case PM_EXECUTE:
262 DIALOG_Execute();
263 break;
264
265 case PM_EXIT:
266 PostQuitMessage(0);
267 break;
268
269 /* Menu Options */
270 case PM_AUTO_ARRANGE:
271 Globals.bAutoArrange = !Globals.bAutoArrange;
272 CheckMenuItem(Globals.hOptionMenu, PM_AUTO_ARRANGE,
273 MF_BYCOMMAND | (Globals.bAutoArrange ?
274 MF_CHECKED : MF_UNCHECKED));
275 WritePrivateProfileStringA("Settings", "AutoArrange",
276 Globals.bAutoArrange ? "1" : "0",
277 Globals.lpszIniFile);
278 WritePrivateProfileStringA(NULL,NULL,NULL,Globals.lpszIniFile); /* flush it */
279 break;
280
281 case PM_MIN_ON_RUN:
282 Globals.bMinOnRun = !Globals.bMinOnRun;
283 CheckMenuItem(Globals.hOptionMenu, PM_MIN_ON_RUN,
284 MF_BYCOMMAND | (Globals.bMinOnRun ?
285 MF_CHECKED : MF_UNCHECKED));
286 WritePrivateProfileStringA("Settings", "MinOnRun",
287 Globals.bMinOnRun ? "1" : "0",
288 Globals.lpszIniFile);
289 WritePrivateProfileStringA(NULL,NULL,NULL,Globals.lpszIniFile); /* flush it */
290 break;
291
292 case PM_SAVE_SETTINGS:
293 Globals.bSaveSettings = !Globals.bSaveSettings;
294 CheckMenuItem(Globals.hOptionMenu, PM_SAVE_SETTINGS,
295 MF_BYCOMMAND | (Globals.bSaveSettings ?
296 MF_CHECKED : MF_UNCHECKED));
297 WritePrivateProfileStringA("Settings", "SaveSettings",
298 Globals.bSaveSettings ? "1" : "0",
299 Globals.lpszIniFile);
300 WritePrivateProfileStringA(NULL,NULL,NULL,Globals.lpszIniFile); /* flush it */
301 break;
302
303 /* Menu Windows */
304 case PM_OVERLAP:
305 SendMessageW(Globals.hMDIWnd, WM_MDICASCADE, 0, 0);
306 break;
307
308 case PM_SIDE_BY_SIDE:
309 SendMessageW(Globals.hMDIWnd, WM_MDITILE, MDITILE_VERTICAL, 0);
310 break;
311
312 case PM_ARRANGE:
313
314 if (hActiveGroupWnd && !IsIconic(hActiveGroupWnd))
315 ArrangeIconicWindows(hActiveGroupWnd);
316 else
317 SendMessageW(Globals.hMDIWnd, WM_MDIICONARRANGE, 0, 0);
318 break;
319
320 /* Menu Help */
321 case PM_CONTENTS:
322 if (!WinHelpA(Globals.hMainWnd, "progman.hlp", HELP_CONTENTS, 0))
323 MAIN_MessageBoxIDS(IDS_WINHELP_ERROR, IDS_ERROR, MB_OK);
324 break;
325
326 case PM_ABOUT_WINE:
327 #ifdef __REACTOS__
328 {
329 WCHAR szTitle[MAX_STRING_LEN];
330 LoadStringW(Globals.hInstance, IDS_PROGRAM_MANAGER, szTitle, ARRAYSIZE(szTitle));
331 ShellAboutW(hWnd, szTitle, NULL, NULL);
332 break;
333 }
334 #else
335 ShellAboutA(hWnd, "WINE", "Program Manager", 0);
336 break;
337 #endif
338
339 default:
340 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
341 break;
342 }
343 }
344
345 /***********************************************************************
346 *
347 * MAIN_RegisterMainWinClass
348 */
349
350 static ATOM MAIN_RegisterMainWinClass(void)
351 {
352 WNDCLASSW class;
353
354 class.style = CS_HREDRAW | CS_VREDRAW;
355 class.lpfnWndProc = MAIN_MainWndProc;
356 class.cbClsExtra = 0;
357 class.cbWndExtra = 0;
358 class.hInstance = Globals.hInstance;
359 class.hIcon = Globals.hMainIcon;
360 class.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW);
361 class.hbrBackground = GetStockObject (NULL_BRUSH);
362 class.lpszMenuName = 0;
363 class.lpszClassName = STRING_MAIN_WIN_CLASS_NAME;
364
365 return RegisterClassW(&class);
366 }
367
368 /***********************************************************************
369 *
370 * MAIN_CreateMainWindow
371 */
372
373 static VOID MAIN_CreateMainWindow(void)
374 {
375 INT left , top, right, bottom, width, height, show;
376 CHAR buffer[100];
377
378 Globals.hMDIWnd = 0;
379 Globals.hMainMenu = 0;
380
381 /* Get the geometry of the main window */
382 GetPrivateProfileStringA("Settings", "Window", "", buffer, sizeof(buffer), Globals.lpszIniFile);
383 if (5 == sscanf(buffer, "%d %d %d %d %d", &left, &top, &right, &bottom, &show))
384 {
385 width = right - left;
386 height = bottom - top;
387 }
388 else
389 {
390 left = top = width = height = CW_USEDEFAULT;
391 show = SW_SHOWNORMAL;
392 }
393
394 /* Create main Window */
395 Globals.hMainWnd =
396 CreateWindowW(STRING_MAIN_WIN_CLASS_NAME, NULL,
397 WS_OVERLAPPEDWINDOW, left, top, width, height,
398 0, 0, Globals.hInstance, 0);
399
400 ShowWindow (Globals.hMainWnd, show);
401 UpdateWindow (Globals.hMainWnd);
402 }
403
404 /***********************************************************************
405 *
406 * MAIN_CreateMDIWindow
407 */
408
409 static VOID MAIN_CreateMDIWindow(void)
410 {
411 CLIENTCREATESTRUCT ccs;
412 RECT rect;
413
414 /* Get the geometry of the MDI window */
415 GetClientRect(Globals.hMainWnd, &rect);
416
417 ccs.hWindowMenu = Globals.hWindowsMenu;
418 ccs.idFirstChild = PM_FIRST_CHILD;
419
420 /* Create MDI Window */
421 Globals.hMDIWnd =
422 CreateWindowW(STRING_MDI_WIN_CLASS_NAME, NULL,
423 WS_CHILD, rect.left, rect.top,
424 rect.right - rect.left, rect.bottom - rect.top,
425 Globals.hMainWnd, 0,
426 Globals.hInstance, &ccs);
427
428 ShowWindow (Globals.hMDIWnd, SW_SHOW);
429 UpdateWindow (Globals.hMDIWnd);
430 }
431
432 /**********************************************************************/
433 /***********************************************************************
434 *
435 * MAIN_MessageBoxIDS
436 */
437 INT MAIN_MessageBoxIDS(UINT ids_text, UINT ids_title, WORD type)
438 {
439 CHAR text[MAX_STRING_LEN];
440 CHAR title[MAX_STRING_LEN];
441
442 LoadStringA(Globals.hInstance, ids_text, text, sizeof(text));
443 LoadStringA(Globals.hInstance, ids_title, title, sizeof(title));
444
445 return(MessageBoxA(Globals.hMainWnd, text, title, type));
446 }
447
448 /***********************************************************************
449 *
450 * MAIN_MessageBoxIDS_s
451 */
452 INT MAIN_MessageBoxIDS_s(UINT ids_text, LPCSTR str, UINT ids_title, WORD type)
453 {
454 CHAR text[MAX_STRING_LEN];
455 CHAR title[MAX_STRING_LEN];
456 CHAR newtext[MAX_STRING_LEN + MAX_PATHNAME_LEN];
457
458 LoadStringA(Globals.hInstance, ids_text, text, sizeof(text));
459 LoadStringA(Globals.hInstance, ids_title, title, sizeof(title));
460 wsprintfA(newtext, text, str);
461
462 return(MessageBoxA(Globals.hMainWnd, newtext, title, type));
463 }
464
465 /***********************************************************************
466 *
467 * MAIN_ReplaceString
468 */
469
470 VOID MAIN_ReplaceString(HLOCAL *handle, LPSTR replace)
471 {
472 HLOCAL newhandle = LocalAlloc(LMEM_FIXED, strlen(replace) + 1);
473 if (newhandle)
474 {
475 LPSTR newstring = LocalLock(newhandle);
476 strcpy(newstring, replace);
477 LocalFree(*handle);
478 *handle = newhandle;
479 }
480 else MAIN_MessageBoxIDS(IDS_OUT_OF_MEMORY, IDS_ERROR, MB_OK);
481 }