Release 980726
[wine] / misc / tweak.c
1 /******************************************************************************
2  *
3  *   tweak.c
4  *
5  *   Windows 95 style interface tweaks.
6  *   Copyright (c) 1997 Dave Cuthbert.
7  *
8  *   FIXME:  This file is, unfortunately, aptly named:  the method of
9  *   displaying Win95 style windows is a tweak.  Lots of stuff does not yet
10  *   work -- and probably never will unless some of this code is
11  *   incorporated into the mainstream Wine code.
12  *
13  *   DEVELOPERS, PLEASE NOTE:  Before delving into the mainstream code and
14  *   altering it, consider how your changes will affect the Win3.1 interface
15  *   (which has taken a major effort to create!).  After you make any sort of
16  *   non-trivial change, *test* the Wine code running in Win3.1 mode!  The
17  *   object here is to make it so that the person who tests the latest version
18  *   of Wine without adding the tweaks into wine.conf notices nothing out of
19  *   the ordinary.
20  *
21  *   Revision history
22  *        03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
23  *             Original implementation.
24  *
25  *****************************************************************************/
26
27 #include <malloc.h>
28 #include "ts_xlib.h"
29 #include <string.h>
30 #include "dc.h"
31 #include "debug.h"
32 #include "graphics.h"
33 #include "options.h"
34 #include "stackframe.h"
35 #include "tweak.h"
36 #include "windows.h"
37
38 /* Parameters for windows/nonclient.c */
39 extern int  NC_MaxControlNudge;
40 extern int  NC_MinControlNudge;
41 extern UINT32  NC_CaptionTextFlags;
42
43 /* Parameters for controls/menu.c */
44 extern UINT32  MENU_BarItemTopNudge;
45 extern UINT32  MENU_BarItemLeftNudge;
46 extern UINT32  MENU_ItemTopNudge;
47 extern UINT32  MENU_ItemLeftNudge;
48 extern UINT32  MENU_HighlightTopNudge;
49 extern UINT32  MENU_HighlightLeftNudge;
50 extern UINT32  MENU_HighlightBottomNudge;
51 extern UINT32  MENU_HighlightRightNudge;
52
53 /* General options */
54 HPEN32  TWEAK_PenFF95;
55 HPEN32  TWEAK_PenE095;
56 HPEN32  TWEAK_PenC095;
57 HPEN32  TWEAK_Pen8095;
58 HPEN32  TWEAK_Pen0095;
59
60 #if defined(WIN_95_LOOK)
61 int  TWEAK_Win95Look = 1;
62 #else
63 int  TWEAK_Win95Look = 0;
64 #endif
65
66 int  TWEAK_WineInitialized = 0;
67
68
69 /******************************************************************************
70  *
71  *   int  TWEAK_MenuInit()
72  * 
73  *   Initializes the Win95 tweaks to the menu code.  See controls/menu.c.
74  *   Return value indicates success (non-zero) or failure.
75  *
76  *   Revision history
77  *        06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
78  *             Original implementation.
79  *
80  *****************************************************************************/
81
82 static int  TWEAK_MenuInit()
83 {
84     MENU_BarItemTopNudge =
85         PROFILE_GetWineIniInt("Tweak.Layout", "MenuBarItemTopNudge", 0);
86     MENU_BarItemLeftNudge =
87         PROFILE_GetWineIniInt("Tweak.Layout", "MenuBarItemLeftNudge", 0);
88     MENU_ItemTopNudge =
89         PROFILE_GetWineIniInt("Tweak.Layout", "MenuItemTopNudge", 0);
90     MENU_ItemLeftNudge =
91         PROFILE_GetWineIniInt("Tweak.Layout", "MenuItemLeftNudge", 0);
92     MENU_HighlightTopNudge =
93         PROFILE_GetWineIniInt("Tweak.Layout", "MenuHighlightTopNudge", 0);
94     MENU_HighlightLeftNudge =
95         PROFILE_GetWineIniInt("Tweak.Layout", "MenuHighlightLeftNudge", 0);
96     MENU_HighlightBottomNudge =
97         PROFILE_GetWineIniInt("Tweak.Layout", "MenuHighlightBottomNudge", 0);
98     MENU_HighlightRightNudge =
99         PROFILE_GetWineIniInt("Tweak.Layout", "MenuHighlightRightNudge", 0);
100
101     return 1;
102 }
103
104
105 /******************************************************************************
106  *
107  *   int  TWEAK_NonClientInit()
108  *
109  *   Initializes the Win95 tweaks to the non-client drawing functions.  See
110  *   windows/nonclient.c.  Return value indicates success (non-zero) or
111  *   failure.
112  *
113  *   Revision history
114  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
115  *             Original implementation.
116  *
117  *****************************************************************************/
118
119 static int  TWEAK_NonClientInit()
120 {
121     char  key_value[2];
122
123     NC_MaxControlNudge =
124         PROFILE_GetWineIniInt("Tweak.Layout", "MaxControlNudge", 0);
125     NC_MinControlNudge =
126         PROFILE_GetWineIniInt("Tweak.Layout", "MinControlNudge", 0);
127
128     NC_CaptionTextFlags = DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX;
129
130     PROFILE_GetWineIniString("Tweak.Layout", "CaptionAlignment", 
131                              TWEAK_Win95Look ? "l" : "c", key_value, 2);
132
133     switch(key_value[0]) {
134     case 'l':
135     case 'L':
136         NC_CaptionTextFlags |= DT_LEFT;
137         break;
138
139     case 'r':
140     case 'R':
141         NC_CaptionTextFlags |= DT_RIGHT;
142         break;
143
144     default:
145         NC_CaptionTextFlags |= DT_CENTER;
146     }
147
148     return 1;
149 }
150
151
152 /******************************************************************************
153  *
154  *   int  TWEAK_VarInit()
155  *
156  *   Initializes the miscellaneous variables which are used in the tweak
157  *   routines.  Return value is non-zero on success.
158  *
159  *   Revision history
160  *        07-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
161  *             Original implementation.
162  *
163  *****************************************************************************/
164
165 static int  TWEAK_VarInit()
166 {
167     TWEAK_Win95Look = PROFILE_GetWineIniBool("Tweak.Layout", "Win95Look", 0);
168
169     /* FIXME: Each color should really occupy a single entry in the wine.conf
170        file, but I couldn't settle on a good (intuitive!) format. */
171
172     TWEAK_PenFF95 = CreatePen32(
173         PS_SOLID, 1,
174         RGB(PROFILE_GetWineIniInt("Tweak.Colors", "PenFF95.Red", 0xff),
175             PROFILE_GetWineIniInt("Tweak.Colors", "PenFF95.Grn", 0xff),
176             PROFILE_GetWineIniInt("Tweak.Colors", "PenFF95.Blu", 0xff)));
177     TWEAK_PenE095 = CreatePen32(
178         PS_SOLID, 1,
179         RGB(PROFILE_GetWineIniInt("Tweak.Colors", "PenE095.Red", 0xe0),
180             PROFILE_GetWineIniInt("Tweak.Colors", "PenE095.Grn", 0xe0),
181             PROFILE_GetWineIniInt("Tweak.Colors", "PenE095.Blu", 0xe0)));
182     TWEAK_PenC095 = CreatePen32(
183         PS_SOLID, 1,
184         RGB(PROFILE_GetWineIniInt("Tweak.Colors", "PenC095.Red", 0xc0),
185             PROFILE_GetWineIniInt("Tweak.Colors", "PenC095.Grn", 0xc0),
186             PROFILE_GetWineIniInt("Tweak.Colors", "PenC095.Blu", 0xc0)));
187     TWEAK_Pen8095 = CreatePen32(
188         PS_SOLID, 1,
189         RGB(PROFILE_GetWineIniInt("Tweak.Colors", "Pen8095.Red", 0x80),
190             PROFILE_GetWineIniInt("Tweak.Colors", "Pen8095.Grn", 0x80),
191             PROFILE_GetWineIniInt("Tweak.Colors", "Pen8095.Blu", 0x80)));
192     TWEAK_Pen0095 = CreatePen32(
193         PS_SOLID, 1,
194         RGB(PROFILE_GetWineIniInt("Tweak.Colors", "Pen0095.Red", 0x00),
195             PROFILE_GetWineIniInt("Tweak.Colors", "Pen0095.Grn", 0x00),
196             PROFILE_GetWineIniInt("Tweak.Colors", "Pen0095.Blu", 0x00)));
197
198     TRACE(tweak, "Using %s look and feel.\n",
199                  TWEAK_Win95Look ? "Win95" : "Win3.1");
200     return 1;
201 }
202
203
204 /******************************************************************************
205  *
206  *   int  TWEAK_Init()
207  *
208  *   Does the full initialization of the Win95 tweak subsystem.  Return value
209  *   indicates success.  Called by loader/main.c's MAIN_Init().
210  *
211  *   Revision history
212  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
213  *             Original implementation.
214  *
215  *****************************************************************************/
216
217 int  TWEAK_Init()
218 {
219     TWEAK_VarInit();
220     TWEAK_NonClientInit();
221     TWEAK_MenuInit();
222     return 1;
223 }
224
225
226 /******************************************************************************
227  *
228  *   int  TWEAK_CheckConfiguration()
229  *
230  *   Examines wine.conf for old/bad entries and recommends changes to the user.
231  *
232  *   Revision history
233  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
234  *             Original implementation.
235  *
236  *****************************************************************************/
237
238 int  TWEAK_CheckConfiguration()
239 {
240     return 1;
241 }
242
243
244 /******************************************************************************
245  *
246  *     Tweak graphic subsystem.
247  *
248  *****************************************************************************/
249
250 /******************************************************************************
251  *
252  *   void  TWEAK_DrawReliefRect95(
253  *      HDC32  hdc,               // Device context on which to draw
254  *      RECT32 const  *rect )     // Rectangle to use
255  *
256  *   Draws the double-bordered Win95-style relief rectangle.
257  *
258  *   Bugs
259  *        There are some checks missing from this function.  Perhaps the
260  *        SelectObject32 calls should be examined?  Hasn't failed on me (yet).
261  *
262  *        Should I really be calling X functions directly from here?  It is
263  *        an optimization, but should I be optimizing alpha code?  Probably
264  *        not.
265  *
266  *   Revision history
267  *        08-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
268  *             Original implementation.
269  *
270  *****************************************************************************/
271
272 void  TWEAK_DrawReliefRect95(
273     HDC32  hdc,
274     RECT32 const  *rect )
275 {
276     DC  *dc;
277     HPEN32  prevpen;
278
279     if((dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC))) {
280
281         /* Draw the top/left lines first */
282         prevpen = SelectObject32(hdc, TWEAK_PenE095);
283         DC_SetupGCForPen(dc);
284         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left, rect->top,
285                   rect->right - 1, rect->top);
286         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left, rect->top,
287                   rect->left, rect->bottom - 1);
288
289         SelectObject32(hdc, TWEAK_PenFF95);
290         DC_SetupGCForPen(dc);
291         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1,
292                   rect->top + 1, rect->right - 2, rect->top + 1);
293         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1,
294                   rect->top + 1, rect->left + 1, rect->bottom - 2);
295
296
297         /* Now the bottom/right lines */
298         SelectObject32(hdc, TWEAK_Pen0095);
299         DC_SetupGCForPen(dc);
300         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left,
301                   rect->bottom - 1, rect->right - 1, rect->bottom - 1);
302         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->right - 1,
303                   rect->top, rect->right - 1, rect->bottom - 1);
304
305         SelectObject32(hdc, TWEAK_Pen8095);
306         DC_SetupGCForPen(dc);
307         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1,
308                   rect->bottom - 2, rect->right - 2, rect->bottom - 2);
309         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->right - 2,
310                   rect->top + 1, rect->right - 2, rect->bottom - 2);
311         
312         SelectObject32(hdc, prevpen);
313     }
314
315     return;
316 }
317
318
319 /******************************************************************************
320  *
321  *   void  TWEAK_DrawRevReliefRect95(
322  *      HDC32  hdc,               // Device context on which to draw
323  *      RECT32 const  *rect )     // Rectangle to use
324  *
325  *   Draws the double-bordered Win95-style relief rectangle.
326  *
327  *   Bugs
328  *        There are some checks missing from this function.  Perhaps the
329  *        SelectObject32 calls should be examined?  Hasn't failed on me (yet).
330  *
331  *        Should I really be calling X functions directly from here?  It is
332  *        an optimization, but should I be optimizing alpha code?  Probably
333  *        not.
334  *
335  *   Revision history
336  *        08-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
337  *             Original implementation.
338  *
339  *****************************************************************************/
340
341 void  TWEAK_DrawRevReliefRect95(
342     HDC32  hdc,
343     RECT32 const  *rect )
344 {
345     DC  *dc;
346     HPEN32  prevpen;
347
348     if((dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC))) {
349
350         /* Draw the top/left lines first */
351         prevpen = SelectObject32(hdc, TWEAK_Pen8095);
352         DC_SetupGCForPen(dc);
353         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left, rect->top,
354                   rect->right - 1, rect->top);
355         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left, rect->top,
356                   rect->left, rect->bottom - 1);
357
358         SelectObject32(hdc, TWEAK_Pen0095);
359         DC_SetupGCForPen(dc);
360         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1,
361                   rect->top + 1, rect->right - 2, rect->top + 1);
362         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1,
363                   rect->top + 1, rect->left + 1, rect->bottom - 2);
364
365
366         /* Now the bottom/right lines */
367         SelectObject32(hdc, TWEAK_PenFF95);
368         DC_SetupGCForPen(dc);
369         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left,
370                   rect->bottom - 1, rect->right - 1, rect->bottom - 1);
371         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->right - 1,
372                   rect->top, rect->right - 1, rect->bottom - 1);
373
374         SelectObject32(hdc, TWEAK_PenE095);
375         DC_SetupGCForPen(dc);
376         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1,
377                   rect->bottom - 2, rect->right - 2, rect->bottom - 2);
378         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->right - 2,
379                   rect->top + 1, rect->right - 2, rect->bottom - 2);
380         
381         SelectObject32(hdc, prevpen);
382     }
383
384     return;
385 }
386
387
388
389 /******************************************************************************
390  *
391  *   void  TWEAK_DrawMenuSeparatorHoriz95(
392  *      HDC32  hdc,               // Device context on which to draw
393  *      UINT32  xc1,              // Left x-coordinate
394  *      UINT32  yc,               // Y-coordinate of the LOWER line
395  *      UINT32  xc2 )             // Right x-coordinate
396  *
397  *   Draws a horizontal menu separator bar Win 95 style.
398  *
399  *   Bugs
400  *        Same as those for DrawReliefRect95.
401  *
402  *   Revision history
403  *        08-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
404  *             Original implementation.
405  *        11-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
406  *             Changed name from DrawMenuSeparator95
407  *
408  *****************************************************************************/
409
410 void  TWEAK_DrawMenuSeparatorHoriz95(
411     HDC32  hdc,
412     UINT32  xc1,
413     UINT32  yc,
414     UINT32  xc2 )
415 {
416     DC  *dc;
417     HPEN32  prevpen;
418
419     if((dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC))) {
420
421         /* Draw the top line */
422         prevpen = SelectObject32(hdc, TWEAK_Pen8095);
423         DC_SetupGCForPen(dc);
424         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, xc1, yc - 1, xc2,
425                   yc - 1);
426
427         /* And the bottom line */
428         SelectObject32(hdc, TWEAK_PenFF95);
429         DC_SetupGCForPen(dc);
430         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, xc1, yc, xc2, yc);
431
432         SelectObject32(hdc, prevpen);
433     }
434
435     return;
436 }
437
438
439 /******************************************************************************
440  *
441  *   void  TWEAK_DrawMenuSeparatorVert95(
442  *      HDC32  hdc,               // Device context on which to draw
443  *      UINT32  xc,               // X-coordinate of the RIGHT line
444  *      UINT32  yc1,              // top Y-coordinate
445  *      UINT32  yc2 )             // bottom Y-coordinate
446  *
447  *   Draws a vertical menu separator bar Win 95 style.
448  *
449  *   Bugs
450  *        Same as those for DrawReliefRect95.
451  *
452  *   Revision history
453  *        11-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
454  *             Original implementation.
455  *
456  *****************************************************************************/
457
458 void  TWEAK_DrawMenuSeparatorVert95(
459     HDC32  hdc,
460     UINT32  xc,
461     UINT32  yc1,
462     UINT32  yc2 )
463 {
464     DC  *dc;
465     HPEN32  prevpen;
466
467     if((dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC))) {
468
469         /* Draw the top line */
470         prevpen = SelectObject32(hdc, TWEAK_Pen8095);
471         DC_SetupGCForPen(dc);
472         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, xc, yc1, xc,
473                   yc2);
474
475         /* And the bottom line */
476         SelectObject32(hdc, TWEAK_PenFF95);
477         DC_SetupGCForPen(dc);
478         TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc, xc + 1, yc1, xc + 1,
479                   yc2);
480
481         SelectObject32(hdc, prevpen);
482     }
483
484     return;
485 }