msvcp90: Return last index in string::find_last_not_of_cstr_substr if input is empty.
[wine/multimedia.git] / programs / progman / main.c
blob49a7bf7e90cdb53ac4b4f4cf75d81de87a56f1f8
1 /*
2 * Program Manager
4 * Copyright 1996 Ulrich Schmid
5 * Copyright 2002 Sylvain Petreolle
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.
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.
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
22 #include <stdio.h>
23 #include <string.h>
25 #define OEMRESOURCE
27 #include "windows.h"
28 #include "shellapi.h"
29 #include "progman.h"
31 GLOBALS Globals;
33 static VOID MAIN_CreateGroups(void);
34 static VOID MAIN_MenuCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
35 static ATOM MAIN_RegisterMainWinClass(void);
36 static VOID MAIN_CreateMainWindow(void);
37 static VOID MAIN_CreateMDIWindow(void);
38 static VOID MAIN_AutoStart(void);
40 #define BUFFER_SIZE 1000
42 /***********************************************************************
44 * WinMain
47 int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
49 MSG msg;
51 Globals.lpszIniFile = "progman.ini";
52 Globals.lpszIcoFile = "progman.ico";
54 Globals.hInstance = hInstance;
55 Globals.hGroups = 0;
56 Globals.hActiveGroup = 0;
58 /* Read Options from `progman.ini' */
59 Globals.bAutoArrange =
60 GetPrivateProfileIntA("Settings", "AutoArrange", 0, Globals.lpszIniFile);
61 Globals.bMinOnRun =
62 GetPrivateProfileIntA("Settings", "MinOnRun", 0, Globals.lpszIniFile);
63 Globals.bSaveSettings =
64 GetPrivateProfileIntA("Settings", "SaveSettings", 0, Globals.lpszIniFile);
66 /* Load default icons */
67 Globals.hMainIcon = ExtractIconA(Globals.hInstance, Globals.lpszIcoFile, 0);
68 Globals.hGroupIcon = ExtractIconA(Globals.hInstance, Globals.lpszIcoFile, 0);
69 Globals.hDefaultIcon = ExtractIconA(Globals.hInstance, Globals.lpszIcoFile, 0);
70 if (!Globals.hMainIcon) Globals.hMainIcon = LoadIconW(0, (LPWSTR)DEFAULTICON);
71 if (!Globals.hGroupIcon) Globals.hGroupIcon = LoadIconW(0, (LPWSTR)DEFAULTICON);
72 if (!Globals.hDefaultIcon) Globals.hDefaultIcon = LoadIconW(0, (LPWSTR)DEFAULTICON);
74 /* Register classes */
75 if (!prev)
77 if (!MAIN_RegisterMainWinClass()) return(FALSE);
78 if (!GROUP_RegisterGroupWinClass()) return(FALSE);
79 if (!PROGRAM_RegisterProgramWinClass()) return(FALSE);
82 /* Create main window */
83 MAIN_CreateMainWindow();
84 Globals.hAccel = LoadAcceleratorsW(Globals.hInstance, MAKEINTRESOURCEW(IDA_ACCEL));
86 /* Setup menu, stringtable and resourcenames */
87 STRING_LoadMenus();
89 MAIN_CreateMDIWindow();
91 /* Initialize groups */
92 MAIN_CreateGroups();
94 /* Start initial applications */
95 MAIN_AutoStart();
97 /* Message loop */
98 while (GetMessageW (&msg, 0, 0, 0))
99 if (!TranslateAcceleratorW(Globals.hMainWnd, Globals.hAccel, &msg))
101 TranslateMessage (&msg);
102 DispatchMessageW (&msg);
104 return 0;
107 /***********************************************************************
109 * MAIN_CreateGroups
112 static VOID MAIN_CreateGroups(void)
114 CHAR buffer[BUFFER_SIZE];
115 CHAR szPath[MAX_PATHNAME_LEN];
116 CHAR key[20], *ptr;
118 /* Initialize groups according the `Order' entry of `progman.ini' */
119 GetPrivateProfileStringA("Settings", "Order", "", buffer, sizeof(buffer), Globals.lpszIniFile);
120 ptr = buffer;
121 while (ptr < buffer + sizeof(buffer))
123 int num, skip, ret;
124 ret = sscanf(ptr, "%d%n", &num, &skip);
125 if (ret == 0)
126 MAIN_MessageBoxIDS_s(IDS_FILE_READ_ERROR_s, Globals.lpszIniFile, IDS_ERROR, MB_OK);
127 if (ret != 1) break;
129 sprintf(key, "Group%d", num);
130 GetPrivateProfileStringA("Groups", key, "", szPath,
131 sizeof(szPath), Globals.lpszIniFile);
132 if (!szPath[0]) continue;
134 GRPFILE_ReadGroupFile(szPath);
136 ptr += skip;
138 /* FIXME initialize other groups, not enumerated by `Order' */
141 /***********************************************************************
143 * MAIN_AutoStart
146 VOID MAIN_AutoStart(void)
148 CHAR buffer[BUFFER_SIZE];
149 HLOCAL hGroup, hProgram;
151 GetPrivateProfileStringA("Settings", "AutoStart", "Autostart", buffer,
152 sizeof(buffer), Globals.lpszIniFile);
154 for (hGroup = GROUP_FirstGroup(); hGroup; hGroup = GROUP_NextGroup(hGroup))
155 if (!lstrcmpA(buffer, GROUP_GroupName(hGroup)))
156 for (hProgram = PROGRAM_FirstProgram(hGroup); hProgram;
157 hProgram = PROGRAM_NextProgram(hProgram))
158 PROGRAM_ExecuteProgram(hProgram);
161 /***********************************************************************
163 * MAIN_MainWndProc
166 static LRESULT CALLBACK MAIN_MainWndProc(HWND hWnd, UINT msg,
167 WPARAM wParam, LPARAM lParam)
169 switch (msg)
171 case WM_INITMENU:
172 CheckMenuItem(Globals.hOptionMenu, PM_AUTO_ARRANGE,
173 MF_BYCOMMAND | (Globals.bAutoArrange ? MF_CHECKED : MF_UNCHECKED));
174 CheckMenuItem(Globals.hOptionMenu, PM_MIN_ON_RUN,
175 MF_BYCOMMAND | (Globals.bMinOnRun ? MF_CHECKED : MF_UNCHECKED));
176 CheckMenuItem(Globals.hOptionMenu, PM_SAVE_SETTINGS,
177 MF_BYCOMMAND | (Globals.bSaveSettings ? MF_CHECKED : MF_UNCHECKED));
178 break;
180 case WM_COMMAND:
181 if (LOWORD(wParam) < PM_FIRST_CHILD){
182 MAIN_MenuCommand(hWnd, LOWORD(wParam), lParam);
184 break;
186 case WM_DESTROY:
187 PostQuitMessage (0);
188 break;
190 return DefFrameProcW(hWnd, Globals.hMDIWnd, msg, wParam, lParam);
193 /***********************************************************************
195 * MAIN_MenuCommand
198 static VOID MAIN_MenuCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
200 HLOCAL hActiveGroup = GROUP_ActiveGroup();
201 HLOCAL hActiveProgram = PROGRAM_ActiveProgram(hActiveGroup);
202 HWND hActiveGroupWnd = GROUP_GroupWnd(hActiveGroup);
204 switch(wParam)
206 /* Menu File */
207 case PM_NEW:
208 switch (DIALOG_New((hActiveGroupWnd && !IsIconic(hActiveGroupWnd)) ?
209 PM_NEW_PROGRAM : PM_NEW_GROUP))
211 case PM_NEW_PROGRAM:
212 if (hActiveGroup) PROGRAM_NewProgram(hActiveGroup);
213 break;
215 case PM_NEW_GROUP:
216 GROUP_NewGroup();
217 break;
219 break;
221 case PM_OPEN:
222 if (hActiveProgram)
223 PROGRAM_ExecuteProgram(hActiveProgram);
224 else if (hActiveGroupWnd)
225 OpenIcon(hActiveGroupWnd);
226 break;
228 case PM_MOVE:
229 case PM_COPY:
230 if (hActiveProgram)
231 PROGRAM_CopyMoveProgram(hActiveProgram, wParam == PM_MOVE);
232 break;
234 case PM_DELETE:
235 if (hActiveProgram)
237 if (DIALOG_Delete(IDS_DELETE_PROGRAM_s, PROGRAM_ProgramName(hActiveProgram)))
238 PROGRAM_DeleteProgram(hActiveProgram, TRUE);
240 else if (hActiveGroup)
242 if (DIALOG_Delete(IDS_DELETE_GROUP_s, GROUP_GroupName(hActiveGroup)))
243 GROUP_DeleteGroup(hActiveGroup);
245 break;
247 case PM_ATTRIBUTES:
248 if (hActiveProgram)
249 PROGRAM_ModifyProgram(hActiveProgram);
250 else if (hActiveGroup)
251 GROUP_ModifyGroup(hActiveGroup);
252 break;
254 case PM_EXECUTE:
255 DIALOG_Execute();
256 break;
258 case PM_EXIT:
259 PostQuitMessage(0);
260 break;
262 /* Menu Options */
263 case PM_AUTO_ARRANGE:
264 Globals.bAutoArrange = !Globals.bAutoArrange;
265 CheckMenuItem(Globals.hOptionMenu, PM_AUTO_ARRANGE,
266 MF_BYCOMMAND | (Globals.bAutoArrange ?
267 MF_CHECKED : MF_UNCHECKED));
268 WritePrivateProfileStringA("Settings", "AutoArrange",
269 Globals.bAutoArrange ? "1" : "0",
270 Globals.lpszIniFile);
271 WritePrivateProfileStringA(NULL,NULL,NULL,Globals.lpszIniFile); /* flush it */
272 break;
274 case PM_MIN_ON_RUN:
275 Globals.bMinOnRun = !Globals.bMinOnRun;
276 CheckMenuItem(Globals.hOptionMenu, PM_MIN_ON_RUN,
277 MF_BYCOMMAND | (Globals.bMinOnRun ?
278 MF_CHECKED : MF_UNCHECKED));
279 WritePrivateProfileStringA("Settings", "MinOnRun",
280 Globals.bMinOnRun ? "1" : "0",
281 Globals.lpszIniFile);
282 WritePrivateProfileStringA(NULL,NULL,NULL,Globals.lpszIniFile); /* flush it */
283 break;
285 case PM_SAVE_SETTINGS:
286 Globals.bSaveSettings = !Globals.bSaveSettings;
287 CheckMenuItem(Globals.hOptionMenu, PM_SAVE_SETTINGS,
288 MF_BYCOMMAND | (Globals.bSaveSettings ?
289 MF_CHECKED : MF_UNCHECKED));
290 WritePrivateProfileStringA("Settings", "SaveSettings",
291 Globals.bSaveSettings ? "1" : "0",
292 Globals.lpszIniFile);
293 WritePrivateProfileStringA(NULL,NULL,NULL,Globals.lpszIniFile); /* flush it */
294 break;
296 /* Menu Windows */
297 case PM_OVERLAP:
298 SendMessageW(Globals.hMDIWnd, WM_MDICASCADE, 0, 0);
299 break;
301 case PM_SIDE_BY_SIDE:
302 SendMessageW(Globals.hMDIWnd, WM_MDITILE, MDITILE_VERTICAL, 0);
303 break;
305 case PM_ARRANGE:
307 if (hActiveGroupWnd && !IsIconic(hActiveGroupWnd))
308 ArrangeIconicWindows(hActiveGroupWnd);
309 else
310 SendMessageW(Globals.hMDIWnd, WM_MDIICONARRANGE, 0, 0);
311 break;
313 /* Menu Help */
314 case PM_CONTENTS:
315 if (!WinHelpA(Globals.hMainWnd, "progman.hlp", HELP_CONTENTS, 0))
316 MAIN_MessageBoxIDS(IDS_WINHELP_ERROR, IDS_ERROR, MB_OK);
317 break;
319 case PM_ABOUT_WINE:
320 ShellAboutA(hWnd, "WINE", "Program Manager", 0);
321 break;
323 default:
324 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
325 break;
329 /***********************************************************************
331 * MAIN_RegisterMainWinClass
334 static ATOM MAIN_RegisterMainWinClass(void)
336 WNDCLASSW class;
338 class.style = CS_HREDRAW | CS_VREDRAW;
339 class.lpfnWndProc = MAIN_MainWndProc;
340 class.cbClsExtra = 0;
341 class.cbWndExtra = 0;
342 class.hInstance = Globals.hInstance;
343 class.hIcon = Globals.hMainIcon;
344 class.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW);
345 class.hbrBackground = GetStockObject (NULL_BRUSH);
346 class.lpszMenuName = 0;
347 class.lpszClassName = STRING_MAIN_WIN_CLASS_NAME;
349 return RegisterClassW(&class);
352 /***********************************************************************
354 * MAIN_CreateMainWindow
357 static VOID MAIN_CreateMainWindow(void)
359 INT left , top, right, bottom, width, height, show;
360 CHAR buffer[100];
362 Globals.hMDIWnd = 0;
363 Globals.hMainMenu = 0;
365 /* Get the geometry of the main window */
366 GetPrivateProfileStringA("Settings", "Window", "", buffer, sizeof(buffer), Globals.lpszIniFile);
367 if (5 == sscanf(buffer, "%d %d %d %d %d", &left, &top, &right, &bottom, &show))
369 width = right - left;
370 height = bottom - top;
372 else
374 left = top = width = height = CW_USEDEFAULT;
375 show = SW_SHOWNORMAL;
378 /* Create main Window */
379 Globals.hMainWnd =
380 CreateWindowW(STRING_MAIN_WIN_CLASS_NAME, NULL,
381 WS_OVERLAPPEDWINDOW, left, top, width, height,
382 0, 0, Globals.hInstance, 0);
384 ShowWindow (Globals.hMainWnd, show);
385 UpdateWindow (Globals.hMainWnd);
388 /***********************************************************************
390 * MAIN_CreateMDIWindow
393 static VOID MAIN_CreateMDIWindow(void)
395 CLIENTCREATESTRUCT ccs;
396 RECT rect;
398 /* Get the geometry of the MDI window */
399 GetClientRect(Globals.hMainWnd, &rect);
401 ccs.hWindowMenu = Globals.hWindowsMenu;
402 ccs.idFirstChild = PM_FIRST_CHILD;
404 /* Create MDI Window */
405 Globals.hMDIWnd =
406 CreateWindowW(STRING_MDI_WIN_CLASS_NAME, NULL,
407 WS_CHILD, rect.left, rect.top,
408 rect.right - rect.left, rect.bottom - rect.top,
409 Globals.hMainWnd, 0,
410 Globals.hInstance, &ccs);
412 ShowWindow (Globals.hMDIWnd, SW_SHOW);
413 UpdateWindow (Globals.hMDIWnd);
416 /**********************************************************************/
417 /***********************************************************************
419 * MAIN_MessageBoxIDS
421 INT MAIN_MessageBoxIDS(UINT ids_text, UINT ids_title, WORD type)
423 CHAR text[MAX_STRING_LEN];
424 CHAR title[MAX_STRING_LEN];
426 LoadStringA(Globals.hInstance, ids_text, text, sizeof(text));
427 LoadStringA(Globals.hInstance, ids_title, title, sizeof(title));
429 return(MessageBoxA(Globals.hMainWnd, text, title, type));
432 /***********************************************************************
434 * MAIN_MessageBoxIDS_s
436 INT MAIN_MessageBoxIDS_s(UINT ids_text, LPCSTR str, UINT ids_title, WORD type)
438 CHAR text[MAX_STRING_LEN];
439 CHAR title[MAX_STRING_LEN];
440 CHAR newtext[MAX_STRING_LEN + MAX_PATHNAME_LEN];
442 LoadStringA(Globals.hInstance, ids_text, text, sizeof(text));
443 LoadStringA(Globals.hInstance, ids_title, title, sizeof(title));
444 wsprintfA(newtext, text, str);
446 return(MessageBoxA(Globals.hMainWnd, newtext, title, type));
449 /***********************************************************************
451 * MAIN_ReplaceString
454 VOID MAIN_ReplaceString(HLOCAL *handle, LPSTR replace)
456 HLOCAL newhandle = LocalAlloc(LMEM_FIXED, strlen(replace) + 1);
457 if (newhandle)
459 LPSTR newstring = LocalLock(newhandle);
460 strcpy(newstring, replace);
461 LocalFree(*handle);
462 *handle = newhandle;
464 else MAIN_MessageBoxIDS(IDS_OUT_OF_MEMORY, IDS_ERROR, MB_OK);