dwrite: Implement GetWeight() for IDWriteFont.
[wine] / programs / 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 #include <stdio.h>
23 #include <string.h>
24
25 #define OEMRESOURCE
26
27 #include "windows.h"
28 #include "shellapi.h"
29 #include "progman.h"
30
31 GLOBALS Globals;
32
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);
39
40 #define BUFFER_SIZE 1000
41
42 /***********************************************************************
43  *
44  *           WinMain
45  */
46
47 int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
48 {
49   MSG      msg;
50
51   Globals.lpszIniFile         = "progman.ini";
52   Globals.lpszIcoFile         = "progman.ico";
53
54   Globals.hInstance           = hInstance;
55   Globals.hGroups             = 0;
56   Globals.hActiveGroup        = 0;
57
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);
65
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);
73
74   /* Register classes */
75   if (!prev)
76     {
77       if (!MAIN_RegisterMainWinClass()) return(FALSE);
78       if (!GROUP_RegisterGroupWinClass()) return(FALSE);
79       if (!PROGRAM_RegisterProgramWinClass()) return(FALSE);
80     }
81
82   /* Create main window */
83   MAIN_CreateMainWindow();
84   Globals.hAccel = LoadAcceleratorsW(Globals.hInstance, MAKEINTRESOURCEW(IDA_ACCEL));
85
86   /* Setup menu, stringtable and resourcenames */
87   STRING_LoadMenus();
88
89   MAIN_CreateMDIWindow();
90
91   /* Initialize groups */
92   MAIN_CreateGroups();
93
94   /* Start initial applications */
95   MAIN_AutoStart();
96
97   /* Message loop */
98   while (GetMessageW (&msg, 0, 0, 0))
99     if (!TranslateAcceleratorW(Globals.hMainWnd, Globals.hAccel, &msg))
100       {
101         TranslateMessage (&msg);
102         DispatchMessageW (&msg);
103       }
104   return 0;
105 }
106
107 /***********************************************************************
108  *
109  *           MAIN_CreateGroups
110  */
111
112 static VOID MAIN_CreateGroups(void)
113 {
114   CHAR buffer[BUFFER_SIZE];
115   CHAR szPath[MAX_PATHNAME_LEN];
116   CHAR key[20], *ptr;
117
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))
122     {
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;
128
129       sprintf(key, "Group%d", num);
130       GetPrivateProfileStringA("Groups", key, "", szPath,
131                               sizeof(szPath), Globals.lpszIniFile);
132       if (!szPath[0]) continue;
133
134       GRPFILE_ReadGroupFile(szPath);
135
136       ptr += skip;
137     }
138   /* FIXME initialize other groups, not enumerated by `Order' */
139 }
140
141 /***********************************************************************
142  *
143  *           MAIN_AutoStart
144  */
145
146 VOID MAIN_AutoStart(void)
147 {
148   CHAR buffer[BUFFER_SIZE];
149   HLOCAL hGroup, hProgram;
150
151   GetPrivateProfileStringA("Settings", "AutoStart", "Autostart", buffer,
152                           sizeof(buffer), Globals.lpszIniFile);
153
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);
159 }
160
161 /***********************************************************************
162  *
163  *           MAIN_MainWndProc
164  */
165
166 static LRESULT CALLBACK MAIN_MainWndProc(HWND hWnd, UINT msg,
167                                  WPARAM wParam, LPARAM lParam)
168 {
169   switch (msg)
170     {
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;
179
180     case WM_COMMAND:
181       if (LOWORD(wParam) < PM_FIRST_CHILD){
182         MAIN_MenuCommand(hWnd, LOWORD(wParam), lParam);
183       }
184       break;
185
186     case WM_DESTROY:
187       PostQuitMessage (0);
188       break;
189     }
190   return DefFrameProcW(hWnd, Globals.hMDIWnd, msg, wParam, lParam);
191 }
192
193 /***********************************************************************
194  *
195  *           MAIN_MenuCommand
196  */
197
198 static VOID MAIN_MenuCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
199 {
200   HLOCAL hActiveGroup    = GROUP_ActiveGroup();
201   HLOCAL hActiveProgram  = PROGRAM_ActiveProgram(hActiveGroup);
202   HWND   hActiveGroupWnd = GROUP_GroupWnd(hActiveGroup);
203
204   switch(wParam)
205     {
206       /* Menu File */
207     case PM_NEW:
208       switch (DIALOG_New((hActiveGroupWnd && !IsIconic(hActiveGroupWnd)) ?
209                          PM_NEW_PROGRAM : PM_NEW_GROUP))
210       {
211       case PM_NEW_PROGRAM:
212         if (hActiveGroup) PROGRAM_NewProgram(hActiveGroup);
213         break;
214
215       case PM_NEW_GROUP:
216         GROUP_NewGroup();
217         break;
218       }
219       break;
220
221     case PM_OPEN:
222       if (hActiveProgram)
223         PROGRAM_ExecuteProgram(hActiveProgram);
224       else if (hActiveGroupWnd)
225         OpenIcon(hActiveGroupWnd);
226       break;
227
228     case PM_MOVE:
229     case PM_COPY:
230       if (hActiveProgram)
231         PROGRAM_CopyMoveProgram(hActiveProgram, wParam == PM_MOVE);
232       break;
233
234     case PM_DELETE:
235       if (hActiveProgram)
236         {
237         if (DIALOG_Delete(IDS_DELETE_PROGRAM_s, PROGRAM_ProgramName(hActiveProgram)))
238           PROGRAM_DeleteProgram(hActiveProgram, TRUE);
239         }
240       else if (hActiveGroup)
241         {
242         if (DIALOG_Delete(IDS_DELETE_GROUP_s, GROUP_GroupName(hActiveGroup)))
243           GROUP_DeleteGroup(hActiveGroup);
244         }
245       break;
246
247     case PM_ATTRIBUTES:
248       if (hActiveProgram)
249         PROGRAM_ModifyProgram(hActiveProgram);
250       else if (hActiveGroup)
251         GROUP_ModifyGroup(hActiveGroup);
252       break;
253
254     case PM_EXECUTE:
255       DIALOG_Execute();
256       break;
257
258     case PM_EXIT:
259       PostQuitMessage(0);
260       break;
261
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;
273
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;
284
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;
295
296       /* Menu Windows */
297     case PM_OVERLAP:
298       SendMessageW(Globals.hMDIWnd, WM_MDICASCADE, 0, 0);
299       break;
300
301     case PM_SIDE_BY_SIDE:
302       SendMessageW(Globals.hMDIWnd, WM_MDITILE, MDITILE_VERTICAL, 0);
303       break;
304
305     case PM_ARRANGE:
306
307       if (hActiveGroupWnd && !IsIconic(hActiveGroupWnd))
308         ArrangeIconicWindows(hActiveGroupWnd);
309       else
310         SendMessageW(Globals.hMDIWnd, WM_MDIICONARRANGE, 0, 0);
311       break;
312
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;
318
319     case PM_ABOUT_WINE:
320       ShellAboutA(hWnd, "WINE", "Program Manager", 0);
321       break;
322
323     default:
324         MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
325       break;
326     }
327 }
328
329 /***********************************************************************
330  *
331  *           MAIN_RegisterMainWinClass
332  */
333
334 static ATOM MAIN_RegisterMainWinClass(void)
335 {
336   WNDCLASSW class;
337
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;
348
349   return RegisterClassW(&class);
350 }
351
352 /***********************************************************************
353  *
354  *           MAIN_CreateMainWindow
355  */
356
357 static VOID MAIN_CreateMainWindow(void)
358 {
359   INT  left , top, right, bottom, width, height, show;
360   CHAR buffer[100];
361
362   Globals.hMDIWnd   = 0;
363   Globals.hMainMenu = 0;
364
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))
368   {
369     width  = right - left;
370     height = bottom - top;
371   }
372   else
373   {
374     left = top = width = height = CW_USEDEFAULT;
375     show = SW_SHOWNORMAL;
376   }
377
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);
383
384   ShowWindow (Globals.hMainWnd, show);
385   UpdateWindow (Globals.hMainWnd);
386 }
387
388 /***********************************************************************
389  *
390  *           MAIN_CreateMDIWindow
391  */
392
393 static VOID MAIN_CreateMDIWindow(void)
394 {
395   CLIENTCREATESTRUCT ccs;
396   RECT rect;
397
398   /* Get the geometry of the MDI window */
399   GetClientRect(Globals.hMainWnd, &rect);
400
401   ccs.hWindowMenu  = Globals.hWindowsMenu;
402   ccs.idFirstChild = PM_FIRST_CHILD;
403
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);
411
412   ShowWindow (Globals.hMDIWnd, SW_SHOW);
413   UpdateWindow (Globals.hMDIWnd);
414 }
415
416 /**********************************************************************/
417 /***********************************************************************
418  *
419  *           MAIN_MessageBoxIDS
420  */
421 INT MAIN_MessageBoxIDS(UINT ids_text, UINT ids_title, WORD type)
422 {
423   CHAR text[MAX_STRING_LEN];
424   CHAR title[MAX_STRING_LEN];
425
426   LoadStringA(Globals.hInstance, ids_text, text, sizeof(text));
427   LoadStringA(Globals.hInstance, ids_title, title, sizeof(title));
428
429   return(MessageBoxA(Globals.hMainWnd, text, title, type));
430 }
431
432 /***********************************************************************
433  *
434  *           MAIN_MessageBoxIDS_s
435  */
436 INT MAIN_MessageBoxIDS_s(UINT ids_text, LPCSTR str, UINT ids_title, WORD type)
437 {
438   CHAR text[MAX_STRING_LEN];
439   CHAR title[MAX_STRING_LEN];
440   CHAR newtext[MAX_STRING_LEN + MAX_PATHNAME_LEN];
441
442   LoadStringA(Globals.hInstance, ids_text, text, sizeof(text));
443   LoadStringA(Globals.hInstance, ids_title, title, sizeof(title));
444   wsprintfA(newtext, text, str);
445
446   return(MessageBoxA(Globals.hMainWnd, newtext, title, type));
447 }
448
449 /***********************************************************************
450  *
451  *           MAIN_ReplaceString
452  */
453
454 VOID MAIN_ReplaceString(HLOCAL *handle, LPSTR replace)
455 {
456   HLOCAL newhandle = LocalAlloc(LMEM_FIXED, strlen(replace) + 1);
457   if (newhandle)
458     {
459       LPSTR  newstring = LocalLock(newhandle);
460       strcpy(newstring, replace);
461       LocalFree(*handle);
462       *handle = newhandle;
463     }
464   else MAIN_MessageBoxIDS(IDS_OUT_OF_MEMORY, IDS_ERROR, MB_OK);
465 }