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