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