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