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