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