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